# Хуки Claude Code: практическое руководство

URL: https://agentvera.dev/ru/blog/claude-code-hooks-guide/ · Опубликовано: 2026-10-23

Как работают хуки Claude Code: события, settings.json, matcher, коды выхода и JSON-ответ, плюс готовые хуки для форматирования, блокировки опасных команд и уведомлений.

**Коротко:**

- Хуки описываются под ключом hooks в settings.json и срабатывают всегда, потому что их запускает Claude Code, а не модель.
- Чтобы заблокировать вызов инструмента, хук PreToolUse завершается с кодом 2 или возвращает JSON с permissionDecision, равным deny; код выхода 1 ничего не блокирует.
- Хук с deny блокирует вызовы даже при --dangerously-skip-permissions, но хуки не песочница: они работают с правами вашего пользователя.

Хуки Claude Code — это команды, которые Claude Code сам запускает в фиксированные моменты сессии: перед вызовом инструмента, после правки файла, при отправке промпта, когда Claude останавливается или ему нужно ваше внимание. Они описываются под ключом `hooks` в `settings.json`. Хук может добавить контекст, отформатировать файл или заблокировать действие, завершившись с кодом 2 или вернув JSON-решение. В отличие от инструкций в `CLAUDE.md`, хук срабатывает всегда, потому что его запускает среда выполнения, а не модель.

