раздел 06 · подстраница 1

События hooks

Hook - это shell-команда, которую Claude Code исполняет при определённом событии: до или после вызова инструмента, при остановке, при отправке промпта. Девять событий, под каждое можно повесить любое количество команд.

Зачем

Hooks - способ навязать Claude процессы, которые он сам не будет соблюдать стабильно: автоформат, авто-тесты, защита от чтения секретов, уведомления, авто-коммиты. В отличие от инструкций в CLAUDE.md, hook исполняется детерминированно - не "по настроению".

Полная таблица событий

СобытиеКогда срабатывает
PreToolUseДо вызова любого инструмента. Можно блокировать вызов (exit 1).
PostToolUseПосле вызова инструмента. Видит результат.
UserPromptSubmitКогда пользователь отправляет промпт. До отправки в модель.
StopКогда Claude закончил отвечать и собирается отдать управление пользователю.
SubagentStopКогда суб-агент (через Task tool) закончил работу.
NotificationКогда Claude хочет показать пользователю notification (например, ждёт ввод)
PreCompactПеред автоматическим сжатием контекста.
SessionStartПри старте сессии (claude, claude --resume).
SessionEndПри завершении сессии (Ctrl+C, exit).

Переменные окружения внутри hook

Claude передаёт контекст события через env-переменные. Доступны не во всех событиях.

ПеременнаяГде доступнаЧто содержит
$CLAUDE_TOOL_NAMEPreToolUse, PostToolUseИмя инструмента: Bash, Edit, Write
$CLAUDE_FILE_PATHSPostToolUse (Edit/Write)Пути изменённых файлов, через пробел
$CLAUDE_TOOL_INPUTPreToolUse, PostToolUseJSON входа инструмента
$CLAUDE_TOOL_RESULTPostToolUseJSON результата
$CLAUDE_USER_PROMPTUserPromptSubmitТекст промпта пользователя
$CLAUDE_SESSION_IDвездеID сессии
$CLAUDE_PROJECT_DIRвездеКорень проекта (или ~)

Что когда срабатывает - примеры

PreToolUse

До любого инструмента. Самое мощное: можно блокировать опасные действия.

# заблокировать чтение .env
[[ "$CLAUDE_TOOL_NAME" == "Read" && "$CLAUDE_FILE_PATHS" == *".env"* ]] && exit 1
exit 0

Если hook вернул exit 1 - инструмент не вызывается, Claude получает ошибку.

PostToolUse

После инструмента. Удобно для автоформата, авто-тестов, уведомлений.

# автоформат .py после Edit
[[ "$CLAUDE_TOOL_NAME" == "Edit" ]] || exit 0
for f in $CLAUDE_FILE_PATHS; do
  [[ "$f" == *.py ]] && black "$f"
done

UserPromptSubmit

Перед отправкой промпта в модель. Можно дополнить промпт системным контекстом или заблокировать.

# логировать все промпты
echo "[$(date +%H:%M)] $CLAUDE_USER_PROMPT" >> ~/.claude/prompts.log

Stop

Когда Claude закончил отвечать. Типично - уведомление, авто-коммит.

# macOS уведомление
osascript -e 'display notification "Claude finished" with title "Claude Code"'

SubagentStop

Когда суб-агент завершился. Удобно собирать результат, обновлять статус, считать траты.

echo "[$(date)] subagent done" >> ~/.claude/agents.log

Notification

Когда Claude хочет вашего внимания (ждёт ответ на вопрос, требует апрув инструмента).

# звук + bounce иконки Dock на macOS
afplay /System/Library/Sounds/Ping.aiff

PreCompact

До автокомпакта. Можно сохранить полную историю в файл прежде, чем её сожмут.

cp ~/.claude/sessions/$CLAUDE_SESSION_ID.json ~/Documents/claude-archive/

SessionStart / SessionEnd

Старт - можно подгрузить контекст (например, дёрнуть git status и положить в системный промпт). End - сохранить summary.

# SessionStart: показать TODO из проекта
[[ -f TODO.md ]] && cat TODO.md

Контроль через exit-код

ExitПоведение
0Hook отработал, Claude продолжает.
1Ошибка / блок. Для PreToolUse - инструмент не вызывается.
2"Soft block" - Claude получит сообщение и попробует иначе.

Антипаттерны

  • Тяжёлые операции в PreToolUse - блокирует каждый вызов инструмента, тормозит работу.
  • Hooks, которые могут зависнуть без таймаута - заблокируют весь Claude. Всегда timeout 10s ....
  • exit 1 без сообщения - Claude не поймёт, что пошло не так. Пишите в stderr.
  • Не использовать кавычки вокруг $CLAUDE_FILE_PATHS - если в имени пробел, всё сломается.

Полезные ссылки