Хуки — это твой код, который харнесс запускает в точках жизненного цикла. В отличие от инструкций в промпте, хук нельзя проигнорировать: он выполняется, даже если модель «не хочет». Это и делает поведение детерминированным.
Из Главы 00 мы помним: промпт советует, а хук исполняет. Хук — это команда (или запрос к модели, или HTTP-вызов), которую харнесс запускает на конкретном событии: перед вызовом инструмента, после него, при старте сессии, перед компактом. Некоторые события хук может заблокировать. Всего событий тридцать, но в работе живёт горстка.
| Событие | Когда | Блокирует? |
|---|---|---|
| PreToolUse | перед вызовом инструмента (matcher по tool_name) | да |
| PostToolUse | после успешного вызова | нет |
| UserPromptSubmit | когда ты отправил промпт, до обработки | да |
| Stop | когда Claude закончил отвечать | да |
| SessionStart | старт/возобновление (matcher по source) | нет |
| PreCompact | перед компактом контекста | да |
| SubagentStop | когда субагент завершился | да |
Matcher сужает срабатывание: "matcher": "Bash" ловит только bash, "matcher": "Write|Edit" — правки файлов, mcp__memory__.* — инструменты MCP-сервера. Хуки без поддержки matcher (Stop, UserPromptSubmit) срабатывают всегда.
| Тип | Что делает | Когда брать |
|---|---|---|
| command | запускает шелл-команду, общается через exit-коды и stdout | Детерминированные правила: формат, линт, звук. |
| prompt | один заход к модели, возвращает yes/no решение | Нужна оценка, а не жёсткое правило. |
| agent | спавнит субагента с Read/Grep/Glob для проверки | Проверка требует заглянуть в файлы/тесты. |
| http | POST JSON на URL, получает JSON | Интеграция с внешним сервисом/вебхуком. |
Полезные опции на любом хуке: async: true (не блокировать выполнение — для звуков и логов), once: true (раз за сессию), timeout, statusMessage (текст в спиннере) и if (условие в синтаксисе разрешений, чтобы не плодить процессы).
"PostToolUse": [{ "matcher": "Write|Edit", "hooks": [{ "type": "command", "command": "bun run format || true" }] }]
Скилл может включать хуки, которые живут только пока он активен. Так делают опасные-но-иногда-нужные правила: /careful блокирует rm -rf, DROP TABLE, force-push через PreToolUse на Bash; /freeze запрещает любые правки вне нужной папки. Включил скилл — правило действует; вышел — снято.
Старые поля decision/reason в PreToolUse устарели. Сейчас: hookSpecificOutput.permissionDecision со значениями allow / deny / ask. Любой хук может вернуть {"continue": false}, чтобы остановить Claude совсем.