Зачем нужен loop
Обычная сессия с Claude — это разговор: я пишу, он отвечает, цикл закрылся. Если задача требует ожидания — посмотреть статус CI через 5 минут, отследить новое сообщение в чате, дождаться завершения деплоя — обычная сессия не помогает. Я либо сижу и переспрашиваю руками, либо забываю и возвращаюсь через час.
/loop решает это. После того как Claude выполнил итерацию работы, он не закрывается, а засыпает. Через заданный интервал — или по сигналу — просыпается, делает следующую итерацию, опять засыпает. И так пока я не скажу «стоп».
Это не «фоновый процесс» в классическом смысле — это тот же чат, в том же окне, с тем же контекстом. Просто между итерациями harness держит сессию замороженной и оживляет её по триггеру.
Чем отличается от обычных режимов
Сравню три способа делать «длительную работу» в Claude Code.
Обычная задача:
- Один промт → один ответ → конец.
- Контекст уходит при закрытии окна.
- Подходит для: «напиши функцию», «отрефакторь файл», «объясни концепт».
Background agent:
- Запускается отдельно, в своём контексте.
- Делает большую задачу автономно и возвращает результат.
- Я в это время работаю в основном окне.
- Подходит для: «исследуй такую тему», «прогони эти тесты».
- Минус: не возвращается к разговору. Результат — один.
/loop dynamic:
- Остаётся в моём окне.
- Между итерациями засыпает.
- На каждом цикле может прочитать что-то новое (файл, чат, лог) и среагировать.
- Я могу в любой момент вмешаться: написать «стоп», задать вопрос, поменять задачу.
- Подходит для: live-сессий, мониторинга, polling-задач.
/loop нужен именно тогда, когда работа разнесена во времени и каждая итерация может зависеть от события, которое ещё не случилось.
Два способа просыпаться
ScheduleWakeup — заснул на N секунд
Самый простой вариант. Claude в конце итерации говорит harness'у: «разбуди меня через 60 секунд». Через минуту просыпается, делает следующий цикл.
Подходит, когда нет внешнего сигнала, но нужно периодически что-то проверять:
- Каждые 5 минут смотреть статус CI на GitHub
- Каждые 30 минут проверять, не пришёл ли новый коммит в ветку
- Раз в час пересобирать дашборд
Минус: даже если ничего не меняется, цикл всё равно срабатывает — это polling. На больших интервалах ок, на маленьких — лишний нагрев.
Monitor — реагирую на событие
Альтернатива polling'у. Я запускаю фоновый процесс (например, tail -f на лог, или какой-то демон), и Monitor следит за его stdout. Каждая строка в stdout будит Claude.
Это event-driven подход: пока процесс молчит — Claude спит, ничего не тратит. Появилась строка — мгновенно проснулся и среагировал.
Подходит, когда есть источник событий, который сам шлёт сигналы:
- Telegram-демон, который пишет в лог каждое новое сообщение
- CI, который шлёт webhook → файл
- Любой
tail -fна «событийный» лог
В live-сессии Ланы (см. отдельную статью про Live Session) у меня именно этот паттерн: демон brain_poll.py стучит в stdout, как только в чате клиента что-то происходит, и Claude мгновенно формулирует ответ.
Как выбирать интервал
Это важно, и не очевидно. У Claude Code есть кэширование промтов: повторные запросы с тем же системным промтом дешевле в разы (cache hit). Если интервал между итерациями короткий, кэш ещё тёплый — итерация дешёвая. Если длинный, кэш истёк — итерация дорогая.
Правила, которыми я живу:
- Меньше 5 минут — окей, кэш почти всегда тёплый. Можно гонять часто без дорогих счетов.
- 5-60 минут — cache miss оправдан, если задача не очень частая. Норм для polling раз в полчаса.
- Около 5 минут ровно — избегаю. Это серая зона, где кэш может быть и тёплым, и холодным, и счёт получается непредсказуемый. Лучше уйти либо ниже (например, 3 минуты), либо выше (10).
- Больше часа — практически всегда новый prompt. Используй только если событие очень редкое.
Если задача event-driven (реальный сигнал, не polling) — лучше Monitor, а не ScheduleWakeup. Тогда вопрос интервала вообще не стоит: спишь, пока ничего не происходит.
Реальный пример: Лана в чате с клиентом
Я веду Live Session с несколькими клиентами параллельно. У каждого свой инстанс, свой чат, своя карточка. Архитектура одна и та же, и каждая сессия держится на /loop dynamic.
Что внутри одной итерации:
- Просыпаюсь (по сигналу от
brain_poll.py— Monitor видит новую строку). - Читаю новые сообщения из inbox (
tg_read.py --client <name> --auto). - Смотрю карточку клиента в
clients/<client>.md. - Решаю: отвечать самой или эскалировать (цены, сроки, формат → к Николаю).
- Если отвечать — формирую короткие сообщения, кладу в outbox JSON.
- Если эскалировать — пишу в моё личное окно «вот что клиент написал, я думаю ответить так — отправляем?».
- Обновляю карточку клиента, если узнала новый факт.
- Засыпаю до следующего сигнала.
Это работает 24/7 (для домашнего чата) и 8-22 (для клиентских) уже месяц. Между итерациями Claude не существует — нет фонового процесса с нагрузкой. Просто проснулся → сделал → заснул.
Стоп-условия:
- В чате появляется слово «Николай» или «лично» — выхожу из цикла, жду меня.
- Я в личном окне пишу «остановись» — фиксирую контекст в
LIVE_IDEAS.md, шлю прощальное «выхожу, контекст сохранён», и/loopзакрывается.
Похожий паттерн в других проектах
То же самое работает в Бюро Тезис (другой мой проект) — в группе с партнёром Сергеем. Тот же /loop, та же связка tg_read.py → решение → tg_send.py, только chat_id и промты другие. Доказательство, что паттерн не вшит в Лану — он переиспользуется.
В HealthCompanion (трекинг здоровья через бота) тот же /loop потенциально можно использовать для напоминаний по KBJU. Пока не сделал, но архитектура такая же: polling с интервалом 1-3 часа или event-driven через лог бота.
В Evolventa (платформа управления ремонтом) /loop не нужен — там обычные REST endpoints и UI. Это к вопросу «когда не нужен loop» — об этом ниже.
Когда не нужен /loop
Три анти-сценария:
1. Batch-задача
«Прогони все 30 файлов через рефакторинг» — это не loop, это обычная итеративная задача, которую Claude сделает за один проход. Loop там лишний.
2. Однократный вопрос
«Объясни мне как работает gRPC» — нет события, на которое реагировать. Это обычный чат.
3. Можно делегировать в background agent
Если задача автономная и не требует моих вмешательств — лучше отправить её в subagent (например, web-researcher или quality-guardian). Background agent работает в своём контексте, не засоряя мой, и возвращает сжатый результат. Loop остаётся в моём контексте, и каждая итерация съедает токены здесь.
Правило: если в задаче нет ожидания событий и нет периодичности — это не loop.
Что сделать прямо сейчас
- Поймай задачу, в которой ты сам периодически проверяешь что-то руками. Деплой, CI, чат, статус процесса. Это кандидат на /loop.
- Реши: polling это (ScheduleWakeup на 1-5 минут) или event-driven (Monitor на лог фонового процесса). Event-driven всегда лучше, если есть источник событий.
- Запусти
/loopс короткой инструкцией: что читать, как реагировать, на каком слове выходить. - Не забудь стоп-слово. Live-сессия без стоп-слова — это runaway-процесс.
/loop dynamic — это не «фича для разработчиков ботов». Это базовый паттерн для любой задачи, где «между итерациями нужно подождать». В моих проектах он закрыл 4-5 разных классов работ — от ведения чатов с клиентами до мониторинга деплоев. И в каждом случае это одно окно Claude, в котором я могу вмешаться в любой момент.