Справочник CLI
Каждая подкоманда, каждый флаг, его переменная окружения и значение по умолчанию — а также то, что каждая команда записывает и с каким кодом возврата завершается.
handbook [global options] <command> [command options]Каждая команда пишет результат в stdout в виде JSON, а логи — в stderr, поэтому конвейеры работают ровно так, как вы и рассчитываете:
handbook analyze --source ~/code/api --work work/api | jq .functions`--help` генерируется, а не пишется руками
Каждый флаг ниже выводится из одного реестра настроек, поэтому handbook <cmd> --help
всегда показывает флаг, его переменную окружения, её вариант с областью видимости
команды и значение по умолчанию. Если эта страница и --help когда-нибудь разойдутся,
прав --help — а тест на расхождение уронит сборку.
Глобальные опции
| Флаг | Действие |
|---|---|
-V, --version | Вывести версию |
-v, --verbose | Отладочное логирование |
-q, --quiet | Только ошибки — приоритетнее -v |
--env <name> | Выбрать окружение: загружает .env.<name>.local и .env.<name> перед .env.local и .env, а также предпочитает handbook.config.<name>.yaml. То же, что HANDBOOK_ENV |
--env-file <path> | Загрузить именно этот файл, минуя каскад .env. Отсутствующий файл — это громкая ошибка, а не откат к умолчанию. Предпочитайте HANDBOOK_ENV_FILE — см. предупреждение ниже |
--config <path> | Использовать этот файл конфигурации вместо поиска ближайшего handbook.config.yaml |
Глобальные опции идут перед подкомандой:
handbook --env prod -v generate --source ~/code/api --work work/api`--env-file` конфликтует с флагом Node
У Node >= 20.6 есть собственный --env-file, и он предварительно сканирует всю
командную строку в его поисках — включая часть после пути к скрипту, где на самом
деле файл не применяется. Существующий путь проходит в Handbooks нетронутым, а вот путь,
которого не существует, убивает процесс раньше:
$ handbook --env-file /gone.env config
node: /gone.env: not found # node, exit 9, before Handbooks ever runsТак что единственный случай, о котором флаг обещает сообщить громко, — это как раз тот,
о котором он сообщить не может. HANDBOOK_ENV_FILE делает ровно то же самое, и его
нельзя перехватить:
$ HANDBOOK_ENV_FILE=/gone.env handbook config
handbook: error: ENOENT: no such file or directory, open '/gone.env'Флаг по-прежнему работает всегда, когда файл действительно на месте, и он приоритетнее переменной окружения, когда заданы оба.
analyze
Только Phase 1: построение статического графа вызовов. Без LLM, без ключа, бесплатно.
handbook analyze --source <dir> --work <dir> [--lang <lang>]| Флаг | По умолчанию | Env |
|---|---|---|
--source <dir> | обязателен | HANDBOOK_SOURCE / HANDBOOK_ANALYZE_SOURCE |
--work <dir> | обязателен | HANDBOOK_WORK / HANDBOOK_ANALYZE_WORK |
--lang <lang> | auto | HANDBOOK_LANG / HANDBOOK_ANALYZE_LANG |
--lang принимает auto или одно из: cpp csharp dart go java kotlin objc
ocaml php python ruby rust scala shell solidity swift typescript zig.
auto определяет и объединяет все языки за один проход и почти всегда является тем,
что вам нужно.
Записывает phase1/graph.json, functions.csv, graph.dot, dropped-calls.json,
scan-coverage.json.
files считает то, что действительно прочитано и разобрано; filesUnparsed — то, что
нет, и каждый такой файл поимённо назван с причиной в scan-coverage.json. См.
Форматы артефактов.
{
"language": "multi",
"files": 412,
"functions": 3187,
"edgesKept": 9042,
"edgesDropped": 611,
"filesUnparsed": 3
}generate
Полный pipeline. Нужна конечная точка LLM для всего, что идёт после phase 1.
handbook generate --source <dir> --work <dir> [options]Опции конвейера
| Флаг | По умолчанию | Что делает |
|---|---|---|
--phase <spec> | all | all · 1 · 2 (=2a+2b+2c) · 2a · 2b · 2c · 3 или список через запятую |
--strategy <s> | (записанная в рабочем каталоге, иначе file) | file или member |
--skeleton <path> | — | Ваш собственный skeleton.yaml. Обязателен для --strategy member |
--detail <d> | brief | Глубина карточек: brief или deep |
--synth-mode <m> | oneshot | oneshot или doctor для цикла ремонта «актёр — критик» |
--narrate-lang <l> | en | en или zh |
--max-doctor-rounds <n> | 6 | Раунды сходимости доктора |
--resume | false | Пропускать файлы, у которых уже есть готовая карточка |
--refresh | false | Игнорировать кеши phase 3 |
--llm-cache | false | Кешировать сырые ответы LLM в <work>/phase3/cache |
Опции пропускной способности
| Флаг | По умолчанию | Что делает |
|---|---|---|
--read-workers <n> | 12 | Параллельные пакеты карточек |
--read-batch-size <n> | (1 для deep, 8 для brief) | Файлов на пакет карточек |
--max-chars-per-file <n> | 0 | Обрезать каждый файл до n символов; 0 — без предела |
--assign-batch-size <n> | 25 | Карточек на пакет назначения |
--assign-workers <n> | 12 | Параллельные пакеты назначения |
--organize-workers <n> | 8 | Параллельные вызовы организации этапов |
--narrate-workers <n> | 8 | Параллельные вызовы повествования |
Опции LLM (общие для generate, plan, resync, studio)
| Флаг | По умолчанию | Псевдоним env |
|---|---|---|
--provider <name> | openai | OPENAI_PROVIDER |
--model <id> | gpt-4o-mini | OPENAI_MODEL |
--base-url <url> | https://api.openai.com/v1 | OPENAI_BASE_URL |
--max-tokens <n> | 16000 | OPENAI_MAX_TOKENS |
--timeout <sec> | 300 | OPENAI_TIMEOUT |
--llm-retries <n> | 6 | — |
--llm-retry-backoff <sec> | 3 | — |
--llm-concurrency <n> | 16 | — |
Ключ API никогда не является флагом. Задайте OPENAI_API_KEY (или
HANDBOOK_LLM_API_KEY) в окружении или в файле .env. В файле конфигурации он
отклоняется, потому что файлы конфигурации попадают в коммиты.
Дополнительное тело запроса тоже никогда не является флагом и по той же причине
отклоняется в файле конфигурации. Задавайте его через OPENAI_EXTRA_BODY (или
HANDBOOK_LLM_EXTRA_BODY) в окружении: оно подмешивает вендорские поля в тело каждого
запроса — например, {"thinking":{"type":"disabled"}}, — а форма у него произвольная, так
что отличить в нём поле тонкой настройки от поля аутентификации невозможно. Поля модели,
сообщений и токенов переопределить через него нельзя.
--base-url, наоборот, флагом остаётся, и в файле конфигурации ему самое место: один
общий шлюз, на который вся команда направляет каждый свой клон, — это ровно тот случай,
ради которого такой файл и нужен. Там — и только там — отклоняется URL со встроенными
учётными данными (https://user:pass@gw.internal/v1); держите их в окружении.
--provider выбирает формат протокола, а не поставщика: openai (по умолчанию) работает с
любым OpenAI-совместимым эндпоинтом, а таких большинство; anthropic и gemini — для двух
оставшихся.
{
"phasesRun": ["1", "2a", "2b", "2c", "3"],
"nCards": 412,
"nStages": 9,
"nUnassignedFiles": 0,
"nRegisters": 6,
"usage": { "promptTokens": 1840221, "completionTokens": 214880, "totalTokens": 2055101 }
}render
Рабочий каталог → markdown и, по желанию, кое-что ещё. Без LLM.
handbook render --work <dir> [--title <t>] [--html] [--html-single] [--agent-site] [--llms-txt]| Флаг | По умолчанию | Что делает |
|---|---|---|
--work <dir> | обязателен | Рабочий каталог для рендеринга |
--title <title> | System Handbook | Заголовок руководства в результате |
--out <dir> | <work>/handbook | Куда записывать |
--html | false | Дополнительно многостраничный HTML-сайт в <out>/html |
--html-single | false | Дополнительно один самодостаточный <out>/handbook.html |
--agent-site | false | Дополнительно индекс для агента и таблицы фактов в <out>/agent |
--llms-txt | false | Дополнительно llms.txt и llms-full.txt |
--source-base-url <url> | — | Связать каждую карточку файла с <url>/<relative path> |
Без --source-base-url результат не содержит вообще никаких внешних URL, что важно, если вы поставляете
руководство для закрытой кодовой базы.
--out имеет только ограниченную область видимости: его переменная окружения —
HANDBOOK_RENDER_OUT, а не плоская HANDBOOK_OUT, потому что --out означает разное в
plan и skill.
skill
Отрендеренное руководство → SKILL-пакет для агента. Без LLM.
handbook skill --handbook <dir> --out <dir> --name <slug> [options]| Флаг | По умолчанию | Что делает |
|---|---|---|
--handbook <dir> | обязателен | Каталог отрендеренного руководства |
--out <dir> | обязателен | Куда попадёт SKILL-пакет |
--name <slug> | обязателен | Slug из строчных букв и дефисов; даёт <slug>-handbook |
--project <name> | (--name) | Человекочитаемое имя проекта, используемое в тексте |
--work <dir> | — | Добавляет coverage.json из назначения phase 2 |
--source <dir> | — | Вместе с --work добавляет хеш содержимого на каждый файл |
--agent-dir <dir> | — | Кладёт индекс для агента и его таблицы фактов в references/agent/ |
--lang <l> | en | Язык тела SKILL.md. Фронтматтер остаётся английским |
Два отказа, о которых стоит знать
--out не должен быть каталогом руководства или его предком: сборка начинается с очистки --out, что
удалило бы ровно то, что упаковывается. А --lang zh даёт вам китайское тело с английским фронтматтером
— среды выполнения агентов маршрутизируют по тексту описания, поэтому его перевод молча сломал бы выбор
скилла.
validate
Проверить SKILL-пакет. Без LLM. Возвращает 2 при неудаче.
handbook validate --skill <dir> [--source <dir>]| Флаг | По умолчанию | Что делает |
|---|---|---|
--skill <dir> | обязателен | Каталог скилла для проверки |
--source <dir> | — | Перехешировать живой исходник, чтобы выявить расхождение |
Проверяет структуру, контракт фронтматтера, согласованность индекса и страниц этапов,
схему coverage.json и свежесть хешей. Ошибки и предупреждения идут в stderr.
plan
Локализация изменений с опорой на руководство. Нужна конечная точка LLM. Только чтение.
handbook plan --source <dir> --request "<text>" [--handbook <dir>] [--out <file>]| Флаг | По умолчанию | Что делает |
|---|---|---|
--source <dir> | обязателен | Кодовая база, для которой строится план (запись в неё никогда не ведётся) |
--request <text> | обязателен | Запрос на изменение на естественном языке |
--handbook <dir> | — | Отрендеренное руководство или skills/<x>/references. Настоятельно рекомендуется |
--out <file> | (stdout) | Записать план сюда |
--max-turns <n> | 30 | Бюджет ходов агента |
Плюс общие опции LLM.
Завершается с ненулевым кодом, если планировщик сдался — выдумал результаты
инструментов, исчерпал ходы или закончил ничем пригодным — вместо того чтобы записать
извинение, которое скрипт скормит в apply.
apply
Применить EDIT-блоки плана. Без LLM. Возвращает 2, если что-то не легло.
handbook apply --source <dir> --plan <file> [--dry-run] [--backup-root <dir>]| Флаг | По умолчанию | Что делает |
|---|---|---|
--source <dir> | обязателен | Дерево для редактирования |
--plan <file> | обязателен | План от handbook plan |
--dry-run | false | Только проверка — никогда не пишет |
--backup-root <dir> | <source>/.handbook-patches | Куда попадают резервные копии |
{
"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": []
}Статусы: applied · created · no-match · ambiguous · file-missing · not-a-file
· unsafe-path · undecodable · skipped.
rollback
Восстановить дерево исходников из резервной копии патча. Без LLM.
handbook rollback --backup <dir> [--source <dir>] [--force]| Флаг | По умолчанию | Что делает |
|---|---|---|
--backup <dir> | обязателен | Каталог резервной копии, содержащий manifest.json |
--source <dir> | — | Отклонить резервную копию, принадлежащую другому дереву |
--force | false | Восстанавливать даже файлы, изменённые после патча |
Без --force файл, текущий хеш которого не совпадает с хешем после патча, отклоняется —
восстановление молча уничтожило бы всё, что было сделано с тех пор.
resync
Перекатить руководство вперёд после изменения кода.
handbook resync --case <dir> --work <dir> [options]| Флаг | По умолчанию | Что делает |
|---|---|---|
--case <dir> | обязателен | Каталог кейса: edited/ + необязательный plan.md + необязательный change.diff |
--work <dir> | обязателен | Рабочий каталог для перекатывания вперёд |
--title <title> | System Handbook | Заголовок, используемый при повторном рендеринге |
--no-llm | (LLM включён) | Только структурное обновление; проза помечается устаревшей |
--no-render | (рендеринг включён) | Не обновлять уже отрендеренные результаты |
--corrections <file> | — | corrections.jsonl; его файлы расширяют набор для обновления |
--detail <d> | (как в существующем руководстве) | brief или deep для перегенерированных карточек |
--narrate-lang <l> | (как в существующем руководстве) | en или zh |
Плюс общие опции LLM.
Оставить --detail и --narrate-lang незаданными — правильное умолчание: незаданное значит
«соответствовать тому, чем это руководство уже является», поэтому resync никогда молча не понижает
глубокое руководство до краткого.
studio
Локальный веб-интерфейс. Работает до Ctrl-C.
handbook studio [--port <n>] [--host <addr>] [--state-dir <dir>]| Флаг | По умолчанию | Что делает |
|---|---|---|
--port <n> | 4860 | Порт для прослушивания |
--host <addr> | 127.0.0.1 | Адрес привязки. Контейнерам нужен 0.0.0.0 |
--state-dir <dir> | $HOME/.handbook-studio | Реестр и управляемые рабочие каталоги |
Плюс общие опции LLM — Studio разрешает их через те же слои, что и любая другая команда,
поэтому и --model, и блок llm: в файле конфигурации доходят до его задач.
Установка --host 0.0.0.0 не делает Studio удалённо доступной в сколько-нибудь полезном смысле: защита
от CSRF проверяет заголовок Host, поэтому запрос, называющий IP из локальной сети, отклоняется с 403.
См. Studio.
config
Вывести разрешённую конфигурацию и то, откуда взялось каждое значение. Без LLM.
handbook config [--command <name>] [--json] [--check]| Флаг | По умолчанию | Что делает |
|---|---|---|
--command <name> | generate | Показать только настройки, применимые к этой подкоманде |
--json | false | Машиночитаемый вывод |
--check | false | Только проверка; код возврата 2, если что-то неверно или отсутствует |
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Она показывает сломанную конфигурацию намеренно
В отличие от всех остальных команд, config не прерывается на неверном значении. Отсутствующий --source
отображается видимой строкой — unset (required), а не роняет тот единственный инструмент, которым вы стали
бы отлаживать ровно эту проблему.
Коды возврата
| Код | Значение |
|---|---|
0 | Успех |
1 | Ошибка — неверная конфигурация, отсутствующий артефакт, сорвавшийся запуск. Сообщение в stderr с префиксом handbook: error: |
2 | Проверка не прошла: validate нашла проблемы, apply легло не полностью или config --check нашла что-то неверное |
2 означает «инструмент отработал, и ответ — нет». Скрипты должны обрабатывать его
иначе, чем 1.
Сокращения pnpm
Из клона каждое из них сначала собирает проект и пробрасывает флаги напрямую:
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