Весь курс мы работали с Claude Code как с интерактивным собеседником: запустили сессию, поговорили, вышли. Но у многих задач нет собеседника. Нужно проверить сотню файлов на одно и то же. Нужно, чтобы в CI на каждый pull request запускалась проверка. Нужно вставить Claude в середину шелл-конвейера между git diff и файлом отчёта.
Для этого есть headless-режим: флаг -p превращает Claude Code в обычную утилиту командной строки. Она читает stdin, пишет в stdout, возвращает код завершения. Всё, что вы умеете делать с утилитами в шелле, применимо и к ней — пайпы, циклы, редиректы, подстановка в скрипты.
Что уже умеем / что добавим
Вы умеете настраивать разрешения, писать скиллы и подключать MCP — всё это работает и в headless-режиме, что порождает отдельный вопрос: а нужно ли оно в CI. Разберём флаг -p, пайпы и лимит stdin, флаги разрешений --allowedTools и --permission-mode, продолжение диалогов через --continue и --resume, а также режим --bare для воспроизводимых запусков.
Что вы узнаете в рамках статьи
- Как запустить Claude Code без интерактивной сессии флагом
p - Как передавать данные через пайп и какой у stdin лимит
- Как заранее разрешить инструменты, чтобы запуск не ждал подтверждения
- Зачем нужен режим
-bareи чем он опасен без него в CI - Как продолжать разговор между отдельными запусками
Ключевые термины
- Headless-режим — неинтерактивный запуск Claude Code флагом
-p(или--print): задача передаётся аргументом, ответ печатается в stdout. -allowedTools— флаг, перечисляющий инструменты, которые выполняются без запроса разрешения.-permission-mode— флаг, задающий режим разрешений для всей сессии.-bare— режим, отключающий автоподхват хуков, скиллов, подагентов, плагинов, MCP-серверов и CLAUDE.md.-append-system-prompt— флаг, добавляющий текст к системному промпту, не заменяя его.
Первый запуск без интерфейса
Самая простая форма — вопрос аргументом:
claude -p "Что делает модуль аутентификации в этом проекте?"
Claude выполнит задачу и напечатает ответ в stdout — без интерфейса и ожидания ввода.
Важное для скриптов: Claude Code возвращает код 0 при успехе и ненулевой при неудаче, так что ветвиться по статусу можно как обычно. Неверный флаг даёт ошибку в stderr до начала работы, а сбой внутри запуска печатается как результат в stdout.
Скиллы и пользовательские команды здесь работают: включите /skill-name в текст промпта, и Claude Code развернёт его перед запуском. Встроенные команды интерфейса, вроде /login, недоступны.
Пайпы: Claude как звено конвейера
Headless-режим читает stdin. Классический пример — объяснить ошибку сборки:
cat build-error.txt | claude -p 'кратко объясни корневую причину этой ошибки сборки' > output.txt
Или встроить Claude в npm-скрипт как линтер опечаток:
{
"scripts": {
"lint:claude": "git diff main | claude -p \"ты линтер опечаток. для каждой опечатки в этом диффе выведи filename:line на одной строке и описание на следующей. больше ничего не выводи.\""
}
}
Скрытая польза: раз дифф приходит через пайп, Claude не нужны права на выполнение Bash. Меньше прав — меньше рисков.
Ограничение: stdin через пайп ограничен 10 МБ. При превышении Claude Code завершается с понятной ошибкой и ненулевым кодом. Если данных больше, запишите их в файл и укажите путь к файлу в промпте.
Разрешения: чтобы запуск не завис
Главная ловушка headless-режима: запуск, который ждёт ответа на запрос разрешения, а ответить некому.
Для -p встроенный стартовый режим разрешений — Manual, на любом плане. Значит, нужно явно указать, что разрешено. Первый способ — перечислить инструменты:
claude -p "Запусти тесты и почини падения" \
--allowedTools "Bash,Read,Edit"
Можно и точнее, синтаксисом правил разрешений:
claude -p "Посмотри staged-изменения и сделай коммит" \
--allowedTools "Bash(git diff *)" "Bash(git log *)" "Bash(git status *)" "Bash(git commit *)"
Обратите внимание на пробел перед звёздочкой: Bash(git diff *) разрешает команды, начинающиеся с git diff. Без пробела Bash(git diff*) совпал бы ещё и с git diff-index.
Второй способ — задать режим разрешений для всей сессии:
# Классификатор проверяет действия вместо вас
claude -p "Обнови пины зависимостей и прогони тесты" --permission-mode auto
# Правки без запроса
claude -p "Примени фиксы линтера" --permission-mode acceptEdits
# Заперто: разрешено только то, что явно в правилах
claude -p "Проверь конфигурацию" --permission-mode dontAsk
Режим dontAsk уместен в CI: Claude Code запретит всё, чего нет в правилах permissions.allow или в наборе read-only команд.
Режим --bare: одинаковый результат на любой машине
Без специальных флагов claude -p загружает ровно тот же контекст, что и интерактивная сессия: хуки, скиллы, подагентов, плагины, MCP-серверы, авто-память, CLAUDE.md. В CI это проблема сразу с двух сторон.
Со стороны воспроизводимости: хук в ~/.claude коллеги или MCP-сервер из .mcp.json проекта изменят поведение запуска, и результат на разных машинах будет разным.
Со стороны безопасности — серьёзнее. Без --bare запуск с -p выполняет хуки из .claude/settings.json проекта и подключает серверы из его .mcp.json даже в папке, которой вы никогда не доверяли. Диалога доверия в режиме -p нет, и отдельного подтверждения по каждому серверу тоже.
Решение — флаг --bare:
claude --bare -p "Кратко перескажи README.md" --allowedTools "Read"
Он отключает автоподхват хуков, скиллов, пользовательских команд, подагентов, плагинов, MCP-серверов, авто-памяти и CLAUDE.md. Заодно ускоряет старт. В bare-режиме у Claude остаются Bash, чтение и правка файлов.
Одна деталь, которая ломает первый запуск: bare-режим не использует вход по подписке. Для Anthropic API нужно задать ANTHROPIC_API_KEY в окружении.
Если что-то из контекста всё же нужно, это передаётся явно:
| Что загрузить | Чем |
|---|---|
| Дополнения к системному промпту | --append-system-prompt, --append-system-prompt-file |
| Настройки | --settings <файл-или-json> |
| MCP-серверы | --mcp-config <файл-или-json> |
| Плагин | --plugin-dir <путь>, --plugin-url <url> |
Документация отмечает, что --bare — рекомендуемый режим для скриптов и что в будущем он станет режимом по умолчанию для -p.
Продолжение разговора между запусками
Каждый вызов claude -p — отдельная сессия, но их можно связать. Флаг --continue продолжает самый недавний разговор:
claude -p "Проверь кодовую базу на проблемы с производительностью"
claude -p "Теперь сосредоточься на запросах к базе" --continue
claude -p "Собери сводку по всем найденным проблемам" --continue
Если параллельных разговоров несколько, надёжнее сохранить идентификатор сессии и возвращаться к нужному по нему. Это пригодится в следующем уроке, где мы разберём JSON-вывод.
Полезно и --append-system-prompt — он добавляет инструкции, не заменяя поведение Claude Code по умолчанию:
gh pr diff "$1" | claude -p \
--append-system-prompt "Ты инженер по безопасности. Ищи уязвимости." \
--output-format json
Частые ошибки
- Забыть про разрешения. Для
pстартовый режим — Manual на любом плане. Без-allowedToolsили-permission-modeзапуск упрётся в запрос, отвечать на который некому. - Запускать в CI без
--bare. Обычныйpподхватывает хуки и MCP-серверы проекта даже в недоверенной папке, без диалога доверия. Результат становится невоспроизводимым, а запуск — небезопасным. - Задать
--bareи не задатьANTHROPIC_API_KEY. В bare-режиме Claude Code не читает OAuth-креденшелы и связку ключей, поэтому вход по подписке не работает. - Пропихивать в пайп больше 10 МБ. Лимит stdin — 10 МБ, при превышении запуск падает с ошибкой. Большие данные пишите в файл и указывайте путь в промпте.
Наиболее частые вопросы
- Работают ли мои скиллы в режиме
p? — Да, включите/skill-nameв текст промпта, и Claude Code развернёт его перед запуском. Встроенные команды интерфейса вроде/loginнедоступны. - Как понять в скрипте, что запуск удался? — По коду завершения: 0 при успехе, ненулевой при неудаче. Ошибки неверных флагов идут в stderr до старта, сбои внутри запуска печатаются как результат в stdout.
- Чем
-bareотличается от-safe-mode? —-bareдополнительно урезает набор инструментов до Bash, чтения и правки ради скорости.-safe-modeоставляет встроенные инструменты и разрешения работать штатно и только отключает пользовательские настройки. - Что будет с фоновой Bash-задачей после завершения запуска? — Её шелл завершается примерно через пять секунд после того, как Claude вернул результат и stdin закрылся.
- Можно ли продолжить конкретный разговор, а не последний? — Да, флагом
-resumeс идентификатором сессии. Запускать команды можно из разных каталогов: Claude Code найдёт сессию по идентификатору.
Итоги
Отличный старт финальной главы: Claude Code перестал быть только собеседником и стал утилитой командной строки. Вы умеете запускать его флагом -p, кормить данными через пайп с учётом лимита в 10 МБ, заранее разрешать инструменты через --allowedTools и --permission-mode, изолировать запуск режимом --bare и связывать вызовы через --continue.
Отдельно отметьте про себя два момента, которые чаще всего портят первый опыт: стартовый режим Manual и подхват хуков проекта без --bare. Оба решаются одним флагом, если о них помнить.
Но пока результат приходит просто текстом, а скрипту нужно что-то надёжнее, чем парсить свободную речь. На следующем уроке мы включим структурированный вывод: JSON с метаданными, схемы для гарантированного формата и разбор ответа через jq.