Verificando acesso...

MÓDULO 4.4

🚪 Install gate: setup como state machine

O instalador não é um script que roda do zero ao fim — é uma máquina de estados que sabe onde parou, o que falta, e o que é opcional. Esse é o gate que evita o abismo do "instalei e agora?".

6
Tópicos
45
Minutos
Operador
Nível
Prático
Tipo
1

🧭 Conceito: setup como state machine

Instalador comum trata o setup como script linear: roda do início ao fim, e se quebrar no meio o user fica órfão. O install gate trata como state machine: cada execução pergunta "em que estado eu estou?", decide o próximo passo, executa, salva o novo estado. Re-rodar é seguro. Parar no meio é seguro. Voltar amanhã e continuar é a operação padrão.

🔀 O ciclo de cada execução

  ┌──────────────────────────────────────────────────────────────┐
  │                    install.sh inicia                         │
  └──────────────────────────────────────────────────────────────┘
                              │
                              ▼
              ┌─────────────────────────────┐
              │  Lê _install-state.json     │
              │  (cria se não existir)      │
              └─────────────────────────────┘
                              │
                              ▼
              ┌─────────────────────────────┐
              │  phase = ?                  │
              └─────────────────────────────┘
                              │
        ┌─────────────┬───────┴───────┬────────────────┐
        ▼             ▼               ▼                ▼
   [fresh]       [brand-ctx]    [skills-install]  [welcome]
        │             │               │                │
        ▼             ▼               ▼                ▼
   pergunta      coleta dados    instala skills    quick-win
   básicos       de marca        do catálogo       opcional
        │             │               │                │
        └─────────────┴───────┬───────┴────────────────┘
                              ▼
              ┌─────────────────────────────┐
              │  Marca passo como done      │
              │  Salva _install-state.json  │
              │  Imprime próximo passo      │
              └─────────────────────────────┘
                              │
                              ▼
                         [exit 0]
        
Idempotente

Rodar 100x = rodar 1x.

Resumable

Parou? Continua de onde parou.

Inspectável

O JSON conta a história.

Versionado

Migra entre versões do OS.

A virada conceitual: o instalador não é dono do tempo do user. Ele oferece passos, registra o que foi feito, sai limpo. O user volta quando quiser e o gate sabe exatamente onde retomar.

2

📦 _install-state.json: o schema completo

Um único arquivo na raiz do projeto carrega o estado. Pequeno, legível, versionado em git (ou em .gitignore se for por-máquina). É o contrato entre o instalador, os hooks e o próprio user.

_install-state.json (real, após 2ª fase)

{
  "version": "1.2.0",
  "schema": "iamasters-os/install-state/v1",
  "phase": "skills-install",
  "fresh": false,
  "started_at": "2026-05-18T20:11:43-03:00",
  "updated_at": "2026-05-18T20:38:09-03:00",
  "completed_steps": [
    {
      "id": "brand-context",
      "blocking": true,
      "completed_at": "2026-05-18T20:14:22-03:00",
      "artifact": "context/brand.md"
    },
    {
      "id": "claude-md-bootstrap",
      "blocking": true,
      "completed_at": "2026-05-18T20:16:01-03:00",
      "artifact": "CLAUDE.md"
    }
  ],
  "pending_steps": [
    { "id": "skills-install",      "blocking": true,  "estimated_minutes": 5 },
    { "id": "hooks-install",       "blocking": true,  "estimated_minutes": 3 },
    { "id": "welcome-quick-win",   "blocking": false, "estimated_minutes": 4 }
  ],
  "skipped_steps": [],
  "machine": {
    "os": "linux",
    "shell": "bash",
    "claude_code_version": "2.5.1"
  }
}
        

📥 Campos obrigatórios

  • version — semver do OS instalado.
  • schema — versão do próprio schema.
  • phase — estado atual da máquina.
  • fresh — true só na 1ª execução.
  • completed_steps[] — auditoria.
  • pending_steps[] — roadmap restante.

📤 Campos opcionais úteis

  • skipped_steps[] — auditar o que foi pulado conscientemente.
  • machine.* — diagnóstico em suporte.
  • artifact — caminho do arquivo que o passo produziu.
  • estimated_minutes — expectativa pro user.

_install-state.template.json (canônico, no repo)

{
  "version": "1.2.0",
  "schema": "iamasters-os/install-state/v1",
  "phase": "brand-context",
  "fresh": true,
  "completed_steps": [],
  "pending_steps": [
    { "id": "brand-context",       "blocking": true,  "estimated_minutes": 6 },
    { "id": "claude-md-bootstrap", "blocking": true,  "estimated_minutes": 2 },
    { "id": "skills-install",      "blocking": true,  "estimated_minutes": 5 },
    { "id": "hooks-install",       "blocking": true,  "estimated_minutes": 3 },
    { "id": "welcome-quick-win",   "blocking": false, "estimated_minutes": 4 },
    { "id": "mcp-extras",          "blocking": false, "estimated_minutes": 5 }
  ],
  "skipped_steps": []
}
        

