Handbooks
Referência

Referência da CLI

Cada subcomando, cada flag, sua variável de ambiente e seu padrão — além do que cada comando escreve e com o que ele sai.

handbook [global options] <command> [command options]

Todo comando escreve seu resultado no stdout como JSON e seus logs no stderr, então o encadeamento com pipes funciona exatamente como você esperaria:

handbook analyze --source ~/code/api --work work/api | jq .functions

`--help` é gerado, não escrito

Toda flag abaixo deriva de um único registro de configurações, então handbook <cmd> --help sempre lista a flag, sua variável de ambiente, sua variável específica daquele comando e seu padrão. Se esta página e o --help algum dia discordarem, o --help está certo — e um teste de deriva quebra o build.

Opções globais

FlagEfeito
-V, --versionImprime a versão
-v, --verboseLog de depuração
-q, --quietApenas erros — vence o -v
--env <name>Seleciona um ambiente: carrega .env.<name>.local e .env.<name> antes de .env.local e .env, e prefere handbook.config.<name>.yaml. O mesmo que HANDBOOK_ENV
--env-file <path>Carrega exatamente este arquivo, ignorando a cascata de .env. Um arquivo ausente é um erro barulhento, não um fallback. Prefira HANDBOOK_ENV_FILE — veja o aviso abaixo
--config <path>Usa este arquivo de configuração em vez de descobrir o handbook.config.yaml mais próximo

As opções globais vêm antes do subcomando:

handbook --env prod -v generate --source ~/code/api --work work/api

`--env-file` colide com uma flag do Node

O Node >= 20.6 tem seu próprio --env-file, e ele varre antecipadamente toda a linha de comando atrás dela — inclusive a parte depois do caminho do script, onde ele na verdade não aplica o arquivo. Um caminho que existe passa intacto para o Handbooks, mas um caminho que não existe mata o processo antes:

$ handbook --env-file /gone.env config
node: /gone.env: not found        # node, exit 9, before Handbooks ever runs

Ou seja, o único caso que a flag promete relatar em alto e bom som é justamente o caso que ela não consegue relatar. HANDBOOK_ENV_FILE faz exatamente a mesma coisa e não pode ser interceptada:

$ HANDBOOK_ENV_FILE=/gone.env handbook config
handbook: error: ENOENT: no such file or directory, open '/gone.env'

A flag continua funcionando sempre que o arquivo está realmente lá, e ela vence a variável de ambiente quando ambas estão definidas.


analyze

Somente a Phase 1: constrói o grafo de chamadas estático. Sem LLM, sem chave, de graça.

handbook analyze --source <dir> --work <dir> [--lang <lang>]
FlagPadrãoEnv
--source <dir>obrigatórioHANDBOOK_SOURCE / HANDBOOK_ANALYZE_SOURCE
--work <dir>obrigatórioHANDBOOK_WORK / HANDBOOK_ANALYZE_WORK
--lang <lang>autoHANDBOOK_LANG / HANDBOOK_ANALYZE_LANG

--lang aceita auto ou qualquer um destes: cpp csharp dart go java kotlin objc ocaml php python ruby rust scala shell solidity swift typescript zig. auto detecta e mescla todas as linguagens em uma única passagem e é quase sempre o que você quer.

Escreve phase1/graph.json, functions.csv, graph.dot, dropped-calls.json, scan-coverage.json.

files conta o que de fato foi lido e parseado; filesUnparsed conta o que não foi, e cada um desses está nomeado, com um motivo, em scan-coverage.json. Veja Formatos de artefato.

stdout
{
  "language": "multi",
  "files": 412,
  "functions": 3187,
  "edgesKept": 9042,
  "edgesDropped": 611,
  "filesUnparsed": 3
}

generate

O pipeline completo. Precisa de um endpoint de LLM para qualquer coisa além da Phase 1.

handbook generate --source <dir> --work <dir> [options]

Opções de pipeline

