Headless-режим Claude Code — это флаг -p. claude -p "your prompt" запускает Claude Code один раз без интерактивного интерфейса: он читает ваш промпт (и всё, что вы передали через пайп), работает с разрешёнными инструментами, печатает результат и завершается. Код выхода 0 означает успех, любой другой — что запуск не удался. Так он становится обычной утилитой командной строки, которую можно вставить в shell-скрипты, cron, git-хуки и CI-пайплайны.
В этом руководстве — флаги, которыми вы действительно будете пользоваться: форматы вывода, разрешения инструментов, лимиты ходов и бюджета, --bare, продолжение сессий и передача данных через пайп, а затем готовые шаблоны для скриптов, cron и CI и момент, когда пора переходить на Agent SDK. Каждый флаг здесь сверен с официальным справочником CLI по состоянию на октябрь 2026 года.
Основы
claude -p "What does the auth module do?"
-p и --print — один и тот же флаг. С ним сочетается большинство интерактивных опций, например --model, --effort, --append-system-prompt и --mcp-config. Некоторые опции существуют только в режиме печати, среди них --max-turns, --max-budget-usd, --json-schema и --no-session-persistence.
Для скриптов важны две детали:
- Если вы передали неверный флаг, ошибка уходит в stderr ещё до начала запуска.
- Если что-то ломается внутри запуска, например нет аутентификации, ошибка печатается как результат в stdout. Проверяйте код выхода, а не только вывод.
Данные на вход через пайп, результат — в файл
Headless-режим читает stdin, поэтому логи, diff и файлы подаются на вход, как в любую Unix-утилиту:
cat build-error.txt | claude -p 'concisely explain the root cause of this build error' > output.txt
git diff main | claude -p "Review this diff for bugs. List each as file:line and one sentence."
Stdin через пайп ограничен 10MB. Если больше, Claude Code завершается с ошибкой, поэтому для больших входных данных запишите содержимое в файл и укажите путь в промпте.
Можно также подключить его в package.json, как в официальной документации сделано с линтером опечаток:
{
"scripts": {
"lint:claude": "git diff main | claude -p \"you are a typo linter. for each typo in this diff, report filename:line on one line and the issue on the next. return nothing else.\""
}
}
Выберите формат вывода
--output-format принимает три значения:
| Формат | Что вы получаете | Для чего |
|---|---|---|
text (по умолчанию) | Итоговый ответ обычным текстом | Для людей, файлов, простых скриптов |
json | Один JSON-объект в конце | Скрипты, которым нужны ответ и метаданные |
stream-json | Одно JSON-событие на строку по ходу работы | Прогресс в реальном времени, свои интерфейсы, логирование |
JSON-объект содержит ответ в result, а также session_id, данные об использовании и total_cost_usd. Эта стоимость — оценка на стороне клиента и может отличаться от вашего счёта.
claude -p "Summarize this project" --output-format json | jq -r '.result'
Структурированный вывод с —json-schema
Когда скрипту нужны данные, а не текст, передайте JSON Schema. Проверенный результат попадает в structured_output:
claude -p "Extract the main function names from auth.py" \
--output-format json \
--json-schema '{"type":"object","properties":{"functions":{"type":"array","items":{"type":"string"}}},"required":["functions"]}'
Если запуск завершился без корректного структурированного вывода, например потому что Claude отказался, поля не будет. Проверяйте его, прежде чем использовать:
out=$(claude -p "Extract the main function names from auth.py" --output-format json --json-schema "$(cat schema.json)")
echo "$out" | jq -e '.structured_output' > /dev/null || { echo "no structured output" >&2; exit 1; }
Потоковые события
stream-json требует --verbose. Добавьте --include-partial-messages, чтобы получать токены по мере генерации. Эта команда печатает только потоковый текст:
claude -p "Write a poem" --output-format stream-json --verbose --include-partial-messages | \
jq -rj 'select(.type == "stream_event" and .event.delta.type? == "text_delta") | .event.delta.text'
Первое событие обычно system/init с моделью, инструментами, MCP-серверами и плагинами. Последняя строка — сообщение result с итоговым текстом, стоимостью и метаданными сессии. Повторные попытки видны как события system/api_retry. Полезная проверка для CI: когда вы передаёте --mcp-config, запись сервера, не прошедшая валидацию, пропускается без падения запуска и появляется в mcp_server_errors события init. Роняйте задачу, если этот массив не пуст.
Решите, что запуску можно делать
В скрипте некому отвечать на запросы разрешений, поэтому заранее решите, что Claude можно делать.
--allowedTools заранее разрешает инструменты в синтаксисе правил разрешений:
claude -p "Look at my staged changes and create an appropriate commit" \
--allowedTools "Bash(git diff *),Bash(git log *),Bash(git status *),Bash(git commit *)"
Пробел перед * важен: Bash(git diff *) совпадает с командами, начинающимися с git diff, а Bash(git diff*) совпал бы ещё и с git diff-index.
--permission-mode задаёт базовое поведение для всего, что не перечислено. По состоянию на октябрь 2026 года (Claude Code v2.1.302 и новее) запуск с -p начинается в режиме Manual, если режим нигде не задан, и вызов, требующий одобрения, отклоняется. Полезные значения:
| Режим | Поведение в headless-запуске |
|---|---|
dontAsk | Всё, что не разрешено заранее, отклоняется. Предсказуемый выбор для скриптов |
acceptEdits | Правки файлов разрешены без вопросов |
plan | Только чтение и планирование, без правок |
auto | Каждое действие проверяет классификатор; блокировка отклоняет это действие, а запуск продолжается |
bypassPermissions | Никаких проверок. Только внутри одноразового контейнера или VM |
--tools ограничивает, какие встроенные инструменты вообще существуют, а --disallowedTools добавляет запреты. --permission-prompts none сообщает Claude, что одобрять запросы некому, чтобы он не повторял их снова и снова; отказы перечислены в permission_denials итогового результата. Почему обходить разрешения на своей машине рискованно, рассказано в статье Claude Code: пропуск разрешений.
Ставьте лимиты на каждый запуск без присмотра
--max-turns 20останавливает работу после указанного числа агентных ходов и завершается с ошибкой. По умолчанию лимита нет.--max-budget-usd 5.00останавливает работу, когда оценка расходов достигает суммы. Используется клиентская оценка, и расходы могут немного превысить предел, так что оставляйте запас.timeoutиз вашей оболочки или шага CI всё равно стоит иметь. Если остановить запуск сигналом SIGTERM, Claude Code завершается с кодом 143, не записывает результат для незаконченного хода и всё равно запускает хукиSessionEnd.
Используйте —bare для воспроизводимых запусков
Без --bare claude -p загружает то же, что и интерактивная сессия: хуки, skills, плагины, MCP-серверы, автопамять и CLAUDE.md, из рабочей папки и из ~/.claude. Это значит, что одна и та же команда ведёт себя по-разному на вашем ноутбуке и на CI-раннере.
claude --bare -p "Summarize README.md" --allowedTools "Read"
--bare пропускает всё это и стартует быстрее. Вы передаёте только то, что нужно запуску:
| Что загрузить | Флаг |
|---|---|
| Дополнительные инструкции | --append-system-prompt, --append-system-prompt-file |
| Настройки | --settings <file-or-json> |
| MCP-серверы | --mcp-config <file-or-json> |
| Свои агенты | --agents <file-or-json> |
| Плагин | --plugin-dir <path> |
Режим bare никогда не читает OAuth-учётные данные и системную связку ключей. С Anthropic API задайте ANTHROPIC_API_KEY или укажите apiKeyHelper в JSON для --settings. Официальная документация рекомендует --bare для скриптовых вызовов и говорит, что в будущем релизе он станет поведением по умолчанию для -p, так что если писать его явно уже сейчас, ваши скрипты не сломаются, когда это произойдёт.
Ещё одна причина обратить на это внимание: без --bare запуск -p в только что клонированном репозитории выполняет хуки проекта и серверы из .mcp.json без диалога доверия. Не направляйте headless-запуск без --bare на код, который вы не проверили.
Продолжение и возобновление сессий
Headless-запуски сохраняются так же, как интерактивные, поэтому шаги можно выстраивать в цепочку:
# First request
claude -p "Review this codebase for performance issues"
# Continue the most recent conversation
claude -p "Now focus on the database queries" --continue
claude -p "Generate a summary of all issues found" --continue
Когда несколько запусков идут одновременно, --continue может подхватить не тот. Вместо этого сохраните ID сессии:
session_id=$(claude -p "Start a review" --output-format json | jq -r '.session_id')
claude -p "Continue that review" --resume "$session_id"
--resume находит сессию по ID из любой папки на машине, а также принимает имя или путь к транскрипту сессии .jsonl. --fork-session начинает новую ветку от возобновлённого разговора, а не дописывает в него, а --no-session-persistence вообще не сохраняет разовые запуски.
Шаблоны для скриптов, cron и CI
Цикл по файлам
На официальной странице лучших практик есть хороший шаблон для механического изменения во многих файлах:
for file in $(cat files.txt); do
claude --bare -p "Migrate $file to the new logger API and commit. Reply OK or FAIL." \
--allowedTools "Read,Edit,Bash(git add *),Bash(git commit *)" \
--permission-mode dontAsk \
--max-turns 20
done
Сначала запустите его на трёх файлах, прочитайте коммиты, поправьте промпт и только потом запускайте остальное. Запуск, упёршийся в лимит ходов, завершается с ошибкой, которую ваш цикл может записать в лог.
Скрипт ревью
gh pr diff "$1" | claude -p \
--append-system-prompt "You are a security engineer. Review for vulnerabilities." \
--output-format json
Сохраните его как review.sh и запустите bash review.sh 123; текст ревью будет в result.
Ночная задача cron
# crontab -e
0 2 * * * cd /srv/app && claude --bare -p "Run the test suite, fix failing tests, commit on the current branch. Do not push." --allowedTools "Read,Edit,Bash(npm test *),Bash(git add *),Bash(git commit *)" --permission-mode dontAsk --max-turns 30 --output-format json >> /var/log/claude-nightly.jsonl 2>> /var/log/claude-nightly.err
Cron работает с минимальным окружением, поэтому убедитесь, что claude есть в его PATH, а ANTHROPIC_API_KEY задан для этого пользователя. Запускайте на отдельной ветке или в worktree, а не на main. Если вы добавите --worktree, учтите, что worktree от запусков -p --worktree не удаляются автоматически; удаляйте их командой git worktree remove <path>. Полная ночная настройка с бюджетами и утренним ревью описана в статье Как запустить Claude Code на ночь, а таймеры для каждой ОС — в статье Как запланировать задачи Claude Code.
CI-пайплайны
В CI используйте --bare, храните API-ключ в хранилище секретов CI и считайте код выхода результатом шага. Для GitHub официальный action делает всё это за вас, с комментариями в PR и упоминаниями @claude: см. статью Claude Code GitHub Actions. Если у вас подписка, а не API-ключ, claude setup-token выводит долгоживущий OAuth-токен для CI и скриптов; он нигде не сохраняется, поэтому сразу положите его в секреты. Помните, что --bare игнорирует OAuth, поэтому токену подписки нужен запуск без --bare.
Подводные камни
- Skills и slash-команды. Пользовательские skills работают, если написать
/skill-nameв промпте. Команды, существующие только в терминальном интерфейсе, например/login, не работают. - Тихие отказы инструментов. Если Claude говорит, что не смог что-то сделать, проверьте
permission_denialsв JSON-результате и добавьте недостающее правило в--allowedTools. - Фоновая работа. Запуск
-pможет оставаться открытым, ожидая фоновые команды или субагентов, которых запустил Claude; по умолчанию он перестаёт ждать после 10 минут бездействия. - Замена системного промпта.
--system-promptполностью заменяет промпт по умолчанию, включая снимок git status. Предпочитайте--append-system-prompt, если вам не нужен именно чистый лист.
Когда переходить на Agent SDK
claude -p — это движок Agent SDK за интерфейсом CLI. Как только ваш скрипт начинает разбирать потоки, обрабатывать одобрения или управлять множеством сессий, переходите на Agent SDK для Python или TypeScript. Он даёт нативные объекты сообщений, колбэки одобрения инструментов и структурированный вывод прямо в коде, без вызова оболочки. В статье Лучшие практики Claude Code разобрано, что нужно подготовить, прежде чем оставлять любой запуск без присмотра.
Как это делать в AgentVera
Headless-запуски работают по принципу «запустил и забыл»; иногда хочется той же автоматизации, но с терминалом, за которым можно следить. В AgentVera задачи по расписанию (на всех тарифах) отправляют промпт агенту по расписанию cron, пока приложение открыто, и агент работает в настоящей панели, которую можно открыть и направлять. Автоматизации (Pro и Team) запускают агента, когда CI краснеет или в PR появляется комментарий, и никогда не пушат в ветку по умолчанию. Центр CI/CD показывает запуски GitHub Actions, GitLab и Jenkins и может передать лог упавшего запуска агенту. Ночная смена (Pro и Team) выполняет очередь задач ночью в worktree на ветке night/<date>-<slug>, коммитит без пуша и оставляет утренний отчёт. Скачайте AgentVera, если хотите видеть эти запуски, а не искать их в лог-файле.
Итог
Основной рецепт headless-режима Claude Code короткий: claude --bare -p "clear task with a check", явный список --allowedTools, --permission-mode dontAsk, --max-turns, --output-format json и код выхода, который ваш скрипт учитывает. Начните с малого, прочитайте, что выдали первые запуски, и только потом ставьте это на таймер.