💡 Tip — o template é um contrato versionado

Mantenha o _install-state.template.json versionado em git. Toda mudança é PR. Quando o user faz upgrade da versão do OS, o instalador compara o state dele com o template novo e infere automaticamente os passos faltantes. Migração vira diff de JSON, não cirurgia.

3

🚦 Fases bloqueantes vs opcionais

Nem todo passo é igual. Alguns precisam acontecer antes do OS sequer funcionar (bloqueantes). Outros melhoram a experiência mas o sistema roda sem (opcionais). O install gate distingue os dois explicitamente — porque misturar gera o pior dos dois mundos: ou o user é forçado a coisas que não precisa, ou pula coisas que vão quebrar depois.

🔒 Bloqueantes — não pula

  • brand-context — sem isso o agente não sabe quem ele representa. Pergunta nome, tom, público, do/dont's. Vira context/brand.md.
  • claude-md-bootstrap — gera o CLAUDE.md raiz. Sem isso, nenhum hook ou skill carrega contexto certo.
  • skills-install — instala o set mínimo da trilha escolhida. Sem skills, é só LLM solto.
  • hooks-install — registra SessionStart e PostToolUse. Sem isso, o greeting nunca aparece.

🎁 Opcionais — pode pular

  • welcome-quick-win — gera 1 demo concreta em projects/welcome/. Pular não quebra nada, mas perde a "primeira vitória".
  • mcp-extras — instala MCPs adicionais (Gmail, Drive). Pode ser feito depois pelo catálogo.
  • analytics-opt-in — telemetria local. Default é off, pergunta uma vez.
  • seed-templates — copia templates de PRD/ADR. Útil mas trivial de adicionar depois.

📊 Por que separar importa

Dados de campo: em onboardings sem gate explícito, ~90% dos users abandonam entre os passos 3 e 5 — exatamente quando o instalador linear força tarefas opcionais misturadas com bloqueantes. O user perde paciência num passo que ele "achou que era opcional" e nunca volta.

Com gate separando os dois, a taxa de conclusão dos passos bloqueantes sobe pra ~85%, e os opcionais ficam disponíveis pro user pegar quando quiser, sem culpa.

Bloqueia

brand, claude.md, skills, hooks.

Opcional

welcome, mcp-extras, analytics.

Sinalizar

[obrigatório] vs [opcional] no prompt.

Skipável

--skip-optional flag.

4

🎉 Welcome quick-win: a 1ª vitória em <5min

Logo após os passos bloqueantes, o gate oferece uma demonstração concreta que prova o OS funciona pro caso real do user. Não é tutorial. Não é vídeo. É um artefato gerado com os dados que ele acabou de fornecer no brand-context, em <5min.

Estrutura de projects/welcome/ após o quick-win

projects/welcome/
├── README.md                  # "Sua primeira vitória — feita pelo OS"
├── brand-applied-demo.html    # landing com cores/tom do brand-context
├── prompt-usado.md            # transparência: o prompt que gerou o artefato
└── proximos-passos.md         # 3 sugestões de próximos projetos
        

✓ Quick-win bom

  • Usa dados reais do brand-context.
  • Gera artefato visível (HTML, PDF, doc).
  • Tem "abra esse arquivo" no final.
  • Roda em <5 minutos.
  • Mostra o prompt que produziu (transparência).

✗ Quick-win ruim

  • "Hello world" com dados fake.
  • Só texto no terminal, sem artefato.
  • Termina com "agora explore!" (e nada mais).
  • Demora >10 min (vira outro install).
  • Esconde como foi feito (mágica = desconfiança).

O quick-win não é marketing — é o teste de fumaça do próprio OS. Se ele falha, o user sabe imediatamente que algo está errado antes de tentar usar pra valer. Se passa, o user já tem 1 caso concreto pra mostrar pro chefe/cliente na próxima reunião.

5

♻️ Re-run idempotente: 100x = 1x

Idempotência é a regra de ouro do install gate: rodar ./install.sh cem vezes seguidas deve produzir o mesmo resultado de rodar uma vez. Nenhum arquivo do user é sobrescrito sem aviso. Nenhum passo já feito é refeito. Nenhuma pergunta já respondida volta.

install.sh — núcleo com case statement

#!/usr/bin/env bash
set -euo pipefail

STATE_FILE="_install-state.json"
TEMPLATE_FILE=".iamasters/_install-state.template.json"