FlagPadrãoO que faz
--phase <spec>allall · 1 · 2 (=2a+2b+2c) · 2a · 2b · 2c · 3, ou uma lista com vírgulas
--strategy <s>(a registrada no diretório de trabalho, senão file)file ou member
--skeleton <path>Seu próprio skeleton.yaml. Obrigatório para --strategy member
--detail <d>briefProfundidade da ficha: brief ou deep
--synth-mode <m>oneshotoneshot, ou doctor para o laço de reparo ator–crítico
--narrate-lang <l>enen ou zh
--max-doctor-rounds <n>6Rodadas de convergência do doctor
--resumefalsePula arquivos que já têm uma ficha de arquivo concluída
--refreshfalseIgnora os caches da Phase 3
--llm-cachefalseGuarda em cache as respostas cruas do LLM em <work>/phase3/cache

Opções de vazão

FlagPadrãoO que faz
--read-workers <n>12Lotes de fichas concorrentes
--read-batch-size <n>(1 para deep, 8 para brief)Arquivos por lote de fichas
--max-chars-per-file <n>0Trunca cada arquivo em n caracteres; 0 = sem limite
--assign-batch-size <n>25Fichas por lote de atribuição
--assign-workers <n>12Lotes de atribuição concorrentes
--organize-workers <n>8Chamadas de organização de etapas concorrentes
--narrate-workers <n>8Chamadas de narração concorrentes

Opções de LLM (compartilhadas por generate, plan, resync, studio)

FlagPadrãoAlias de env
--provider <name>openaiOPENAI_PROVIDER
--model <id>gpt-4o-miniOPENAI_MODEL
--base-url <url>https://api.openai.com/v1OPENAI_BASE_URL
--max-tokens <n>16000OPENAI_MAX_TOKENS
--timeout <sec>300OPENAI_TIMEOUT
--llm-retries <n>6
--llm-retry-backoff <sec>3
--llm-concurrency <n>16

A chave de API nunca é uma flag. Defina OPENAI_API_KEY (ou HANDBOOK_LLM_API_KEY) no ambiente ou em um arquivo .env. Ela é rejeitada em um arquivo de configuração, porque arquivos de configuração são commitados.

O corpo de requisição extra também nunca é uma flag, e é rejeitado em um arquivo de configuração pelo mesmo motivo. Defina OPENAI_EXTRA_BODY (ou HANDBOOK_LLM_EXTRA_BODY) no ambiente: ele mescla campos do fornecedor em todo corpo de requisição — {"thinking":{"type":"disabled"}}, por exemplo — e, por ser de formato livre, não há como distinguir ali dentro um campo de ajuste de um campo de autenticação. Campos de modelo, mensagem e tokens não podem ser sobrescritos por ele.

