Headless-режим Claude Code: claude -p для скриптов и CI

Headless-режим Claude Code: claude -p, вывод JSON и stream-json, --allowedTools, --max-turns, --bare, продолжение сессий, передача данных через пайп, cron и CI.

Solviera Teknoloji 8 мин чтения

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 и код выхода, который ваш скрипт учитывает. Начните с малого, прочитайте, что выдали первые запуски, и только потом ставьте это на таймер.

Вопросы

Что такое headless-режим Claude Code?

Это неинтерактивный запуск Claude Code с флагом -p (или --print). Вы передаёте промпт, Claude выполняет работу с разрешёнными инструментами, печатает результат в stdout и завершается. Код выхода 0 означает успех, ненулевой — что запуск не удался, поэтому скрипты могут на него опираться.

Как разрешить claude -p править файлы без вопросов?

Перечислите инструменты в --allowedTools, например --allowedTools "Read,Edit,Bash(npm test *)". По состоянию на октябрь 2026 года запуски с -p начинаются в режиме Manual, если режим нигде не задан, и вызовы инструментов, требующие одобрения, отклоняются. Добавьте --permission-mode dontAsk, чтобы задать это явно, или acceptEdits, чтобы разрешить все правки файлов.

Как получить вывод Claude Code в JSON?

Добавьте --output-format json. Ответ — один JSON-объект с ответом в result, а также session_id, usage и оценкой total_cost_usd. Передайте его в jq -r ".result", чтобы получить текст. Добавьте --json-schema, чтобы получить проверенные данные в structured_output, и проверяйте, что это поле есть, прежде чем его использовать.

Можно ли продолжить headless-сессию Claude Code?

Да. claude -p "next step" --continue подхватывает самый свежий разговор в текущей папке. Чтобы выбрать конкретный, сохраните session_id из запуска с JSON и передайте его в --resume; Claude Code находит сессию по ID из любой папки на этой машине.

Headless-режим использует мою подписку Claude или API-ключ?

Обычный запуск с -p использует тот вход, который есть на машине. С --bare Claude Code никогда не читает OAuth-учётные данные и связку ключей, поэтому ему нужен ANTHROPIC_API_KEY или apiKeyHelper в JSON для --settings. Для CI на подписке claude setup-token создаёт долгоживущий OAuth-токен.

Соберите своих агентов за одним столом.

Скачайте AgentVera бесплатно; ваши установленные CLI уже готовы к работе.

Другие статьи