# Хуки: правило, которое нельзя забыть

Курс: Claude Code: уровень профи — https://zero2claude.ru/learn/claude-code-pro
Канонический URL: https://zero2claude.ru/learn/claude-code-pro/2-1-huki-pretooluse

Правило в CLAUDE.md — совет, который Claude может упустить. Хук — твоя команда, которую Claude Code запускает в заданный момент всегда. Хук PreToolUse с кодом выхода 2 блокирует действие ещё до проверки разрешений.

Ты пишешь в CLAUDE.md: «никогда не правь package-lock.json». Claude следует этому почти всегда. Но «почти» — это и есть проблема: правило в памяти — совет, который модель может упустить в длинной сессии.

Хук работает иначе. Это **твоя команда**, которую Claude Code запускает в заданный момент сессии **всегда** — что бы Claude ни решил.

## События хуков

Хук привязывается к событию. Главные из них:

| Событие | Когда срабатывает |
|---|---|
| `SessionStart` | при старте сессии |
| `UserPromptSubmit` | когда ты отправил запрос |
| `PreToolUse` | перед каждым вызовом инструмента |
| `PostToolUse` | после успешного вызова инструмента |
| `Stop` | когда Claude закончил отвечать |
| `Notification` | когда Claude Code нужно твоё внимание |

Сегодня нас интересует `PreToolUse` — хук, который может **остановить** действие.

## Как PreToolUse блокирует

Перед вызовом инструмента Claude Code запускает твой скрипт и передаёт ему на вход JSON с описанием события — например, какой файл собираются править. Дальше решает код выхода:

- **0** — всё в порядке, действие идёт дальше;
- **2** — вызов **заблокирован**, а то, что скрипт напечатал в stderr, уходит Claude как причина.

Claude видит объяснение — например, «Blocked: package-lock.json защищён» — и меняет план.

Важная деталь: `PreToolUse` срабатывает **до** проверки режима разрешений. Поэтому блок держится в любом режиме, даже в Auto.

## Регистрация хука

Хуки описываются в файле настроек, рядом с правилами из прошлого уровня:

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

- `matcher` выбирает инструменты: `Edit|Write` — только правки и запись файлов;
- `${CLAUDE_PROJECT_DIR}` подставляет путь к проекту, чтобы хук находился откуда угодно;
- с `"args": []` скрипт запускается напрямую, без оболочки, и путь не нужно брать в кавычки.

Внутри сессии `/hooks` покажет, какие хуки подхватились.

Скрипт можно проверить **без Claude**: передай ему JSON, который прислал бы Claude Code, и посмотри код выхода.

```bash
echo "{\"tool_input\":{\"file_path\":\"$PWD/package-lock.json\"}}" | .claude/hooks/protect-files.sh; echo "exit $?"
```

Ожидаешь `exit 2` — значит, хук сработает и в сессии.

<MicroQuiz
  question="Хук на Edit|Write защищает .env. Claude выполнил команду echo X >> .env. Остановит ли его хук?"
  options="Нет — это команда оболочки, а хук смотрит только на Edit и Write | Да, хук видит любые изменения | Да, если включён режим Plan"
  answer="0"
  explanation="Matcher Edit|Write ловит только инструменты редактирования. Для команд нужен отдельный хук с matcher Bash или хук на Stop, который проверяет рабочее дерево."
/>

**Осторожно.** 
Хуки выполняются с правами твоего пользователя: в интерактивной сессии — после того как ты доверил папку, а в claude -p — без всякого вопроса. Прежде чем доверять чужому репозиторию или запускать в нём Claude из скрипта, прочитай его хуки.