--base-url é uma flag, e é bem-vinda em um arquivo de configuração — um time apontando todos os seus checkouts para um mesmo gateway compartilhado é exatamente para isso que esse arquivo serve. Uma URL que embute credenciais (https://user:pass@gw.internal/v1) é recusada ali, e só ali; deixe a credencial no ambiente.

--provider escolhe o formato do protocolo, não o fornecedor: openai (o padrão) fala com qualquer endpoint compatível com OpenAI, que é a maioria; anthropic e gemini existem para os dois que não são.

stdout
{
  "phasesRun": ["1", "2a", "2b", "2c", "3"],
  "nCards": 412,
  "nStages": 9,
  "nUnassignedFiles": 0,
  "nRegisters": 6,
  "usage": { "promptTokens": 1840221, "completionTokens": 214880, "totalTokens": 2055101 }
}

render

Diretório de trabalho → markdown, e opcionalmente mais. Sem LLM.

handbook render --work <dir> [--title <t>] [--html] [--html-single] [--agent-site] [--llms-txt]
FlagPadrãoO que faz
--work <dir>obrigatórioO diretório de trabalho a renderizar
--title <title>System HandbookTítulo do handbook na saída
--out <dir><work>/handbookOnde escrever
--htmlfalseTambém o site HTML de múltiplas páginas, em <out>/html
--html-singlefalseTambém um único <out>/handbook.html autocontido
--agent-sitefalseTambém o índice para agentes + as tabelas de fatos, em <out>/agent
--llms-txtfalseTambém llms.txt e llms-full.txt
--source-base-url <url>Liga cada ficha de arquivo a <url>/<relative path>

Sem --source-base-url a saída não contém nenhuma URL externa, o que importa se você está entregando um handbook de uma base de código privada.

--out é apenas escopada: sua variável de ambiente é HANDBOOK_RENDER_OUT, não uma HANDBOOK_OUT plana, porque --out significa coisas diferentes em plan e skill.


skill

Handbooks renderizado → pacote SKILL para agentes. Sem LLM.

handbook skill --handbook <dir> --out <dir> --name <slug> [options]
FlagPadrãoO que faz
--handbook <dir>obrigatórioO diretório do handbook renderizado
--out <dir>obrigatórioPara onde vai o pacote SKILL
--name <slug>obrigatórioSlug em minúsculas com hífens; produz <slug>-handbook
--project <name>(--name)Nome legível do projeto usado na prosa
--work <dir>Adiciona coverage.json da atribuição da Phase 2
--source <dir>Com --work, adiciona um hash de conteúdo por arquivo
--agent-dir <dir>Entrega o índice para agentes e suas tabelas de fatos em references/agent/
--lang <l>enIdioma do corpo do SKILL.md. O frontmatter fica em inglês

Duas recusas que vale conhecer

--out não pode ser o diretório do handbook, nem um ancestral dele: a construção começa apagando --out, o que apagaria justamente aquilo que está sendo empacotado. E --lang zh te dá um corpo em chinês com frontmatter em inglês — os runtimes de agentes roteiam pelo texto da descrição, então traduzi-lo quebraria silenciosamente a seleção do skill.


validate

Verifica um pacote SKILL. Sem LLM. Sai com 2 em caso de falha.

handbook validate --skill <dir> [--source <dir>]
FlagPadrãoO que faz
--skill <dir>obrigatórioO diretório do skill a validar
--source <dir>Refaz o hash do código-fonte vivo para detectar deriva

Verifica a estrutura, o contrato do frontmatter, a consistência entre índice ↔ páginas de etapa, o schema do coverage.json e a atualidade dos hashes. Erros e avisos vão para o stderr.


plan

Localização de mudanças guiada pelo handbook. Precisa de um endpoint de LLM. Somente leitura.

handbook plan --source <dir> --request "<text>" [--handbook <dir>] [--out <file>]
FlagPadrãoO que faz
--source <dir>obrigatórioA base de código sobre a qual planejar (nunca é escrita)
--request <text>obrigatórioO pedido de mudança em linguagem natural
--handbook <dir>Handbooks renderizado ou skills/<x>/references. Fortemente recomendado
--out <file>(stdout)Escreve o plano aqui
--max-turns <n>30Orçamento de turnos do agente

Mais as opções de LLM compartilhadas.

Sai com código diferente de zero se o planejador desistiu — inventou resultados de ferramentas, esgotou os turnos ou terminou sem nada aproveitável — em vez de escrever um pedido de desculpas que um script alimentaria no apply.


apply

Aplica os blocos EDIT de um plano. Sem LLM. Sai com 2 se algo não foi aplicado.

handbook apply --source <dir> --plan <file> [--dry-run] [--backup-root <dir>]
FlagPadrãoO que faz
--source <dir>obrigatórioA árvore a editar
--plan <file>obrigatórioO plano vindo do handbook plan
--dry-runfalseApenas verifica — nunca escreve
--backup-root <dir><source>/.handbook-patchesPara onde vão os backups
stdout
{
  "ok": true,
  "dryRun": false,
  "outcomes": [
    { "index": 1, "file": "src/upload.py", "where": "Uploader.send (~88)", "status": "applied", "line": 88 }
  ],
  "changedFiles": ["src/upload.py"],
  "backupDir": "/repo/.handbook-patches/2026-08-08T14-05-11-204Z",
  "problems": []
}

Status: applied · created · no-match · ambiguous · file-missing · not-a-file · unsafe-path · undecodable · skipped.


rollback

Restaura uma árvore de código a partir de um backup de patch. Sem LLM.

handbook rollback --backup <dir> [--source <dir>] [--force]
FlagPadrãoO que faz
--backup <dir>obrigatórioDiretório de backup contendo manifest.json
--source <dir>Recusa um backup que pertence a outra árvore
--forcefalseRestaura até arquivos que mudaram depois do patch

Sem --force, um arquivo cujo hash atual não bate com o hash pós-patch é recusado — restaurá-lo destruiria silenciosamente tudo o que foi feito desde então.


resync

Avança um handbook depois de uma mudança de código.

handbook resync --case <dir> --work <dir> [options]
FlagPadrãoO que faz
--case <dir>obrigatórioDiretório do caso: edited/ + plan.md opcional + change.diff opcional
--work <dir>obrigatórioO diretório de trabalho a avançar
--title <title>System HandbookTítulo usado ao re-renderizar
--no-llm(LLM ligado)Apenas atualização estrutural; a prosa é marcada como obsoleta
--no-render(render ligado)Pula a atualização das saídas já renderizadas
--corrections <file>corrections.jsonl; seus arquivos ampliam o conjunto a atualizar
--detail <d>(igual ao handbook existente)brief ou deep para as fichas regeradas
--narrate-lang <l>(igual ao handbook existente)en ou zh

Mais as opções de LLM compartilhadas.

Deixar --detail e --narrate-lang sem definir é o padrão certo: não definir significa "seja igual ao que este handbook já é", então um resync nunca rebaixa silenciosamente um handbook deep para brief.


studio

A interface web local. Roda até Ctrl-C.

handbook studio [--port <n>] [--host <addr>] [--state-dir <dir>]
FlagPadrãoO que faz
--port <n>4860Porta em que escutar
--host <addr>127.0.0.1Endereço de bind. Contêineres precisam de 0.0.0.0
--state-dir <dir>$HOME/.handbook-studioRegistro e diretórios de trabalho gerenciados

Mais as opções de LLM compartilhadas — o Studio as resolve a partir das mesmas camadas que todos os outros comandos, então tanto --model quanto um bloco llm: em arquivo de configuração chegam aos seus jobs.

Definir --host 0.0.0.0 não torna o Studio acessível remotamente em nenhum sentido útil: a proteção CSRF verifica o cabeçalho Host, então uma requisição que nomeia um IP da LAN é recusada com 403. Veja Studio.


config

Imprime a configuração resolvida e de onde veio cada valor. Sem LLM.

handbook config [--command <name>] [--json] [--check]
FlagPadrãoO que faz
--command <name>generateMostra apenas as configurações que se aplicam a este subcomando
--jsonfalseSaída legível por máquina
--checkfalseApenas valida; sai com 2 se algo for inválido ou estiver faltando
handbook config --command generate      # a table, with provenance per row
handbook config --json | jq '.settings[] | select(.source.kind == "env")'
handbook config --check                 # put this one in CI

Ele mostra configuração quebrada de propósito

Ao contrário de todos os outros comandos, o config não aborta diante de um valor inválido. Um --source ausente aparece como uma linha visível — unset (required) em vez de derrubar a única ferramenta que você usaria para depurar exatamente esse problema.


Códigos de saída

CódigoSignificado
0Sucesso
1Um erro — configuração inválida, um artefato ausente, uma execução que falhou. Mensagem no stderr, prefixada handbook: error:
2Uma verificação falhou: o validate achou problemas, o apply não foi aplicado por completo, ou o config --check achou algo inválido

2 significa "a ferramenta funcionou, e a resposta é não". Scripts devem tratá-lo de forma diferente de 1.

Os atalhos do pnpm

A partir de um clone, cada um destes faz o build antes e repassa as flags diretamente:

pnpm analyze  --source ~/code/proj --work work/proj
pnpm generate --source ~/code/proj --work work/proj
pnpm render   --work work/proj --html --agent-site --llms-txt
pnpm skill    --handbook work/proj/handbook --out skills/proj --name proj
pnpm validate --skill skills/proj --source ~/code/proj
pnpm plan     --source ~/code/proj --request "…" --out plan.md
pnpm apply    --source ~/code/proj --plan plan.md --dry-run
pnpm rollback --backup ~/code/proj/.handbook-patches/<stamp>
pnpm resync   --case cases/mycase --work work/proj
pnpm studio
pnpm config:show --command generate
pnpm handbook --help

Nesta página