В сессии Claude Code срабатывает 30 событий хуков. Ответить могут только 3.
Полный список событий хуков в Claude Code: когда срабатывает каждое, какие 15 умеют блокировать и правило stdout, которое молча съедает вывод большинства хуков. Практический справочник, собранный на хуках, работающих в продакшене в тысячах сессий агентов.
При подключении хуков к Claude Code раз за разом всплывают две поломки, и они совершенно не похожи друг на друга.
Первая: вы добавляете хук, и ничего не происходит. Ни ошибки, ни предупреждения, ни строки в логе. Хук просто никогда не запускается.
Вторая: хук явно отрабатывает, его побочные эффекты видны на диске, но сообщение, которое он печатает для агента, не доходит. Агент ведёт себя так, будто хук ничего не сказал.
У обеих одна и та же причина. Система хуков шире и неоднороднее, чем горстка событий, которую разбирает большинство статей, а правила, определяющие, кто может говорить с агентом, вовсе не те, о которых вы бы догадались. Это тот справочник, которого нам самим не хватало. Мы строим AgentsRoom поверх этих хуков, и всё, что ниже, либо процитировано из официальной документации, либо измерено в продакшене.
Событий 30, а не шесть
Большинство руководств разбирает PreToolUse, PostToolUse, UserPromptSubmit, Stop, Notification и SubagentStop. Эти шесть реальны, и на них приходится основная часть полезной работы. Они же составляют пятую часть от того, что существует.
Полный список, сгруппированный по тому, за чем каждое событие наблюдает:
| Группа | События |
|---|---|
| Сессия | SessionStart, SessionEnd, Setup |
| Промпт | UserPromptSubmit, UserPromptExpansion |
| Инструменты | PreToolUse, PostToolUse, PostToolUseFailure, PostToolBatch |
| Разрешения | PermissionRequest, PermissionDenied |
| Ход | Stop, StopFailure |
| Субагенты и задачи | SubagentStart, SubagentStop, TaskCreated, TaskCompleted, TeammateIdle |
| Контекст | PreCompact, PostCompact, InstructionsLoaded |
| Окружение | FileChanged, CwdChanged, ConfigChange |
| Worktrees | WorktreeCreate, WorktreeRemove |
| Интерфейс | Notification, MessageDisplay |
| Elicitation в MCP | Elicitation, ElicitationResult |

Порядок срабатывания событий в одной сессии. Блок инструмента повторяется на каждый вызов инструмента, а весь блок промпта повторяется на каждый ход.
Некоторые из этих событий меняют взгляд на систему. PostToolUseFailure существует, поэтому ветка «сработал ли инструмент» вынесена в отдельное событие, а не выводится из payload. PostToolBatch срабатывает один раз после того, как разрешится пачка параллельных вызовов инструментов: это подходящее место, чтобы запустить линтер один раз, а не по разу на каждую правку. InstructionsLoaded срабатывает при чтении CLAUDE.md, что даёт точку подключения для проверки, действительно ли агент загрузил те правила, которые вы считаете загруженными.
Правило stdout, которое съедает вывод большинства хуков
Это самое полезное, что есть на этой странице.
При коде выхода 0 Claude Code разбирает stdout в поисках полей JSON. Но показывается ли этот stdout агенту вообще, зависит от события, и список исключений короткий. Из документации:
Для большинства событий stdout пишется в отладочный лог, но не показывается в транскрипте. Исключения:
UserPromptSubmit,UserPromptExpansionиSessionStart, где stdout добавляется как контекст, который Claude видит и может использовать.
Три события из тридцати. Если вы делаете echo "warning: this migration is destructive" из хука PostToolUse и ждёте, что агент это прочитает, он не прочитает никогда. Ваш текст ушёл в отладочный лог.
Есть ровно два способа показать агенту текст из любого другого события:
- Выйти с кодом 2 и писать в stderr. При выходе с кодом 2 Claude Code игнорирует stdout и любой JSON в нём, а stderr отдаёт агенту как сообщение об ошибке.
- Выйти с кодом 0 и напечатать объект JSON, несущий
hookSpecificOutput.additionalContext.
Обратите внимание на асимметрию в первом пункте. Выход 0: важен stdout, stderr не важен. Выход 2: важен stderr, а stdout отбрасывается целиком. Путаница между этими двумя случаями и есть причина, по которой хук может выглядеть совершенно правильным и всё равно молчать.
Любой другой код выхода считается неблокирующей ошибкой. В транскрипте появляется уведомление <hook name> hook error с первой строкой stderr, выполнение продолжается, а полный stderr попадает в отладочный лог.

