Рутины и headless-режим
Всё, что мы делали до сих пор, происходило в интерактивной сессии: вы пишете, Claude отвечает. Но многие задачи агентства повторяются и не требуют человека у терминала: прогнать линтер по всем проектам ночью, обновить зависимости в двадцати репозиториях, разобрать вчерашние ошибки из мониторинга. В этом уроке разберём headless-режим — запуск claude как обычной команды в скрипте — и три способа запускать такие команды по расписанию.
Флаг -p: Claude как команда
Флаг -p (или --print) переводит Claude Code в неинтерактивный режим: он выполняет запрос, печатает ответ и завершается. Вся механика та же — инструменты, агентный цикл, CLAUDE.md, — только без диалога.
claude -p "Что делает модуль авторизации?"Как обычная команда, claude -p читает стандартный ввод и возвращает код выхода — 0 при успехе, ненулевой при ошибке. Это значит, его можно ставить в конвейер:
cat build-error.txt | claude -p "коротко объясни причину ошибки сборки" > answer.txtИли использовать как проверку в package.json:
{
"scripts": {
"lint:claude": "git diff main | claude -p \"ты линтер опечаток. для каждой опечатки в дифе выведи файл:строка и суть. больше ничего не выводи.\""
}
}Через стандартный ввод можно передать до 10 МБ; для большего сохраняйте в файл и указывайте путь в запросе.
Права в неинтерактивном режиме
Спросить некого, поэтому всё, что потребовало бы подтверждения, отклоняется. Права задаются явно:
--allowedTools— список инструментов и шаблонов в синтаксисе правил разрешений:--allowedTools "Read,Edit,Bash(pnpm lint *)". Пробел перед*тот же, что вsettings.json.--permission-mode— базовый режим:acceptEditsдля правок файлов,dontAskдля жёсткого списка,autoдля классификатора.--max-turns— ограничить число ходов агента; при превышении команда завершится с ошибкой. Страховка от бесконечных циклов.
claude -p "Примени исправления линтера" --permission-mode acceptEdits --allowedTools "Bash(pnpm lint *)"Для полностью автономных прогонов есть --dangerously-skip-permissions, но, как разбирали в уроке про режимы прав, только внутри контейнера или виртуалки.
Флаг --bare: одинаковый результат на любой машине
По умолчанию claude -p загружает всё то же, что и интерактивная сессия: хуки, навыки, плагины, MCP-серверы, автопамять, CLAUDE.md из рабочей папки и из ~/.claude. В CI это проблема: хук из чьей-то домашней папки или MCP-сервер из .mcp.json проекта запустятся без вопросов, и результат будет зависеть от машины.
Флаг --bare отключает автообнаружение всего этого. Остаются Bash, чтение и правка файлов, а нужный контекст передаётся флагами: --append-system-prompt, --settings, --mcp-config, --plugin-dir. Документация называет --bare рекомендуемым режимом для скриптов. Есть нюанс: в этом режиме не используется вход по подписке, нужна переменная ANTHROPIC_API_KEY.
claude --bare -p "Кратко перескажи README.md" --allowedTools "Read"Вывод, который можно разобрать
Флаг --output-format управляет форматом ответа:
text— обычный текст (по умолчанию);json— один объект с полемresult, идентификатором сессии, стоимостью и метаданными;stream-json— по объекту на строку, события по мере генерации (вместе с--verbose).
claude -p "Перечисли все API-эндпоинты" --output-format json | jq -r '.result'Если нужна строгая структура, добавьте --json-schema с JSON Schema, и ответ появится в поле structured_output, проверенный по схеме:
claude -p "Извлеки имена функций из auth.ts" \
--output-format json \
--json-schema '{"type":"object","properties":{"functions":{"type":"array","items":{"type":"string"}}},"required":["functions"]}' \
| jq '.structured_output'Для скриптов, которые обрабатывают результат дальше, это удобнее, чем парсить свободный текст.
Продолжение разговора из скрипта
Каждый вызов -p создаёт сессию, к которой можно вернуться: --continue продолжает последнюю, --resume с идентификатором — конкретную.
session_id=$(claude -p "Начни ревью производительности" --output-format json | jq -r '.session_id')
claude -p "Теперь сосредоточься на запросах к базе" --resume "$session_id"Так один скрипт может вести многошаговый диалог: сначала анализ, потом уточнение, потом отчёт.
Пример: ночной прогон линтера по двадцати проектам
Задача из практики агентства: в двадцати клиентских репозиториях каждую ночь прогонять линтер и проверку типов, а утром иметь список того, что сломалось, с предложенными исправлениями в отдельных ветках. Скрипт nightly-lint.sh:
#!/bin/bash
set -u
REPORT="$HOME/reports/lint-$(date +%F).md"
echo "# Линтер: $(date +%F)" > "$REPORT"
while read -r repo; do
cd "$repo" || continue
git checkout -q main && git pull -q
git checkout -q -B "claude/lint-$(date +%F)"
result=$(claude --bare -p "Запусти pnpm lint и pnpm typecheck. Исправь ошибки, не меняя поведение кода и не добавляя any или eslint-disable. Если что-то нельзя исправить безопасно — не трогай и опиши. В конце выведи одну строку: OK или FAIL, затем список изменённых файлов." \
--permission-mode acceptEdits \
--allowedTools "Bash(pnpm lint *),Bash(pnpm typecheck *),Bash(git diff *)" \
--max-turns 30 \
--output-format json)
status=$(echo "$result" | jq -r '.result' | head -n 1)
echo "## $repo — $status" >> "$REPORT"
echo "$result" | jq -r '.result' | tail -n +2 >> "$REPORT"
if ! git diff --quiet; then
git commit -qam "lint: автоисправления $(date +%F)"
fi
done < "$HOME/projects.txt"Что здесь важно. Каждый репозиторий обрабатывается в своей ветке claude/..., ничего не отправляется в удалённый репозиторий — утром человек смотрит дифы и решает сам. Права ограничены линтером, проверкой типов и чтением дифа: Claude не сможет ни установить пакет, ни сделать git push. --max-turns не даст зависнуть на одном проекте. --bare гарантирует, что результат не зависит от того, чей ноутбук запустил скрипт. И запрос требует машиночитаемую первую строку — OK или FAIL, — чтобы отчёт собирался без разбора прозы.
Документация советует сначала прогнать такой скрипт на двух-трёх проектах, поправить запрос по тому, что пошло не так, и только потом запускать на всех.
Похожим циклом делается обновление зависимостей: для каждого репозитория — «обнови минорные версии, прогони тесты, при падении откати конкретный пакет и опиши» — с разрешением на pnpm update, pnpm test и git diff.
Три способа запускать по расписанию
Скрипт написан; теперь его надо запускать. Вариантов три, и они различаются тем, где работают и что им доступно.
/loop внутри сессии. Команда /loop 15m проверь, прошёл ли CI, и разбери замечания ревью повторяет запрос каждые 15 минут, пока сессия открыта. Без интервала Claude сам выбирает паузу между итерациями по обстановке. Есть /loop без запроса — встроенный сценарий «доделай незавершённое, посмотри PR текущей ветки, приберись». Задачи живут в сессии, восстанавливаются при --resume и истекают через семь дней. Это для присмотра за PR или деплоем, пока вы работаете, а не для ночных прогонов.
Локальные задачи Desktop. Приложение Claude Desktop умеет запускать задачи по расписанию на вашей машине, без открытой сессии, с доступом к локальным файлам. Машина должна быть включена. Для ночного скрипта на рабочем ноутбуке подходит, но обычный cron или systemd-таймер с вызовом nightly-lint.sh делает то же самое и не требует ничего, кроме claude в PATH.
Рутины в облаке. Рутина — сохранённая конфигурация: запрос, репозитории, коннекторы, — которая выполняется на инфраструктуре Anthropic без вашей машины. Создаётся на claude.ai/code/routines или командой /schedule в сессии: /schedule ежедневное ревью PR в 9 утра. Триггеры трёх видов: расписание (минимальный интервал — час), HTTP-запрос на эндпоинт рутины (для алертов из мониторинга и деплой-пайплайнов) и события GitHub (открыт PR, вышел релиз).
Рутина работает автономно: без запросов на подтверждение, в свежем клоне репозитория, с правом писать только в ветки с префиксом claude/. Доступ определяется тем, какие репозитории, коннекторы и сетевые правила вы ей дали, — сужайте до необходимого. Всё, что рутина делает, делается от вашего имени: коммиты, PR, сообщения в Slack. Рутины доступны на планах Pro, Max, Team и Enterprise, находятся в статусе research preview, и у них есть дневной лимит запусков. Актуальные ограничения — в документации.
Сводно:
/loop |
Desktop / cron | Рутины | |
|---|---|---|---|
| Где работает | В открытой сессии | На вашей машине | В облаке |
| Нужна включённая машина | Да | Да | Нет |
| Локальные файлы | Да | Да | Нет, свежий клон |
| Минимальный интервал | Минута | Минута | Час |
| Подтверждения | Как в сессии | Настраиваются | Нет, автономно |
Для ночного линтера по двадцати проектам естественный выбор — cron с nightly-lint.sh на сервере сборки или рутина с выбранными репозиториями, если проекты в GitHub и нужны PR. Для присмотра за своим PR — /loop. Для реакции на алерт — рутина с API-триггером.
Попробуйте сами
10–15 мин на рабочем месте- Выполните в своём проекте
claude -p "перечисли скрипты из package.json и что делает каждый" --output-format json | jq -r '.result'. Потом добавьте--json-schemaсо схемой{"scripts": [{"name": "...", "purpose": "..."}]}и посмотрите наstructured_output. - Напишите скрипт из двух вызовов: первый анализирует диф текущей ветки и возвращает
session_id, второй через--resumeпросит составить описание PR. Проверьте, что второй вызов помнит первый. - Возьмите
nightly-lint.sh, сократите список до одного тестового репозитория и запустите руками. Прочитайте отчёт и диф. Что бы вы изменили в запросе перед прогоном на всех проектах?
Коротко
claude -p "запрос"— Claude как обычная команда: читает stdin, печатает результат, возвращает код выхода.- Права задаются флагами:
--allowedTools,--permission-mode,--max-turns; для CI —--bareиANTHROPIC_API_KEY. --output-format jsonдаёт полеresultиsession_id;--json-schema— проверенную структуру вstructured_output.- Цикл
for repo in ...; do claude -p ...; doneс узкими правами — рабочий шаблон для массовых операций; сначала на трёх проектах, потом на всех. - По расписанию:
/loopв сессии, cron или Desktop на своей машине, рутины в облаке с триггерами по времени, API и событиям GitHub.
Видеоверсия
Сценарий озвучки · 595 слов, ≈ 5 мин
До сих пор мы работали в интерактивной сессии: вы пишете, Claude отвечает. Но многие задачи повторяются и не требуют человека у терминала: ночью прогнать линтер по всем проектам, обновить зависимости в двадцати репозиториях, разобрать вчерашние ошибки из мониторинга. В этом ролике разберём, как запускать Claude Code как обычную команду в скрипте и как ставить такие команды на расписание.
Флаг «пэ» переводит Claude Code в неинтерактивный режим: выполнил запрос, напечатал ответ, завершился. Механика та же — инструменты, агентный цикл, файл клод-эм-дэ, — только без диалога. И ведёт он себя как обычная команда: читает стандартный ввод, возвращает код выхода. Можно направить в него лог сборки и попросить объяснить ошибку. Можно поставить в скрипты пакета как линтер опечаток на дифе.
Спросить в таком режиме некого, поэтому всё, что потребовало бы подтверждения, отклоняется. Права задаются явно: флаг со списком разрешённых инструментов в том же синтаксисе, что в файле настроек; флаг режима — принятие правок, «не спрашивать» или авто; и ограничение числа ходов — страховка от бесконечного цикла.
Для скриптов и CI есть важный флаг — «бэр». По умолчанию неинтерактивный запуск загружает всё, что и обычная сессия: хуки, плагины, MCP-серверы, автопамять из домашней папки. В CI это плохо: результат зависит от того, чей ноутбук запустил скрипт, а чужой хук выполнится без вопросов. Флаг «бэр» отключает автообнаружение. Остаются базовые инструменты, а нужный контекст передаётся флагами. Нюанс: в этом режиме не работает вход по подписке, нужен ключ API в переменной окружения.
Вывод можно получить в трёх форматах. Текст — по умолчанию. Джейсон — один объект с полем «результат», идентификатором сессии и стоимостью; из него удобно вытаскивать нужное утилитой «джей-кью». И потоковый джейсон — по объекту на строку по мере генерации. Если нужна строгая структура, добавьте флаг со схемой — ответ придёт проверенным по схеме в отдельном поле. А идентификатор сессии позволяет продолжить разговор следующим вызовом: сначала анализ, потом уточнение, потом отчёт — всё из скрипта.
Теперь пример из практики. Двадцать клиентских репозиториев, каждую ночь — линтер и проверка типов, утром — список того, что сломалось, с исправлениями в отдельных ветках. Скрипт идёт по списку репозиториев. В каждом: обновить основную ветку, создать ветку с префиксом «клод» и датой, запустить Claude с флагом «бэр» и запросом: прогони линтер и типы, исправь ошибки, не меняя поведение и не добавляя «эни», в конце выведи одну строку — «ок» или «фейл» — и список файлов. Права — только линтер, проверка типов и просмотр дифа. Ограничение ходов — тридцать. Результат в джейсоне: первая строка ответа идёт в заголовок отчёта, остальное — в тело. Если есть изменения — коммит в локальную ветку. Ничего не отправляется наружу: утром человек смотрит дифы и решает сам. Документация советует сначала прогнать такое на двух-трёх проектах, поправить запрос и только потом на всех.
Скрипт есть, его надо запускать. Три способа. Первый — команда «луп» внутри сессии: повторяет запрос с интервалом, пока сессия открыта. Это для присмотра за пул-реквестом или деплоем, пока вы работаете; задачи истекают через семь дней. Второй — на своей машине: приложение Claude Desktop умеет запускать задачи по расписанию, а обычный «крон» с вашим скриптом делает то же самое. Машина должна быть включена. Третий — рутины в облаке. Рутина — это сохранённый запрос, репозитории и коннекторы, которые выполняются на инфраструктуре Anthropic без вашей машины. Создаётся на сайте или командой «шедул» в сессии. Триггеры трёх видов: расписание с минимальным интервалом в час, эйч-ти-ти-пи-запрос на эндпоинт рутины — для алертов из мониторинга, — и события GitHub, например открытый пул-реквест. Рутина работает автономно, без подтверждений, в свежем клоне, и всё делает от вашего имени. Поэтому сужайте ей доступ до необходимого. Функция в статусе исследовательского превью, лимиты смотрите в документации.
Итого: для ночного линтера — крон на сервере сборки или рутина, если проекты в GitHub и нужны пул-реквесты. Для присмотра за своим PR — «луп». Для реакции на алерт — рутина с API-триггером.