# 1. Inicializa state se não existir (fresh=true)
if [[ ! -f "$STATE_FILE" ]]; then
  cp "$TEMPLATE_FILE" "$STATE_FILE"
  jq '.fresh = true | .started_at = (now | todate)' \
     "$STATE_FILE" > "$STATE_FILE.tmp" && mv "$STATE_FILE.tmp" "$STATE_FILE"
fi

# 2. Lê fase atual
PHASE=$(jq -r '.phase' "$STATE_FILE")

# 3. Executa o handler da fase (case dispatch)
case "$PHASE" in
  brand-context)
    run_brand_context_step          # só pergunta se faltar
    advance_phase "claude-md-bootstrap"
    ;;
  claude-md-bootstrap)
    run_claude_md_step              # gera só se CLAUDE.md ausente
    advance_phase "skills-install"
    ;;
  skills-install)
    run_skills_install              # checa cada skill, pula se já instalada
    advance_phase "hooks-install"
    ;;
  hooks-install)
    run_hooks_install               # idempotente via jq merge em settings
    advance_phase "welcome-quick-win"
    ;;
  welcome-quick-win)
    run_quick_win_step              # opcional, pergunta antes
    advance_phase "done"
    ;;
  done)
    echo "✓ Install já completo. Use --reset para reinstalar."
    exit 0
    ;;
  *)
    echo "✗ Fase desconhecida: $PHASE"; exit 1
    ;;
esac
        

🚨 Alerta — re-run que apaga progresso = user nunca volta

O pior bug do install gate é parecer idempotente e não ser. Casos clássicos: sobrescrever CLAUDE.md que o user já editou, regenerar brand.md apagando customizações, "resetar" silenciosamente o state quando encontra um campo desconhecido.

Regra: qualquer arquivo do user com mtime > started_at do install precisa pedir confirmação antes de tocar. Sempre. Sem exceção.

Checagem de fase

Sempre lê state antes de agir.

Avanço atômico

advance_phase só após sucesso.

--reset explícito

Reinstalar é opt-in com flag.

6

👋 First-time greeting via SessionStart hook

Depois do install, na primeira vez que o user abre o Claude Code no projeto, um hook SessionStart lê o _install-state.json, vê fresh=true, mostra um checklist com os próximos 5 passos sugeridos — e marca fresh=false para nunca mais aparecer automaticamente.

✓ Fazer — greeting só na 1ª vez

  • Hook checa fresh === true.
  • Mostra 3-5 próximos passos concretos.
  • Aponta para arquivos reais (welcome demo, CLAUDE.md).
  • Marca fresh = false ao final.
  • Tem comando explícito pra reativar: /welcome.

✗ Evitar — greeting toda vez

  • Mostrar o checklist em todo SessionStart.
  • "Bem-vindo de volta!" antes de qualquer prompt.
  • Dicas aleatórias que poluem o contexto.
  • Mensagens longas que o user vai começar a fechar no automático.
  • Nenhum jeito de desativar.

Saída do greeting (primeira sessão)

╭─────────────────────────────────────────────────────────────╮
│  Bem-vindo ao iAmasters OS — instalação completa ✓          │
├─────────────────────────────────────────────────────────────┤
│  Próximos 5 passos sugeridos:                               │
│                                                             │
│    1. Abrir projects/welcome/brand-applied-demo.html        │
│    2. Ler CLAUDE.md (3 min) — entender as regras do OS      │
│    3. Rodar /skills para ver o que está instalado           │
│    4. Criar seu 1º projeto: /new-project <nome>             │
│    5. Quando travar, rodar /doctor                          │
│                                                             │
│  Este checklist não aparece de novo. Use /welcome para ver. │
╰─────────────────────────────────────────────────────────────╯
        

💡 Princípio — silêncio é respeito

O greeting é caro: aparece uma vez, tem que valer. Depois disso, o OS volta a ser silencioso por default. Confiança se constrói não pedindo atenção desnecessária. O /welcome fica disponível como comando explícito pra quem quiser revisitar.

📝 Resumo do módulo

Setup é state machine, não script linear — cada execução lê fase, executa, salva, sai.
_install-state.json é o contrato — phase, completed_steps, pending_steps, fresh, version.
Bloqueantes vs opcionais separados — brand-context bloqueia, welcome-quick-win é opt-in.
Welcome quick-win é teste de fumaça — 1 artefato real com dados do brand, em <5min.
Re-run idempotente é inegociável — 100x = 1x. Sobrescrever arquivo do user = sempre pedir confirmação.
Greeting só na 1ª vez — SessionStart lê fresh=true, mostra próximos 5 passos, vira false.

Próximo módulo:

4.5 — Operação diária: rotinas, telemetria local e o ciclo de manutenção do OS