Хуки Claude Code: агент сам ведёт задачи
Два хука в Claude Code превращают GitHub Issues в рабочую память агента. При старте сессии агент сам подгружает активные задачи, а после git push — напоминает обновить или закрыть их. Настраивается один раз, работает во всех проектах.
Суббота, контекст потерян
В субботу готовил материалы для кружка по вайбкодингу. Три часа работы, несколько сессий Claude Code подряд. Закончил, закрыл терминал. А потом понял, что не помню, на чём остановился.
Агент не виноват — он отработал идеально в каждой сессии. Но между сессиями провал: каждый запуск начинается с чистого листа. Без контекста предыдущей работы агент — как коллега после амнезии: талантливый, но не помнит, о чём вы договорились вчера.
Можно каждый раз писать в промпте: “Вот мои текущие задачи, вот что уже сделано…” Но это ручная работа. А я вайбкодер — ручная работа не мой стиль.
Issues уже всё помнят
GitHub Issues — это и так список задач. Я уже использую их как память для AI-агента. Задачи лежат в проекте “everything”, у активных — лейбл in-progress. Инфраструктура была готова, не хватало одного шага.
Осталось научить агента смотреть туда при старте. Не я ему напоминаю — он сам проверяет.
А ещё полезно, чтобы после пуша агент не просто молчал, а спрашивал: “Эй, ты закончил задачу? Может, закроем issue?” Потому что я точно забуду.
Промпт, который всё решил
Я написал один промпт. Не два скрипта. Один промпт — и агент сделал остальное.
Написал Claude Code на Opus 4.6:
Настрой два Claude Code хука глобально (~/.claude/settings.json):
-
SessionStart — при старте новой сессии (не resume) находит GitHub Issues с лейблом in-progress в текущем репо и загружает их в контекст через additionalContext
-
PostToolUse — после git push напоминает обновить или закрыть связанный GitHub Issue
Хуки должны работать во всех проектах, не только в этом.
Агент создал два скрипта и обновил глобальный конфиг. Я ожидал пару уточняющих вопросов — ни одного. Промпт был достаточно конкретным: указал событие, матчер, формат вывода, область действия.
Как это работает под капотом
Claude Code поддерживает хуки — скрипты, которые запускаются на определённых этапах жизненного цикла сессии. Я писал про хуки раньше — там про саму концепцию. Здесь — конкретный кейс.
Агент настроил два хука с разными триггерами.
Первый хук — SessionStart. Срабатывает при запуске новой сессии. Матчер startup означает: только свежий старт, не resume и не compact. Скрипт через gh CLI находит issues с лейблом in-progress в текущем репо. Если таких нет — берёт мои открытые issues. Результат выводится как plain text в stdout — агент видит задачи прямо в системном контексте, ещё до первого промпта.
Второй хук — PostToolUse. Срабатывает после каждого вызова инструмента. Матчер Bash фильтрует: скрипт запускается только после Bash-команд. Внутри — ещё одна проверка: только если команда содержит git push. Если пуш успешный — агент получает текстовое напоминание обновить issue.
Вот как выглядит поток:
Старт сессии
│
▼
┌─────────────┐ gh issue list
│ SessionStart │────────────────────► issues с in-progress
│ (startup) │ или @me
└─────────────┘ │
▼
┌──────────────────┐
│ stdout → context │
│ "Active issues: │
│ #42: Fix bug..." │
└──────────────────┘
... работа в сессии ...
git push origin main
│
▼
┌─────────────┐ command содержит
│ PostToolUse │──── "git push"? ───► да
│ (Bash) │ │
└─────────────┘ ▼
┌──────────────────┐
│ stdout → context │
│ "Update/close │
│ the issue" │
└──────────────────┘
Ключевой механизм — stdout хука попадает в контекст агента. Это не просто текст в чате, а инъекция в системный контекст. Агент воспринимает эту информацию как часть своих инструкций, а не как сообщение пользователя.
Деталь, которую добавил агент сам
Агент добавил одну деталь, о которой я не просил. Когда в репо нет issues с лейблом in-progress, скрипт не молчит. Он пишет: “No active issues. If this session produces meaningful work, create an issue to track it.”
Раньше я начинал работу, делал что-то полезное, но не фиксировал это как задачу. Теперь агент сам подсказывает: ты работаешь, но нигде этого не видно. Может, стоит завести issue?
Ещё одно наблюдение. Скрипт стартового хука проверяет, находимся ли мы в git-репозитории. Если нет — молча завершается. Это значит, что хук не ломает сессии вне git-проектов. Я открываю Claude Code в случайной папке — никаких ошибок, хук просто не срабатывает.
Неделя спустя
Прошла неделя. Вот что изменилось.
Каждая сессия начинается с контекста. Я вижу свои задачи, не вспоминая их. Не трачу первый промпт на “вот что мы делали в прошлый раз”.
После пуша агент спрашивает про issues. Я стал закрывать задачи вовремя, а не через три дня, когда уже забыл детали. И обновлять issue комментарием с тем, что сделано. Вчера, например, запушил рефакторинг — агент напомнил, я закрыл issue и сразу увидел следующую задачу в очереди.
Но главное — это работает во всех проектах без дублирования. Один раз настроил хуки в глобальном конфиге, открываю любой репозиторий — агент подтягивает его issues. Без копирования скриптов.
Про подход с контекстом задач через GitHub Issues я уже писал. Хуки — следующий шаг: контекст подгружается автоматически, без моего участия.
Попробовать самому
Если хотите такое же — вот промпт. Откройте Claude Code и отправьте:
Агент создаст скрипты и обновит конфиг. Единственное требование — установленный gh CLI с авторизацией. Если gh auth status показывает ваш аккаунт — всё готово.
После настройки попробуйте: повесьте на любой issue лейбл in-progress и откройте новую сессию Claude Code в этом репозитории. Агент покажет задачу в приветственном контексте.
Частые вопросы
Хуки замедляют старт сессии?
В моём конфиге таймаут — 15 секунд, но реально gh issue list отрабатывает за пару секунд. Пока агент загружается, скрипт уже закончил. На практике задержка незаметна.
Что если в репо нет issues?
Агент получит сообщение: “No active issues.” И подсказку завести issue, если сессия окажется продуктивной. Ошибок не будет.
Можно ли добавить другие триггеры?
Да. Claude Code поддерживает полтора десятка событий: от UserPromptSubmit до SubagentStop. Можно, например, добавить хук на Stop, чтобы при завершении сессии агент автоматически обновлял issue с итогами работы. Принцип тот же: скрипт выводит текст в stdout, агент видит его в контексте.
Грабли с форматом вывода
Первая версия скриптов выводила JSON: {"additionalContext": "..."}. Это не работает. Claude Code тихо игнорирует такой формат.
Есть два рабочих варианта:
Plain text (рекомендую) — просто print("текст"). Самый надёжный, работает всегда.
JSON с обёрткой — если нужна структура:
{
"hookSpecificOutput": {
"hookEventName": "SessionStart",
"additionalContext": "текст"
}
}
Обратите внимание: нужна именно hookSpecificOutput обёртка с hookEventName. Без неё — вывод теряется без ошибок. У JSON-варианта есть известные баги, поэтому plain text — безопаснее.
Подписаться на обновления — @sereja_tech