Handbooks
Referência

Variáveis de ambiente

Cada variável que o Handbooks lê, a regra de nomenclatura que as gera, a cascata de .env e quais delas jamais podem entrar em um arquivo de configuração.

A regra de nomenclatura

Cada configuração tem uma chave camelCase no registro. Três nomes são derivados dela pela mesma transformação:

SuperfícieDe readWorkersCom escopo em generate
Flag--read-workers <n>
AmbienteHANDBOOK_READ_WORKERSHANDBOOK_GENERATE_READ_WORKERS
Chave no arquivo de configuraçãoreadWorkersgenerateReadWorkers, ou aninhada generate: { readWorkers: }

A forma com escopo sempre vence a forma plana. É isso que permite dizer "narre em chinês, mas só ao gerar" sem tocar em mais nada.

export HANDBOOK_NARRATE_LANG=en              # everywhere
export HANDBOOK_GENERATE_NARRATE_LANG=zh     # …except generate

Algumas configurações são exclusivas de escopo, porque seu significado muda conforme o comando: --out (HANDBOOK_RENDER_OUT, HANDBOOK_SKILL_OUT, HANDBOOK_PLAN_OUT), --handbook (HANDBOOK_SKILL_HANDBOOK, HANDBOOK_PLAN_HANDBOOK), o --lang do skill (HANDBOOK_SKILL_BODY_LANG) e o --detail / --narrate-lang do resync (HANDBOOK_RESYNC_CARD_DETAIL, HANDBOOK_RESYNC_PROSE_LANG).

Aliases de fornecedor

Sete configurações também aceitam os nomes que as pessoas já têm exportados:

ConfiguraçãoAlias
llmApiKeyOPENAI_API_KEY
llmProviderOPENAI_PROVIDER
llmModelOPENAI_MODEL
llmBaseUrlOPENAI_BASE_URL
llmMaxTokensOPENAI_MAX_TOKENS
llmTimeoutOPENAI_TIMEOUT
llmExtraBodyOPENAI_EXTRA_BODY

A ordem de busca é: com escopo HANDBOOK_<CMD>_<KEY> → plana HANDBOOK_<KEY> → o alias de fornecedor.

Variáveis de bootstrap

Três configurações são resolvidas antes de todo o resto, porque todo o resto depende delas. Nenhuma delas pode ser definida pela coisa que elas carregam — uma chave --env dentro de handbook.config.yaml não teria mais ninguém para lê-la.

Variável / flagO que faz
HANDBOOK_ENV / --env <name>Seleciona uma cascata de .env por ambiente e prefere handbook.config.<name>.yaml
--env-file <path> / HANDBOOK_ENV_FILECarrega exatamente esse único arquivo, contornando a cascata. Um arquivo ausente é um erro barulhento. Prefira a variável: o Node >= 20.6 também tem seu próprio --env-file e faz uma pré-varredura em busca dele, então um caminho ausente morre como node: <path>: not found (saída 9) antes de o Handbooks rodar. A flag vence a variável quando ambas estão definidas
--config <path>Nomeia um arquivo de configuração exato, contornando a descoberta

A cascata de .env

Sem --env-file, a CLI carrega uma cascata de arquivos .env* a partir do diretório atual, da maior precedência para a menor:

#ArquivoQuemEscopoVersionado?
1o ambiente do shellsempre vence
2.env.<name>.localpessoalsó este ambientenão (no gitignore)
3.env.<name>timesó este ambientesim
4.env.localpessoaltodos os ambientesnão (no gitignore)
5.envtimelinha de basesim

As linhas 2 e 3 só se aplicam quando --env/HANDBOOK_ENV nomeia um ambiente. Sem nenhum dos dois definido, apenas as linhas 4 e 5 são carregadas.

A cascata inteira é "chame nesta ordem, o primeiro a escrever vence", porque carregar um arquivo nunca sobrescreve uma chave que já está definida. Essa única regra é o que mantém o shell acima de todos os arquivos, sem nenhuma lógica extra em lugar nenhum.

handbook generate --env prod --source ~/code/api --work work/api
# loads .env.prod.local → .env.prod → .env.local → .env
# and prefers handbook.config.prod.yaml over handbook.config.yaml

A cascata é apenas no cwd

Diferente de handbook.config.yaml — que é descoberto subindo até a raiz do git — os arquivos .env são lidos do diretório em que você roda o comando. .env significa "esta máquina, agora". Rode os comandos apoiados em LLM a partir da raiz do repositório, ou passe --env-file.

O que o parser de .env aceita

KEY=value, um prefixo export opcional, linhas em branco, linhas de comentário #, valores entre aspas simples e duplas (as aspas são removidas) e um comentário inline # ao final de um valor sem aspas. Finais de linha CRLF, LF e CR isolado funcionam todos. Nenhum valor multilinha.

Um valor vazio é lido como não definidoHANDBOOK_TITLE= não vai produzir um handbook sem título.

Segredos

Duas configurações são marcadas como secret no registro — llmApiKey / OPENAI_API_KEY e llmExtraBody / OPENAI_EXTRA_BODY. Para as duas, isso significa que:

  • elas nunca são flags de linha de comando (flags vão parar no histórico do shell e na saída do ps);
  • elas são rejeitadas se aparecerem em um arquivo de configuração, com uma mensagem dizendo por quê — arquivos de configuração são versionados;
  • elas são mascaradas na saída de handbook config.

llmExtraBody é um segredo porque é de formato livre. Ele mescla o que quer que você coloque nele em todo corpo de requisição, e gateways de fato aceitam autenticação no corpo — então a ferramenta não tem como enumerar o que está ali, nem como distinguir um campo de ajuste de uma credencial. Ele não tem flag alguma; use a variável de ambiente.

llmBaseUrl deliberadamente não é um segredo: um time apontando todos os seus checkouts para um mesmo gateway compartilhado tem um motivo legítimo para versioná-la. Só uma URL que carrega credenciais embutidas (https://user:pass@gw.internal/v1) é recusada em um arquivo de configuração — ali e em nenhum outro lugar.

handbook.config.yaml: llmApiKey must not appear in a config file (it gets committed)
— use .env or the shell environment instead

Docker

A imagem já traz embutidos HANDBOOK_SOURCE=/src e HANDBOOK_WORK=/work, então você só monta volumes:

docker run --rm -v "$PWD:/src:ro" -v handbook-work:/work handbook:local analyze

O --env-file do próprio Docker se sobrepõe por cima do carregamento de .env da toolchain — os dois se aplicam, e uma variável OPENAI_* passada assim fica visível exatamente como um export de shell ficaria. Arquivos .env* nunca são embutidos na imagem; veja .dockerignore.

Vendo o que realmente foi resolvido

handbook config --command generate

imprime o ambiente ativo, cada arquivo .env que a cascata carregou, o arquivo de configuração que ela resolveu e uma linha por configuração com sua procedência — flag, env, file ou default.

handbook config --check    # exit 2 on the first invalid or missing value

Coloque o --check na CI

Uma variável com erro de digitação costumava significar "rodou silenciosamente no valor padrão". Agora é uma falha com a variável nomeada na mensagem — o que é muito mais barato de encontrar na CI do que quarenta minutos adentro de uma execução de geração.

A lista completa

Cada variável, com seu tipo, valor padrão e documentação, está na página Referência de configuração — que é gerada a partir do mesmo registro que a CLI lê, então ela não pode divergir.

O .env.example na raiz do repositório também é gerado a partir desse registro. Toda linha nele começa comentada, então copiar o arquivo inteiro é seguro.

Nesta página