Суть урока
Скиллы ты вызываешь сам — когда нужно. Hooks работают без твоего участия — всегда. Это как правила в трудовом договоре: сотрудник следует им автоматически, не ждёт напоминания каждый раз. Хук срабатывает при определённом событии — перед действием, после, при ошибке, при завершении — и выполняет то что ты предписал.
В этом уроке — полная картина: около 30 типов событий, 5 типов обработчиков, точный формат данных. Начнём с главного.
Ключевые концепции
- Hook — автоматическое правило которое срабатывает при конкретном событии в Claude Code
- Событие (event) — момент в жизненном цикле Claude Code: старт сессии, вызов инструмента, завершение и т.д.
- Обработчик (handler) — что именно выполняется при событии: bash-скрипт, HTTP-запрос, MCP-инструмент, prompt или agent
- Matcher — фильтр: на какие именно инструменты или события реагировать
- settings.json — файл конфигурации хуков (
.claude/settings.jsonдля проекта,~/.claude/settings.jsonглобально) - Exit code — как хук сообщает решение:
0= ок,2= заблокировать
Теория
Skills vs Hooks: в чём разница
Это не конкуренты — это разные инструменты.
| Skills | Hooks | |
|---|---|---|
| Активация | Ты вызываешь явно | Автоматически при событии |
| Уровень | Проект или глобально | Проект или глобально |
| Хранение | .claude/skills/<name>/SKILL.md |
.claude/settings.json или ~/.claude/settings.json |
| Назначение | Инструкции как делать задачу | Правила безопасности и автоматизации |
| Аналогия | Рецепт | Правила трудового договора |
Типы событий (events) — когда хуки срабатывают
Claude Code поддерживает около 30 типов событий (точный список растёт от версии к версии — см. официальную документацию). Для начала тебе нужны 6 основных. Остальные — для продвинутых сценариев.
Основные 6 событий (80% использования)
| Событие | Когда | Зачем |
|---|---|---|
| PreToolUse | ДО выполнения инструмента | Блокировка опасных действий, проверка условий |
| PostToolUse | ПОСЛЕ успешного выполнения | Логирование, аудит, уведомления |
| Stop | Claude завершил ответ | Уведомление "готово", cleanup, запуск тестов |
| Notification | Claude отправляет уведомление | Реакция на промежуточные события |
| SessionStart | Начало или возобновление сессии | Загрузка контекста, проверка окружения |
| UserPromptSubmit | Пользователь отправил запрос | Валидация, добавление контекста перед обработкой |
Продвинутые события (когда вырастешь из основных)
| Событие | Когда | Пример |
|---|---|---|
| SubagentStart | Запуск субагента | Логирование какие агенты запускаются |
| SubagentStop | Субагент завершил работу | Проверка результата субагента |
| PostToolUseFailure | Инструмент завершился ошибкой | Отправка алерта при ошибке |
| PostToolBatch | Пакет параллельных вызовов завершён | Проверка после batch-операций |
| FileChanged | Файл изменился на диске | Перезагрузка .env при изменении |
| ConfigChange | Изменилась конфигурация | Реакция на обновление settings |
| PreCompact | Перед сжатием контекста | Сохранение важного перед compaction |
| SessionEnd | Сессия завершается | Финальный cleanup, сохранение состояния |
| StopFailure | Ответ прерван ошибкой API | Алерт при rate limit или billing error |
| PermissionRequest | Появилось окно permission | Авто-одобрение определённых операций |
| CwdChanged | Смена рабочей директории | Переключение окружения |
| Setup | Запуск с --init или --maintenance |
Установка зависимостей при инициализации |
Подробнее: 4 главных события
⚠️ Важно про актуальность: Ранние материалы про Claude Code упоминают "4 типа хуков" (Pre-tool / Post-tool / Stop / Need you) — это базовая модель из старой документации. К октябрю 2026 экосистема выросла до около 30 lifecycle events (PreToolUse, PostToolUse, UserPromptSubmit, Stop, SessionStart, SubagentStop, Notification, PreCompact, PostCompact и др.) и 5 типов обработчиков (command, http, mcp_tool, prompt, agent). Эти 4 базовых сценария всё ещё покрывают большую часть задач. Остальные события — для тонкой настройки поверх. Подробнее в уроке Hook-Deny-By-Design — там как раз продвинутые события используются.
Маппинг старой "четвёрки" на современные события:
| Старая категория | Современные события 2026 |
|---|---|
| Pre-tool | PreToolUse + PreCompact + UserPromptSubmit |
| Post-tool | PostToolUse + PostCompact + SessionStart |
| Stop | Stop + SubagentStop |
| Need you | Notification + UserPromptSubmit |
1. PreToolUse — проверка перед действием
Когда срабатывает: до того как Claude выполнит любой инструмент (запись файла, чтение, bash-команда, etc.)
Зачем: блокировать опасные действия, проверять условия, защищать чувствительные файлы.
Практические сценарии:
- Не давать Claude редактировать
.envфайл с API-ключами - Проверять что код не содержит захардкоженных секретов
- Блокировать запись в production базу данных
- Проверять бюджет перед дорогими операциями
{
"hooks": {
"PreToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "/path/to/check-secrets.sh"
}
]
}
]
}
}Если скрипт возвращает exit code 2 → Claude Code останавливается и не выполняет действие. Сообщение из stderr передаётся Claude.
2. PostToolUse — действие после выполнения
Когда срабатывает: после того как Claude успешно выполнил инструмент.
Зачем: логировать что изменилось, создавать аудит-трейл, уведомлять о конкретных изменениях.
Практические сценарии:
- Записывать в лог-файл какие файлы Claude изменил и когда
- Отправлять уведомление в Telegram когда изменился критичный файл
- Обновлять счётчик операций для бюджет-контроля
- Создавать git commit после изменений
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "/path/to/audit-log.sh"
}
]
}
]
}
}3. Stop — при завершении ответа
Когда срабатывает: когда Claude Code заканчивает отвечать и завершает задачу.
Зачем: уведомлять что работа выполнена, делать cleanup, запускать следующий шаг.
Практические сценарии:
- Mac OS уведомление "Claude завершил задачу" — ты можешь работать параллельно
- Отправка итогового отчёта в Telegram
- Запуск тестов после того как Claude написал код
- Автоматический git commit по завершении
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "osascript -e 'display notification \"Claude завершил задачу\" with title \"Claude Code\"'"
}
]
}
]
}
}4. Notification — информирование
Когда срабатывает: когда Claude Code отправляет уведомление пользователю (но не Stop).
Зачем: реагировать на промежуточные сообщения Claude, не только на завершение.
Отличие от Stop: Stop — полное завершение задачи. Notification — Claude что-то сообщает в процессе.
Matcher-варианты: permission_prompt, idle_prompt, auth_success
Практические сценарии:
- Логировать все промежуточные сообщения Claude
- Уведомлять когда Claude встречает ошибку и продолжает работу
- Трекать прогресс длинных задач
5 типов обработчиков (handlers) — КАК хук выполняет действие
Событие — это КОГДА. Обработчик — это КАК. Claude Code поддерживает 5 типов обработчиков:
| Тип | Что делает | Когда использовать |
|---|---|---|
command |
Запускает bash-скрипт | 90% случаев — проверки, логи, уведомления |
http |
Отправляет HTTP POST запрос | Webhook в Telegram, Slack, внешний сервис |
mcp_tool |
Вызывает инструмент MCP-сервера | Когда MCP-сервер уже подключён |
prompt |
Отправляет текст в быструю модель | AI-проверка запроса перед выполнением |
agent |
Запускает субагента (экспериментально) | Сложные проверки требующие рассуждения |
Обработчик command (bash-скрипт) — основной
Самый простой и распространённый. Запускает shell-скрипт.
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/check-secrets.sh",
"timeout": 30
}Обработчик http (webhook) — для внешних сервисов
Отправляет данные хука как POST запрос. Тело запроса — тот же JSON что получает command-хук через stdin.
{
"type": "http",
"url": "http://localhost:8080/hooks/validate",
"headers": {
"Authorization": "Bearer $MY_TOKEN"
},
"allowedEnvVars": ["MY_TOKEN"],
"timeout": 30
}Ответ сервера в формате JSON обрабатывается так же как stdout command-хука.
Обработчик prompt — быстрая AI-проверка
Отправляет текст в быструю модель. Полезно для оценки безопасности запроса.
{
"type": "prompt",
"prompt": "Эта bash-команда безопасна? Команда: $ARGUMENTS\nОтветь JSON: {\"decision\": \"allow\"} или {\"decision\": \"deny\"}",
"timeout": 30
}Обработчики mcp_tool и agent — продвинутые
mcp_tool вызывает инструмент подключённого MCP-сервера. agent запускает субагента для проверки (в документации помечен как экспериментальный). Оба — для сложных сценариев, не для старта.
Matcher — фильтр "на что реагировать"
Matcher определяет на какие КОНКРЕТНЫЕ инструменты реагировать. Без matcher хук срабатывает на ВСЁ.
| Значение matcher | Что делает | Пример |
|---|---|---|
"Bash" |
Только bash-команды | Хук сработает при npm test, git push |
"Write|Edit" |
Запись или редактирование файлов | Хук на проверку секретов |
"mcp__memory__.*" |
Все инструменты MCP-сервера memory | Аудит MCP-операций |
"*" или отсутствует |
Все инструменты | Универсальный лог |
Matcher — это регулярное выражение если в нём есть спецсимволы, или точное совпадение если только буквы.
Дополнительный фильтр "if" позволяет фильтровать по аргументам (например, Bash(git *) или Edit(*.ts)):
{
"matcher": "Bash",
"hooks": [{
"type": "command",
"if": "Bash(rm *)",
"command": "echo 'rm заблокирован' >&2 && exit 2"
}]
}Здесь хук сработает только для Bash, и только если команда начинается с rm. Полный синтаксис if — в официальном справочнике по хукам.
Структура settings.json (официальный формат)
Все хуки хранятся в settings.json. Есть три уровня файлов:
| Файл | Область | Делиться? |
|---|---|---|
~/.claude/settings.json |
Все проекты (глобально) | Нет |
.claude/settings.json |
Этот проект | Да (коммитить в git) |
.claude/settings.local.json |
Этот проект (локально) | Нет (в .gitignore) |
Структура: 3 уровня вложенности
hooks → Событие → [{ matcher, hooks: [{ type, command, ... }] }]Полный пример с 3 хуками:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/check-secrets.sh",
"timeout": 30
}
]
}
],
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/audit-log.sh"
}
]
}
],
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "osascript -e 'display notification \"Claude завершил\" with title \"Claude Code\"'"
}
]
}
]
}
}Ключевые правила:
- Имена событий — CamelCase:
PreToolUse, неpre_tool_use - Каждое событие содержит массив групп с
matcherиhooks - Каждая группа содержит массив обработчиков
hooks matcherфильтрует по инструменту (для Stop/SessionStart — не нужен)- Можно полностью отключить все хуки:
"disableAllHooks": true
Как хук получает данные (JSON-протокол)
Claude Code передаёт хуку данные через stdin (для command-хуков) или POST body (для http-хуков) в формате JSON.
Что получает PreToolUse хук
{
"session_id": "abc123",
"cwd": "/Users/me/project",
"hook_event_name": "PreToolUse",
"tool_name": "Write",
"tool_input": {
"file_path": "/project/config.py",
"content": "API_KEY = 'sk-proj-abc123...'"
}
}Что получает PostToolUse хук
{
"session_id": "abc123",
"cwd": "/Users/me/project",
"hook_event_name": "PostToolUse",
"tool_name": "Bash",
"tool_input": { "command": "npm test" },
"tool_response": "All tests passed"
}Что получает SessionStart хук
{
"session_id": "abc123",
"cwd": "/Users/me/project",
"hook_event_name": "SessionStart",
"source": "startup",
"model": "<идентификатор модели>"
}Как хук отвечает Claude Code (JSON-ответ)
Хук может вернуть JSON через stdout для управления поведением:
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "allow",
"permissionDecisionReason": "Безопасная команда",
"additionalContext": "Подсказка для Claude"
}
}Решения для PreToolUse: "allow" (разрешить без вопросов), "deny" (заблокировать), "ask" (спросить пользователя); в новых версиях есть ещё "defer".
Если несколько хуков дают разные решения, приоритет: deny > ask > allow.
Exit codes — как хук сообщает решение
| Exit code | Результат |
|---|---|
| 0 | Успех. Claude Code парсит stdout как JSON |
| 2 | Блокировка. Stderr передаётся Claude как причина |
| 1 или другой | Некритичная ошибка — запись в лог, работа продолжается |
Важно: exit code 2 (не 1!) блокирует действие. Exit code 1 — это просто ошибка, хук "сломался", но Claude продолжает работу.
Как добавить хук: два способа
Способ 1: Попросить Claude Code (рекомендуется для начала)
Я хочу сделать хук: когда Claude завершает ответ, отправлять мне Mac OS уведомление
Claude Code задаст уточняющие вопросы, создаст bash-скрипт и добавит запись в settings.json.
Способ 2: Через /hooks в терминале
claude
# В интерфейсе Claude Code:
/hooks
# Открывает список настроенных хуков (просмотр)
# Для редактирования — правь settings.json напрямуюПоказывает текущие хуки: тип обработчика ([command], [http], [prompt]), источник ([User], [Project], [Local]) и matcher.
Глобальные vs проектные хуки
Хуки безопасности (секреты, бюджет) — ставь глобально (~/.claude/settings.json). Они защищают тебя во всех проектах.
Хуки специфичные для проекта (линтер, тесты, деплой) — ставь проектно (.claude/settings.json). Их можно коммитить в git и шарить с командой.
~/.claude/settings.json ← Безопасность (все проекты)
└── PreToolUse: no-secrets
└── PreToolUse: budget-check
.claude/settings.json ← Проектные (этот проект)
└── PostToolUse: run-linter
└── Stop: run-testsВсе уровни объединяются. Глобальные + проектные + локальные хуки работают вместе.
Переменные окружения в хуках
Внутри command-хука доступны:
| Переменная | Что содержит |
|---|---|
$CLAUDE_PROJECT_DIR |
Корень проекта (оборачивай в кавычки!) |
$CLAUDE_ENV_FILE |
Путь для сохранения env-переменных на всю сессию |
Пример использования:
#!/bin/bash
# Запуск скрипта из папки проекта
"$CLAUDE_PROJECT_DIR"/.claude/hooks/my-check.shПрактика
Задание: Изучить структуру settings.json
- Открой или создай файл
.claude/settings.json - Попроси Claude Code:
Покажи мне текущие настройки хуков - Попроси создать самый простой хук:
Создай хук: когда Claude завершает ответ, выводи уведомление "Готово"— нажми yes - Проверь что settings.json обновился: посмотри новую запись в разделе
Stop(CamelCase!) - Протестируй: задай Claude любой простой вопрос — должно появиться уведомление
- Набери
/hooksв Claude Code — убедись что хук виден в списке
Цель: понять что settings.json — единая точка конфигурации всех хуков, хуки работают автоматически без твоего участия
Инструменты и ресурсы
.claude/settings.json— проектный файл хуков (коммитить в git)~/.claude/settings.json— глобальный файл хуков (все проекты)/hooks— команда для просмотра настроенных хуков в Claude Codejq— инструмент для парсинга JSON в bash-скриптах (нужен для command-хуков)osascript— Mac OS команда для отправки нативных уведомлений- Официальная документация (актуальный reference): https://code.claude.com/docs/en/hooks — все lifecycle events, форматы JSON, exit codes
- Продвинутые события: урок Hook-Deny-By-Design — практика SubagentStop, PreCompact, PermissionRequest
Источники
- https://code.claude.com/docs/en/hooks — official reference (проверено в октябре 2026)
- Урок Hook-Deny-By-Design — продвинутые события на практике
Ключевые выводы
Hooks ≠ Skills. Скиллы вызываешь сам. Хуки работают автоматически при событии — ты их настраиваешь один раз.
Около 30 типов событий, но начинай с 4-6 основных: PreToolUse, PostToolUse, Stop, Notification, SessionStart, UserPromptSubmit.
5 типов обработчиков: command (bash), http (webhook), mcp_tool, prompt (AI-проверка), agent (субагент). Для старта хватит command.
Matcher фильтрует по инструменту:
"Write|Edit"— только файловые операции,"Bash"— только команды.
Exit code 2 = блокировка, exit code 0 = разрешить. Не 1, а именно 2 блокирует!
Хуки хранятся в settings.json на трёх уровнях: глобальный, проектный, локальный. Все объединяются.
Что дальше
Отметка хранится только в этом браузере и никуда не отправляется. Мой прогресс