Routines в Claude Code против моего парка cron-обёрток на VPS: что уехало в облако, а что нет
Routine в Claude Code - это сохранённая конфигурация агента (промпт, репозитории, окружение, коннекторы), которая запускается сама на инфраструктуре Anthropic по расписанию, HTTP-запросу или событию GitHub. Свой cron она заменяет только там, где задаче не нужны локальные файлы: каждый прогон стартует со свежего клона репозитория.
Routines в Claude Code запускают агентов по расписанию, вебхуку и событию GitHub. Разбираю на парке из 11 cron-обёрток, что реально уехало в облако, а что осталось на VPS и почему.

У меня на VPS живёт парк из одиннадцати bash-обёрток. Они дёргают claude -p по расписанию: собирают темы в беклог, генерят черновики, гоняют фактчек по скоркарте, рисуют обложки, публикуют. Первая обёртка появилась 10 июля 2026, сегодня 19-е. За эти девять дней в папку cron/ упало 29 коммитов, из них 12 с префиксом fix. Каждый fix - это когда оно молча сломалось ночью, а я узнал утром по отсутствию алерта в телеге.
А ещё в апреле 2026 Anthropic выкатили Routines: облачные агенты, которые запускаются сами. По расписанию, по HTTP-запросу или по событию в GitHub. На инфраструктуре Anthropic, без моего сервера, без моего flock и без моих двенадцати фиксов.
Ну и первая мысль была понятная: выкидываю парк, переезжаю, живу счастливо. Сел разбираться. Спойлер - не выкинул, но половину задач всё же увёл в облако.
Что такое routines в Claude Code
Routine в Claude Code - это сохранённая конфигурация агента: промпт, список репозиториев, облачное окружение и набор коннекторов. Она запускается автоматически на инфраструктуре Anthropic и работает, даже когда ноутбук закрыт. Фича вышла на неделе 13-17 апреля 2026 и до сих пор в статусе research preview: лимиты и API могут поменяться. Доступна на планах Pro, Max, Team и Enterprise с включённым Claude Code на вебе.
Ключевое отличие от обычной сессии - routine работает полностью автономно. Никакого выбора permission-режима, никаких запросов на подтверждение. Агент сам гоняет shell-команды, сам использует скиллы из склонированного репозитория, сам дёргает коннекторы. Что он может достать - определяется тремя вещами: какие репозитории ты выбрал, какая у окружения сетевая политика и какие коннекторы ты не выключил.
После инцидента, когда агент одной командой снёс мне папку проекта, слово "автономно" я читаю очень внимательно. Тут, правда, есть защита по умолчанию: пушить Claude может только в ветки с префиксом claude/, если ты явно не включил "Allow unrestricted branch pushes" для конкретного репо.
Как запустить routine по расписанию
Два пути. Из веба - claude.ai/code/routines, кнопка New routine, форма с промптом, репозиториями, окружением и триггером. Из CLI - команда /schedule, которой можно сразу скормить описание человеческим языком:
> /schedule daily PR review at 9amClaude дозадаст вопросы про расписание, репозитории и промпт, потом сохранит routine в твой аккаунт. Обе поверхности пишут в одно место, так что созданное в терминале сразу видно в вебе. Есть алиас /routines, а ещё /schedule list, /schedule update и /schedule run.
Триггеров три штуки, и их можно комбинировать на одной routine:
- Расписание - hourly, daily, weekdays, weekly или разовый запуск на конкретную дату. Кастомный cron задаётся через
/schedule update, минимальный интервал - один час, всё что чаще просто отклоняется. - GitHub - события pull request и release, с фильтрами по автору, заголовку, веткам, лейблам, драфт/не драфт, смёржен/не смёржен.
- API - персональный эндпоинт
/fireс bearer-токеном.
Вот последний мне зашёл больше всего:
curl -X POST https://api.anthropic.com/v1/claude_code/routines/trig_01ABC.../fire \
-H "Authorization: Bearer sk-ant-oat01-xxxxx" \
-H "anthropic-beta: experimental-cc-routine-2026-04-01" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{"text": "Sentry alert SEN-4521 fired in prod. Stack trace attached."}'В ответ прилетает id и урл новой сессии - открываешь в браузере и смотришь, что там агент нахимичил, в реальном времени.
Отдельно порадовала штука, которую явно делали люди, уже обжёгшиеся на промпт-инъекциях. Текст из поля text не приходит агенту как обычное сообщение - он оборачивается в блок <routine-fire-payload> и помечается как недоверенные данные. Промпт routine должен явно сказать "разбери алерт из routine-fire-payload", иначе текст лежит инертным контекстом. Логика простая: токен могут украсть, и тогда чужие инструкции приедут промаркированными, а не как приказ. Пральна? Пральна.
Чем облачный запуск по расписанию лучше своего cron
Тем, что тебе не надо писать обвязку. В облаке уже есть запуск без твоей машины, история прогонов с полным транскриптом, ретраи триггеров, изоляция окружения и веб-морда, где видно каждый запуск. В своём cron всё это - твой код, который ты пишешь, ломаешь и чинишь сам.
Чтобы не быть голословным, вот что реально лежит в моих обёртках. Не архитектура, а вот именно тот осадок, который выпадает за девять дней:
Блокировки. Каждая обёртка берёт flock на своём lock-файле. Причём семантика разная: авто-запуск по cron, если lock занят, молча выходит с нулём, а запуск из кнопки админки честно ждёт освобождения. Это две строчки кода и один вечер размышлений о том, почему генерация запустилась дважды.
Откат состояния. Генератор клеймит тему из беклога, ставит ей status=in_work и пишет id во временный файл. Если claude -p упал - обёртка обязана вернуть тему обратно в candidate, иначе она навсегда зависнет в работе. У меня для этого отдельная ветка и topic-release в обработчике ошибок.
Коды выхода. У меня их шесть штук с ручным маппингом в человеческие названия шагов: 10 - git pull, 11 - установка скиллов, 12 - упала генерация, 13 - в выводе нет строки ИТОГ, 15 - сдохла работа с базой. Плюс два "хороших" ненулевых кода: 100 (делать нечего, алерт не нужен) и 101 (беклог пуст, но алертить не чаще раза в сутки, для чего есть файл-маркер и find -mmin +1380).
И мой любимый. Алерты в телеграм у меня резали через tail -c 1200, и обрезка иногда разваливала многобайтовый UTF-8 символ пополам. Telegram отвечал на такое 400, алерт молча терялся, а я сидел и думал, почему пайплайн такой тихий. Лечится одной iconv -f utf-8 -t utf-8 -c в общей функции. Искал полдня.
Вот этого всего в routines просто нет как класса задач. Ты пишешь промпт, а не обвязку вокруг промпта.
Сколько routines съедают лимитов
Routines расходуют подписочные лимиты так же, как обычные интерактивные сессии - отдельного тарифа нет. Сверху накидывается дневной кап на количество запусков routine с аккаунта; текущий остаток видно на странице routines и в настройках usage. Разовые запуски (те, которые на конкретную дату) в этот дневной кап не считаются, но лимиты подписки жрут как все.
Когда упёрся в кап или в лимит подписки - есть развилка. С включёнными usage credits запуски продолжаются на платном оверейдже, без них - отклоняются до сброса окна. На Team и Enterprise кредиты включает админ.
Про claude code лимиты я уже писал отдельно, когда мои скиллы выжирали недельный лимит за четыре дня. Мораль ровно та же: любая автономная штука, которая ходит по расписанию, - это фоновое потребление, которое ты не чувствуешь, пока не откроешь /usage.
Отдельная засада для тех, кто сидит на ключе. Routines требуют логина через claude.ai, и аккаунты Anthropic API не поддерживаются. Если в шелле торчит ANTHROPIC_API_KEY или ANTHROPIC_AUTH_TOKEN, либо в settings.json прописан apiKeyHelper - команда /schedule просто не найдётся, потому что ключ имеет приоритет над логином. Туда же DISABLE_TELEMETRY, DO_NOT_TRACK и CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: они рубят получение фича-флагов, от которого /schedule зависит. Из веба routines при этом создаются всегда.
Когда всё-таки нужен собственный сервер под агентов
Когда у задачи есть состояние, которое живёт между запусками, и оно не в гите. Облачная routine клонирует репозиторий заново на каждый прогон, стартует с дефолтной ветки и доступа к локальным файлам не имеет вообще. Всё, что твой пайплайн накопил на диске, для неё не существует.
У меня это стоп-фактор ровно один, зато железобетонный: папка data/ весит 616 мегабайт. Там SQLite с темами, черновиками, комментами и историей проверок, сгенеренные обложки и бэкапы. Это не артефакт сборки, это и есть сам пайплайн. Плюс .env с токенами бота на сервере и админка на blog.sunm8.ru, которая ходит в ту же базу и умеет жать кнопки руками. Переносить это в модель "склонировали репо, поработали, выкинули" - значит переписать всё хранилище.
Ещё три момента, на которых стоит притормозить:
Минимальный интервал - один час. Если у тебя есть свип, который добирает подвисшие задачи каждые несколько минут, чтобы не копить очередь, - его в routines просто не переложить, придётся менять логику.
Зелёный статус прогона не значит, что задача выполнена. В доках прямым текстом: зелёный - это "сессия стартовала и завершилась без инфраструктурной ошибки". Заблокированные сетевые запросы, отсутствующие тулзы коннектора и провал самой задачи туда не попадают - надо открывать транскрипт. То есть свой слой проверки результата ты всё равно пишешь. У меня это grep -q '^ИТОГ: черновик #' по выводу, и он ловил реальные случаи, когда claude отработал "успешно", но черновик не создал.
Routines привязаны к личному аккаунту. Не шарятся с командой, а всё, что агент делает через твой GitHub и коннекторы, выглядит как сделанное тобой: коммиты и пулл-реквесты под твоим юзером, сообщения в слаке от тебя.
Cloud, Desktop или /loop
Их вообще три, и я про это узнал уже по ходу. Кроме облачных routines есть локальные scheduled tasks в десктопном приложении и /loop внутри сессии. Разница по делу:
| Cloud routines | Desktop tasks | /loop | |
|---|---|---|---|
| Где выполняется | облако Anthropic | твоя машина | твоя машина |
| Нужна включённая машина | нет | да | да |
| Нужна открытая сессия | нет | нет | да |
| Доступ к локальным файлам | нет, свежий клон | есть | есть |
| Запросы разрешений | нет, автономно | настраиваются | наследуются |
| Минимальный интервал | 1 час | 1 минута | 1 минута |
Desktop-таски - это, по сути, окультуренный cron с доступом к локальным файлам. Они стартуют только пока приложение открыто и комп не спит; если машина проспала запуск, при пробуждении будет ровно один догоняющий прогон за последние семь дней, остальное выкидывается. Отдельно уважаю честное предупреждение в доках: задача на 9 утра может отработать в 11 вечера, так что гардрейлы надо писать прямо в промпте.
Что я в итоге сделал
Провёл черту по признаку "нужны ли локальные файлы".
Всё, что живёт в гите и не трогает мою базу, - кандидат в облако. Ревью пулл-реквестов по событию pull_request.opened, еженедельная проверка дрейфа документации, разбор алертов через /fire из мониторинга. Это ровно те кейсы, под которые routines и делали, и там мой bash не даёт вообще ничего, кроме поводов для фиксов. Туда и буду переносить.
На VPS остаётся сам блог-пайплайн: генерация, фактчек, публикация, обложки. Всё, что упирается в 616 мегабайт состояния и админку, ходящую в ту же базу. Это не переносится в модель "склонировали репо, поработали, выкинули" - это переписывается заново, а такой задачи у меня сейчас нет.
Так что нет, парк я не выкинул. Но главное, что дало это разбирательство, - я перестал расширять его по инерции. Раньше новая регулярная задача автоматически означала новую обёртку с флоком, кодами выхода и алертом. Теперь сначала вопрос: а ей вообще нужен мой диск? Если нет - ей нечего делать на моём сервере.
Такие дела.
Частые вопросы
Нужна ли подписка, чтобы клод нейросеть работала по расписанию?
Да. Routines доступны на планах Pro, Max, Team и Enterprise с включённым Claude Code на вебе. Аккаунты Anthropic API не поддерживаются: если в окружении задан ANTHROPIC_API_KEY или ANTHROPIC_AUTH_TOKEN, команда /schedule не сработает, потому что ключ имеет приоритет над логином через claude.ai.
Можно ли запускать routine чаще раза в час?
Нет. У облачных routines минимальный интервал - один час, cron-выражения с большей частотой отклоняются. Если нужно чаще, подойдут локальные scheduled tasks в десктопном приложении или /loop внутри сессии: там минимум одна минута, но требуется включённая машина.
Что будет с routine, если её запуск упал?
Зелёный статус в списке прогонов означает только то, что сессия стартовала и завершилась без инфраструктурной ошибки. Провал самой задачи, заблокированные сетевые запросы и отсутствующие тулзы коннектора туда не попадают - надо открывать транскрипт прогона и читать, что агент на самом деле сделал.