Какой канал доходит до агента при каждом коде выхода. Пунктирный путь: тот самый, который все считают существующим, но которого нет.
Блокировать умеет ровно половина
Пятнадцать событий останавливают действие при выходе с кодом 2. Пятнадцать его игнорируют и продолжают.
Могут блокировать: PreToolUse, PermissionRequest, UserPromptSubmit, UserPromptExpansion, Stop, SubagentStop, TeammateIdle, TaskCreated, TaskCompleted, ConfigChange, PostToolBatch, PreCompact, Elicitation, ElicitationResult, WorktreeCreate.
Не могут блокировать: PostToolUse, PostToolUseFailure, PermissionDenied, StopFailure, Notification, SubagentStart, SessionStart, Setup, SessionEnd, CwdChanged, FileChanged, PostCompact, WorktreeRemove, InstructionsLoaded, MessageDisplay.
Практическое следствие: предохранитель ставится на PreToolUse и никогда на PostToolUse. PostToolUse срабатывает после того, как инструмент отработал успешно. Выход с кодом 2 там не отменит запись, он лишь напечатает ошибку, пока ущерб уже лежит на диске. Если вы хотите остановить rm -rf, у вас есть ровно одно место, где это делается.
То, что PostToolBatch блокирует, а PostToolUse нет, заслуживает второго взгляда. Это значит, что проверка на уровне пачки всё ещё может остановить ход после того, как параллельные правки применились: ближе к вето после записи система ничего не предлагает.
Matcher работает по точному совпадению, пока вдруг не перестаёт
Поле matcher меняет стратегию вычисления в зависимости от собственных символов, и ничто не подсказывает вам, по какому пути оно пошло.
| Matcher | Как вычисляется |
|---|---|
"*", "" или отсутствует | подходит ко всему |
Только буквы, цифры, _, -, пробелы, ,, | | точная строка или список точных строк, разделённых | или , |
| Что-либо ещё | регулярное выражение JavaScript без якорей |
Ловушка именно в отсутствии якорей. В документации прямо сказано, что регулярное выражение проверяется через RegExp.prototype.test, который срабатывает при совпадении в любом месте значения. Поэтому Edit.* подходит и к Edit, и к NotebookEdit. Если вы имели в виду один инструмент, пишите ^Edit$.
Два зависящих от версии поведения, которые стоит знать, прежде чем отлаживать не то:
- Запятые как разделители и терпимость к пробелам требуют Claude Code v2.1.191 или новее.
- Дефис вошёл в набор символов точного совпадения в v2.1.195. До этого matcher вида
code-reviewerсчитался регулярным выражением без якорей и потому срабатывал ещё и наsenior-code-reviewer.
В AgentsRoom мы ограничиваем собственный хук атрибуции файлов через Write|Edit|MultiEdit|NotebookEdit: он остаётся на ветке точной строки и подходит к этим четырём инструментам и ни к чему больше. У хуков жизненного цикла, которые мы устанавливаем, matcher отсутствует вовсе, потому что они касаются нас всегда.
Хуки можно объявить в шести местах, и все они складываются
Первый порыв: поискать порядок приоритетов. Его нет, и в этом самое интересное.
| Расположение | Область действия |
|---|---|
~/.claude/settings.json | все ваши проекты, локально на вашей машине |
.claude/settings.json | один проект, можно закоммитить |
.claude/settings.local.json | один проект, Claude Code добавляет его в gitignore |
| Managed policy settings | вся организация, под контролем администратора |
hooks/hooks.json плагина | пока плагин включён |
| Frontmatter скилла или агента | пока компонент активен |
Из документации:
Записи хуков сливаются между уровнями настроек, а не заменяют друг друга: пользовательские, проектные и локальные настройки добавляют свои хуки, не удаляя управляемые, а настройка
disableAllHooksне может отключить управляемые хуки извне управляемых настроек.
То есть проектный хук никогда не перекрывает глобальный, он ложится сверху. Шесть источников, все складываются. Форматтер на PostToolUse, объявленный в ваших пользовательских настройках и ещё раз в проекте, отработает дважды на каждую правку, и единственный симптом: ощущение, что всё стало медленнее.

