Handbooks
Referencia

Variables de entorno

Todas las variables que Handbooks lee, la regla de nombres que las genera, la cascada de .env y cuáles no deben entrar nunca en un archivo de configuración.

La regla de nombres

Cada ajuste tiene una clave camelCase en el registro. De ella se derivan tres nombres mediante la misma transformación:

SuperficieDesde readWorkersAcotado a generate
Bandera--read-workers <n>
EntornoHANDBOOK_READ_WORKERSHANDBOOK_GENERATE_READ_WORKERS
Clave del archivo de configuraciónreadWorkersgenerateReadWorkers, o anidada generate: { readWorkers: }

La forma acotada siempre gana a la plana. Eso es lo que te permite decir «narra en chino, pero solo al generar» sin tocar nada más.

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

Unos pocos ajustes son solo acotados, porque su significado cambia según el comando: --out (HANDBOOK_RENDER_OUT, HANDBOOK_SKILL_OUT, HANDBOOK_PLAN_OUT), --handbook (HANDBOOK_SKILL_HANDBOOK, HANDBOOK_PLAN_HANDBOOK), el --lang de skill (HANDBOOK_SKILL_BODY_LANG) y el --detail / --narrate-lang de resync (HANDBOOK_RESYNC_CARD_DETAIL, HANDBOOK_RESYNC_PROSE_LANG).

Alias del proveedor

Siete ajustes aceptan además los nombres que la gente ya tiene exportados:

AjusteAlias
llmApiKeyOPENAI_API_KEY
llmProviderOPENAI_PROVIDER
llmModelOPENAI_MODEL
llmBaseUrlOPENAI_BASE_URL
llmMaxTokensOPENAI_MAX_TOKENS
llmTimeoutOPENAI_TIMEOUT
llmExtraBodyOPENAI_EXTRA_BODY

El orden de búsqueda es: acotado HANDBOOK_<CMD>_<KEY> → plano HANDBOOK_<KEY> → el alias del proveedor.

Variables de arranque

Tres ajustes se resuelven antes que todo lo demás, porque todo lo demás depende de ellos. Ninguno de ellos puede establecerse desde aquello que cargan — una clave --env dentro de handbook.config.yaml no tendría ya nada que la leyera.

Variable / banderaQué hace
HANDBOOK_ENV / --env <name>Selecciona una cascada .env por entorno y prefiere handbook.config.<name>.yaml
--env-file <path> / HANDBOOK_ENV_FILECarga exactamente ese único archivo, saltándose la cascada. Un archivo ausente es un error ruidoso. Prefiere la variable: Node >= 20.6 también se apropia de --env-file y lo pre-escanea, así que una ruta ausente muere como node: <path>: not found (salida 9) antes de que Handbooks se ejecute. La bandera gana a la variable cuando ambas están establecidas
--config <path>Nombra un archivo de configuración exacto, saltándose el descubrimiento

La cascada de .env

Sin --env-file, la CLI carga una cascada de archivos .env* desde el directorio actual, de mayor a menor precedencia:

#ArchivoQuiénÁmbito¿Con commit?
1el entorno de la shellsiempre gana
2.env.<name>.localpersonalsolo este entornono (ignorado por git)
3.env.<name>equiposolo este entorno
4.env.localpersonaltodos los entornosno (ignorado por git)
5.envequipolínea base

Las filas 2 y 3 solo se aplican cuando --env/HANDBOOK_ENV nombra un entorno. Si no hay ninguno establecido, solo se cargan las filas 4 y 5.

Toda la cascada es «llámala en este orden, el primero que escribe gana», porque cargar un archivo nunca sobrescribe una clave que ya está establecida. Esa única regla es lo que mantiene a la shell por encima de todos los archivos, sin lógica extra en ninguna parte.

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

La cascada es solo del cwd

A diferencia de handbook.config.yaml — que se descubre subiendo hasta la raíz del repositorio git — los archivos .env se leen desde el directorio en el que ejecutas el comando. .env significa «esta máquina, ahora mismo». Ejecuta los comandos respaldados por un LLM desde la raíz del repositorio, o pasa --env-file.

Qué acepta el parser de .env

KEY=value, un prefijo export opcional, líneas en blanco, líneas de comentario #, valores entre comillas simples y dobles (se quitan las comillas) y un comentario en línea # al final de un valor sin comillas. Funcionan los finales de línea CRLF, LF y CR a secas. Nada de valores multilínea.

Un valor vacío se lee como no establecidoHANDBOOK_TITLE= no producirá un handbook sin título.

Secretos

Hay dos ajustes marcados como secret en el registro — llmApiKey / OPENAI_API_KEY y llmExtraBody / OPENAI_EXTRA_BODY. Para ambos eso significa que:

  • nunca son una bandera de línea de comandos (las banderas acaban en el historial de la shell y en la salida de ps);
  • se rechazan si aparecen en un archivo de configuración, con un mensaje que dice por qué — los archivos de configuración se suben al repositorio;
  • se enmascaran en la salida de handbook config.

llmExtraBody es un secreto porque es de formato libre. Fusiona en el cuerpo de cada petición lo que sea que pongas en él, y los gateways sí aceptan autenticación en el cuerpo, así que la herramienta no puede enumerar lo que hay ahí dentro ni distinguir un campo de ajuste de una credencial. No tiene bandera alguna; usa la variable de entorno.

llmBaseUrl deliberadamente no es un secreto: un equipo que apunta todos sus checkouts a un mismo gateway compartido tiene un motivo legítimo para subirlo al repositorio. Solo se rechaza en un archivo de configuración una URL que lleve credenciales incrustadas (https://user:pass@gw.internal/v1) — ahí y en ningún otro sitio.

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

Docker

La imagen incorpora HANDBOOK_SOURCE=/src y HANDBOOK_WORK=/work, así que solo montas volúmenes:

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

El propio --env-file de Docker se superpone por encima de la carga de .env de la cadena de herramientas — ambos se aplican, y una variable OPENAI_* pasada de ese modo es visible exactamente igual que lo sería un export de la shell. Los archivos .env* nunca se incorporan a la imagen; consulta .dockerignore.

Ver qué se resolvió realmente

handbook config --command generate

imprime el entorno activo, todos los archivos .env que cargó la cascada, el archivo de configuración que resolvió y una fila por ajuste con su procedencia — flag, env, file o default.

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

Pon --check en CI

Una variable con una errata antes significaba «se ejecutó silenciosamente con el valor por defecto». Ahora es un fallo con la variable nombrada en el mensaje — mucho más barato de encontrar en CI que a los cuarenta minutos de una ejecución de generación.

La lista completa

Todas las variables, con su tipo, valor por defecto y documentación, están en la página de referencia de configuración — que se genera a partir del mismo registro que lee la CLI, así que no puede derivar.

.env.example en la raíz del repositorio también se genera a partir de ese registro. Todas sus líneas empiezan comentadas, así que copiar el archivo entero es seguro.

En esta página