В этом руководстве: важные события, формат конфигурации, matcher, коды выхода и JSON-ответ, три хука, которые можно скопировать сегодня, и замечания по безопасности, которые стоит прочитать до добавления любого хука. Факты взяты из официального [справочника по хукам](https://code.claude.com/docs/en/hooks "Справочник по хукам Claude Code") и [руководства по хукам](https://code.claude.com/docs/en/hooks-guide "Руководство по хукам Claude Code"). Если нужно только короткое определение, см. [статью глоссария о хуках Claude Code](/ru/glossary/claude-code-hooks/ "Хуки Claude Code").

## Зачем нужны хуки, если есть инструкции

В `CLAUDE.md` можно написать «всегда запускай Prettier после правок», и Claude обычно так и сделает. «Обычно» — вот в чём проблема. Инструкции — это совет, который модель взвешивает вместе со всем остальным в своём контексте. Хуки — это код, который выполняется каждый раз, когда срабатывает событие.

Поэтому хуки подходят для трёх видов правил:

- **То, что должно происходить всегда**: форматирование, линтинг, логирование.
- **То, чего не должно происходить никогда**: правка `.env` или `rm -rf` не в той папке.
- **То, о чём вы хотите знать**: например, Claude ждёт ответа на запрос разрешения, пока вы в другом окне.

Советы по стилю и знания о проекте держите в [CLAUDE.md](/ru/blog/claude-md-agents-md/ "CLAUDE.md и AGENTS.md"), а жёсткие правила — в хуках.

## События хуков, которые вам реально понадобятся

В справочнике больше тридцати событий, и список растёт с новыми релизами. В большинстве реальных настроек используется несколько:

| Событие | Когда срабатывает | Может ли блокировать? |
| --- | --- | --- |
| `PreToolUse` | Перед запуском вызова инструмента | Да, блокирует вызов |
| `PostToolUse` | После успешного вызова инструмента | Нет, инструмент уже отработал; stderr уходит Claude |
| `UserPromptSubmit` | Когда вы отправляете промпт | Да, промпт не доходит до Claude |
| `Notification` | Когда Claude Code отправляет уведомление, например запрос разрешения или ожидание | Нет |
| `Stop` | Когда Claude заканчивает ответ | Да, Claude продолжает работать |
| `SubagentStart` / `SubagentStop` | Когда субагент запускается или завершается | Только `SubagentStop` |
| `SessionStart` | При запуске, возобновлении, `/clear` или сжатии | Нет, но stdout становится контекстом |
| `PreCompact` | Перед сжатием контекста | Да, блокирует сжатие |
| `PermissionRequest` | Когда вот-вот появится диалог разрешения | Только через JSON, не через exit 2 |
| `SessionEnd` | Когда сессия заканчивается | Нет |

Большинство задач закрывают `PreToolUse` и `PostToolUse`. Для «сообщи мне, когда готово или завис» подходят `Notification` и `Stop`.

## Как хуки настраиваются в settings.json

Хуки живут в тех же файлах настроек, что и разрешения:

| Файл | Область | Передаётся через git? |
| --- | --- | --- |
| `~/.claude/settings.json` | Все ваши проекты | Нет |
| `.claude/settings.json` | Один проект | Да |
| `.claude/settings.local.json` | Один проект, только вы | Нет (в gitignore) |
| Managed policy settings | Вся организация | Задают администраторы |

Плагины могут поставлять хуки в `hooks/hooks.json`, а skills и субагенты — описывать хуки в своём frontmatter.

Структура состоит из трёх уровней: событие, группа matcher и список обработчиков.

```json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write",
            "timeout": 30
          }
        ]
      }
    ]
  }
}
```

`type` обработчика может быть `command` (shell-команда), `http` (POST на URL), `mcp_tool` (инструмент подключённого MCP-сервера), `prompt` (быстрая проверка «да/нет» моделью) или `agent` (экспериментальная проверка субагентом). Таймаут по умолчанию — 600 секунд для обработчиков command, HTTP и MCP tool, 30 секунд для хуков prompt и 60 для хуков agent.

Каждый хук получает JSON на stdin. Общие поля: `session_id`, `transcript_path`, `cwd`, `permission_mode` и `hook_event_name`. События инструментов добавляют `tool_name`, `tool_input` и `tool_use_id`. Ваш скрипт читает этот JSON, обычно через `jq`, и решает, что делать. Переменная окружения `CLAUDE_PROJECT_DIR` указывает на корень проекта, что удобно для ссылок на скрипты из репозитория.

Введите `/hooks` в Claude Code, чтобы посмотреть, что загружено и из какого файла пришёл каждый хук. Браузер хуков работает только на чтение, поэтому менять хуки нужно, редактируя JSON.

## Matcher: какие вызовы инструментов видит хук

`matcher` определяет, какие вызовы запускают хук. Для событий инструментов он сопоставляется с именем инструмента:

| Matcher | Значение |
| --- | --- |
| `"*"`, `""` или без matcher | Каждый вызов |
| `"Bash"` | Именно инструмент Bash |
| `"Edit\|Write"` | Edit или Write (список) |
| `"mcp__memory__.*"` | Каждый инструмент MCP-сервера `memory` |
| `"mcp__.*__write.*"` | Любой инструмент MCP, имя которого начинается с `write` |

Правило простое. Если matcher содержит только буквы, цифры, `_`, `-`, пробелы, запятые или `|`, это точное имя или список имён. Любой другой символ превращает его в регулярное выражение JavaScript. Инструменты MCP называются `mcp__<server>__<tool>`.

Некоторые события игнорируют matcher, в том числе `UserPromptSubmit` и `Stop`, потому что сопоставлять нечего. Другие сопоставляют не имя инструмента. `SessionStart` сопоставляет способ запуска сессии (`startup`, `resume`, `clear`, `compact`), а `Notification` — тип уведомления, например `permission_prompt` или `idle_prompt`.

События инструментов также принимают поле `if` с синтаксисом правил разрешений, так что хук Bash может запускаться только для, скажем, `"Bash(git *)"`. В документации это описано как фильтр по принципу «лучшее из возможного», поэтому настоящую проверку держите в скрипте.

## Коды выхода и JSON-ответ

Командный хук отвечает Claude Code двумя способами: кодом выхода и необязательным JSON в stdout.

| Код выхода | Что происходит |
| --- | --- |
| `0` | Успех. stdout разбирается как JSON, если это один JSON-объект. Для `UserPromptSubmit` и `SessionStart` простой текст в stdout добавляется в контекст Claude. |
| `2` | Блокирующая ошибка. stderr — это причина. В `PreToolUse` вызов отменяется, в `UserPromptSubmit` промпт отклоняется, в `Stop` Claude продолжает работу. |
| Любой другой, включая `1` | Неблокирующая ошибка. Claude Code отмечает её и идёт дальше. |

Ловушка здесь — код выхода 1. Многие скрипты по умолчанию падают с 1, и это **не** блокирует ничего. Если вы имеете в виду «остановить», выходите с 2.

Для более тонкого управления завершайтесь с 0 и выводите JSON. Хук `PreToolUse` может разрешить, запретить или спросить:

```json
{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "deny",
    "permissionDecisionReason": "Use rg instead of grep for better performance"
  }
}
```

`permissionDecision` принимает `allow`, `deny`, `ask` или `defer`. Хук также может переписать вызов через `updatedInput` или передать Claude дополнительный текст через `additionalContext`. Поля, работающие для любого события, включают `continue: false` (полностью остановить Claude, с `stopReason`) и `systemMessage` (предупреждение, которое видите вы).

Если подходит несколько хуков, они выполняются параллельно, и побеждает самый строгий ответ: deny сильнее defer, defer сильнее ask, ask сильнее allow. `allow` от хука не отменяет правило deny в ваших разрешениях.

## Пример 1: форматировать файлы после каждой правки

С этого хука начинает большинство. Он запускает Prettier для любого файла, который пишет или правит Claude:

```json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
          }
        ]
      }
    ]
  }
}
```

Для других языков подставьте `ruff format`, `gofmt -w` или `rustfmt`. Поскольку форматтер запускается после правки, Claude увидит отформатированный файл при следующем чтении, а вы перестанете встречать в ревью diff, где меняется только стиль.

## Пример 2: блокировать опасные команды и защищённые файлы

Хук `PreToolUse` — место для жёстких ограничений. Этот скрипт, адаптированный из официального руководства, блокирует правки чувствительных файлов. Сохраните его как `.claude/hooks/protect-files.sh`:

```bash
#!/bin/bash
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')

PROTECTED_PATTERNS=(".env" "package-lock.json" ".git/")

for pattern in "${PROTECTED_PATTERNS[@]}"; do
  if [[ "$FILE_PATH" == *"$pattern"* ]]; then
    echo "Blocked: $FILE_PATH matches protected pattern '$pattern'" >&2
    exit 2
  fi
done

exit 0
```

Сделайте его исполняемым командой `chmod +x .claude/hooks/protect-files.sh`, затем зарегистрируйте:

```json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/protect-files.sh"
          }
        ]
      }
    ]
  }
}
```

Тот же приём работает для shell-команд. Сопоставьте `Bash`, прочитайте `.tool_input.command` и выходите с 2, если там есть то, что вам не нужно никогда, например `rm -rf /`, `git push --force` или `DROP TABLE`. Помните, что проверку по строке легко обойти, поэтому считайте её ремнём безопасности, а не замком.

## Пример 3: получить уведомление на рабочем столе

Долгие задачи останавливаются и ждут вас чаще, чем хотелось бы. Хук `Notification` сообщит об этом сразу. В macOS:

```json
{
  "hooks": {
    "Notification": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "osascript -e 'display notification \"Claude Code needs your attention\" with title \"Claude Code\"'"
          }
        ]
      }
    ]
  }
}
```

В Linux используйте вместо этого `notify-send 'Claude Code' 'Claude Code needs your attention'`. Задайте matcher `permission_prompt`, если вас интересуют только запросы разрешений, или добавьте хук `Stop` с той же командой, чтобы узнавать, когда Claude закончил.

## Ещё полезные приёмы

- **Вернуть контекст после сжатия.** Хук `SessionStart` с matcher `compact` может сделать `echo` короткого напоминания о ваших правилах. Его stdout добавляется в новый контекст.
- **Аудит изменений конфигурации.** Хук `ConfigChange` может дописывать каждое изменение настроек в лог-файл.
- **Контроль качества на Stop.** Хук `Stop` может запускать ваши тесты и завершаться с 2, передав сбои, чтобы Claude продолжал исправлять. Проверяйте поле `stop_hook_active` во входных данных, чтобы не попасть в бесконечный цикл. Кроме того, Claude Code отключает хук Stop после нескольких блокировок подряд.
- **Автоодобрение одного безопасного запроса.** Хук `PermissionRequest` может ответить на конкретный диалог с помощью `{"behavior": "allow"}` внутри объекта решения. Делайте matcher узким.

## Замечания по безопасности перед добавлением хуков

Хуки выполняются как shell-команды с правами вашего пользователя, без вопросов. В этом и смысл, и риск.

- **Читайте хуки, прежде чем доверять репозиторию.** `.claude/settings.json` проекта может содержать хуки. Просматривайте их так же, как скрипт `postinstall`.
- **Заключайте переменные в кавычки.** Входные данные хука приходят от модели, а модель читает файлы и веб-страницы, где может быть [prompt injection](/ru/glossary/prompt-injection/ "Prompt injection"). Используйте `"$VAR"`, никогда не применяйте eval ко входным данным и предпочитайте `jq` самодельному разбору.
- **Используйте абсолютные или относительные к проекту пути** через `$CLAUDE_PROJECT_DIR`, чтобы хук не зависел от текущей папки.
- **Держите хуки быстрыми.** Медленный хук `PreToolUse` замедляет каждый вызов инструмента. Задайте `timeout`.
- **Хуки — не песочница.** Хук deny блокирует вызовы даже при `--dangerously-skip-permissions`, и это полезно, но настойчивый или запутавшийся агент может прийти к тому же результату другим путём. Сочетайте хуки с правилами deny и изоляцией, как описано в статьях [безопасность ИИ-агентов для кода](/ru/blog/ai-coding-agent-security/ "Безопасность ИИ-агентов для кода") и [безопасный пропуск разрешений](/ru/blog/claude-code-skip-permissions/ "Claude Code --dangerously-skip-permissions").
- **Знайте выключатели.** `"disableAllHooks": true` отключает хуки, а администраторы могут задать `allowManagedHooksOnly` в managed settings, чтобы заблокировать пользовательские и проектные хуки.

Если хук ведёт себя странно, запустите Claude Code с `claude --debug` или пишите лог в файл через `--debug-file /tmp/claude.log`, чтобы увидеть matcher, код выхода и вывод каждого хука.

## Как AgentVera использует хуки

AgentVera — десктопное приложение, которое запускает Claude Code, Codex, Gemini CLI и другие кодовые CLI рядом друг с другом. Хуки — важная часть того, как оно работает с Claude Code.

- **Ваши хуки остаются вашими.** AgentVera передаёт собственные хуки каждому процессу Claude Code через флаг `--settings`. Claude Code объединяет их с хуками из ваших файлов настроек, а ваш `settings.json` не редактируется.
- **Статус агента берётся из хуков.** Статус, который каждый агент показывает в приложении, читается из собственных событий хуков CLI, а не угадывается по тексту терминала.
- **Smart tools — это хуки.** Функция [smart tools](/ru/features/smart-tools/ "Smart tools") добавляет четыре хука локальным агентам Claude Code: блокирует повторное чтение одного и того же файла, запускает только те тесты, которых касается правка, проверяет ошибки сразу после правки и делит результаты между агентами. Они включены по умолчанию, и их можно отключить в Settings → “Token saving”.
- **Скрипт уведомлений не нужен.** [Уведомления и одобрения](/ru/features/notifications-and-approvals/ "Уведомления и одобрения") собирают всех агентов, ждущих одобрения, в одну очередь, отправляют уведомления на рабочий стол, пока приложение в фоне, и могут отправить сообщение на телефон через Telegram.

Qwen Code тоже получает хуки AgentVera, потому что его система хуков следует событиям и формату JSON Claude Code.

## Итоги

Начните с одного форматтера `PostToolUse` и одной защиты `PreToolUse`, проверьте их через `/hooks` и `--debug` и добавляйте новые, только когда правило продолжают нарушать. Выходите с 2, чтобы заблокировать, выводите JSON, когда нужно больше контроля, и относитесь к каждому хуку как к коду, который работает с вашими правами.

Читайте также:

- [Хуки Claude Code (глоссарий)](/ru/glossary/claude-code-hooks/ "Хуки Claude Code")
- [Smart tools](/ru/features/smart-tools/ "Smart tools")
- [Уведомления и одобрения](/ru/features/notifications-and-approvals/ "Уведомления и одобрения")
- [Агент Claude Code](/ru/agents/claude-code/ "Claude Code в AgentVera")

Чтобы попробовать AgentVera, начните с [главной страницы](/ru/ "AgentVera").

## Частые вопросы

**Что такое хуки Claude Code?** Хуки — это shell-команды, HTTP-вызовы, инструменты MCP или промпты, которые Claude Code сам запускает в заданные моменты сессии: перед вызовом инструмента, после правки файла или когда Claude нужно ваше внимание. Они описываются в settings.json.

**Где разместить хуки Claude Code?** Под ключом hooks в файле настроек: ~/.claude/settings.json для всех проектов, .claude/settings.json для проекта, которым вы делитесь через git, или .claude/settings.local.json для проекта только на вашей машине. Хуки могут задавать и плагины, skills и субагенты.

**Как хук блокирует вызов инструмента?** Хук PreToolUse либо завершается с кодом 2 и пишет причину в stderr, либо завершается с 0 и выводит JSON с permissionDecision, равным deny. Claude Code отменяет вызов и показывает причину Claude. Код выхода 1 не блокирует.

**Работают ли хуки при --dangerously-skip-permissions?** Да. Хук, вернувший deny, блокирует вызов инструмента даже в режиме bypassPermissions. Поэтому PreToolUse полезен как последний рубеж для команд, которые вам не нужны никогда, хотя песочницей он не является.

**Как отладить хук Claude Code, который не срабатывает?** Откройте /hooks, чтобы увидеть загруженные хуки и их источники, проверьте, что matcher совпадает с точным именем инструмента, и запустите Claude Code с --debug или --debug-file, чтобы увидеть каждый запуск хука, его код выхода и вывод.

---

**Об AgentVera.** AgentVera — настольное приложение для macOS, Windows и Linux от Solviera Teknoloji. Оно запускает 18 ИИ-агентов для программирования (Claude Code, Codex, Gemini CLI, Copilot, Cursor, Antigravity, opencode, Hermes, Qwen Code, Kimi Code, Kiro, Amp, Droid, Goose, Vibe, Crush, Aider, Cline) рядом, по проектам, в настоящих терминалах с собственными установками CLI и входами пользователя. В бесплатном тарифе количество агентов не ограничено. Скачать: https://agentvera.dev/ru/download/ · Цены: https://agentvera.dev/ru/pricing/