Шесть источников, один слитый набор. Ничто здесь ничего не перекрывает.
Это же объясняет, почему инструменту, который ставит хук в чужой проект, стоит выбирать .claude/settings.local.json. Он ограничен проектом, Claude Code добавляет его в gitignore, и он загружается без единого флага CLI. Именно туда AgentsRoom пишет свои записи, чтобы закоммиченный пользователем .claude/settings.json никогда не трогался, а его коллеги никогда не наследовали путь, привязанный к конкретной машине.
Чему нас научили хуки в продакшене
AgentsRoom ставит хуки в каждый проект, который открывает, чтобы детерминированно отслеживать статус агентов и приписывать изменённые файлы нужному агенту. Некоторые вещи вылезают только на таком масштабе.
Неизвестные имена событий молча игнорируются. В документации этого нет, а мы на это опираемся. Когда мы добавляем новое событие жизненного цикла в наш установщик, пользователи со старым CLI получают settings.local.json с именем события, о котором их бинарник никогда не слышал. Ничего не ломается, ничего не предупреждает, запись просто пропускается. Именно это позволяет безопасно выпускать установщик раньше релиза CLI. И именно из-за этого, что неизбежно, опечатка даёт полную тишину вместо ошибки.
agent_id показывает, что вы находитесь внутри субагента. Поле присутствует только тогда, когда хук срабатывает внутри вызова субагента. Это важнее, чем кажется: Stop срабатывает, когда свой ход заканчивает субагент, а не только главный агент. Наивное правило «пометить сессию завершённой на Stop» помечает всю сессию законченной при первом же возврате любого субагента. Мы пропускаем события конца хода, несущие agent_id, ровно по этой причине.
Не читайте transcript_path для текущего хода. В документации предупреждают, что транскрипт пишется асинхронно и может отставать от диалога в памяти, поэтому самых свежих сообщений там может ещё не быть в момент срабатывания вашего хука. Stop и SubagentStop получают last_assistant_message именно затем, чтобы вам никогда не приходилось гоняться за файлом.
Хуки: единственный надёжный сигнал статуса. До хуков мы разбирали вывод PTY, чтобы понять, думает агент, ждёт или закончил. Это ломается в тот момент, когда CLI начинает рисовать через альтернативный экранный буфер терминала, что и делает /tui fullscreen. Хуки срабатывают одинаково при любом рендерере. Если вы строите что-то, что наблюдает за агентом снаружи, стройте именно на этом слое, а разбор вывода терминала остаётся в лучшем случае запасным вариантом.
async: true ничего не стоит. Команда хука может объявить async: true, и агент её не ждёт. Наш хук делает POST на локальный эндпоинт с потолком в 2 секунды и возвращает управление; задержка хода агента не меняется, даже когда принимающее приложение закрыто. Если ваш хук только наблюдает и никогда ничего не решает, сделайте его асинхронным и перестаньте за него платить.
Никогда не позволяйте хуку писать мусор в терминал. Наш скрипт проглатывает все исключения, в том числе на верхнем уровне. Необработанный traceback из хука не просто тихо падает, он печатает стек вызовов Python в терминальную сессию пользователя посреди его работы.
Таймауты
Значения по умолчанию щедрые, с тремя исключениями, которые щедрыми не назовёшь:
| Тип хука | Таймаут по умолчанию |
|---|---|
command, http, mcp_tool | 600 с |
prompt | 30 с |
agent | 60 с |
UserPromptSubmit (command, http, mcp_tool) | 30 с |
MessageDisplay (command, http, mcp_tool) | 10 с |
SessionEnd | 1,5 с на все хуки вместе, поднимается под более длинный timeout отдельного хука, максимум до 60 с |
Бюджет SessionEnd удивляет чаще всего. Это общий бюджет, а не лимит на каждый хук, поэтому три хука очистки делят между собой 1,5 секунды, если вы явно его не поднимете.
Коротко
- Событий существует 30. Известны шесть.
- stdout доходит до агента только на
UserPromptSubmit,UserPromptExpansionиSessionStart. Во всех остальных случаях выходите с кодом 2 и пишите в stderr либо передавайтеadditionalContextв JSON. - 15 событий блокируют при выходе с кодом 2, 15 его игнорируют. Предохранители ставятся на
PreToolUse. - Matcher остаётся точной строкой, пока специальный символ не превратит его в регулярное выражение без якорей.
- Шесть источников настроек складываются. Ничто ничего не перекрывает.
- Имя события с опечаткой отказывает в абсолютной тишине.
Если вы хотите видеть, как эти события срабатывают, а не рассуждать о них, мы построили именно это: AgentsRoom показывает каждое срабатывание хука по агенту, по проекту, по запуску, на десятках параллельных агентов и в сессиях субагентов. Хуки, которые вы настроили в своих собственных настройках, продолжают работать ровно так, как написаны, потому что AgentsRoom запускает настоящий CLI.
Читать далее
Как масштабировать AI кодирующих агентов на команду разработчиков
Один разработчик с кодирующим агентом : это история о продуктивности. Пять разработчиков с двадцатью агентами : это проблема координации. Вот что ломается в первую очередь, когда команда масштабируется, и настройка, которая удерживает: зафиксированные контекстные файлы, четкое владение файлами, обзор по радиусу взрыва и затраты, которые вы действительно можете увидеть.
Читать статьюAgentsRoom теперь поддерживает Kimi Code
Kimi Code, терминальный агент для кода от Moonshot AI, стал полноценным провайдером в AgentsRoom. Запускайте его рядом с Claude, Codex, Antigravity CLI, OpenCode, Aider, Grok Build и Mistral Vibe и переключайтесь прямо посреди разговора.
Читать статьюСтоит ли вам все еще проверять код вашего AI-агента?
Ваши агенты пишут лучший код, чем половина пулл-реквестов, которые вы раньше сливались. Так стоит ли вам читать каждую строку? Честный случай для обеих сторон, 10 сигналов, которые говорят о том, что агент допустил ошибку, и сколько проверки на самом деле заслуживает каждое изменение.
Читать статью
Скачать AgentsRoom
Запускай ИИ-агентов (Claude, Codex, Antigravity CLI, OpenCode, Aider, Grok Build, Mistral Vibe, Kimi Code) на всех проектах из одного окна.
Приложение-компаньон: следите за агентами на ходу
Используйте Claude, Codex, Antigravity CLI или другого поставщика AI.
Отправляйте баги и запросы прямо в ваш публичный бэклог.
Взгляд на AgentsRoom в действии.