К содержимому
Claude Code с 0:полный курс
Claude CodeАвтор: Михаил Кузьмицкий

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

Коротко

Строчка в CLAUDE.md — совет, хук — закон. Разбираем хук PreToolUse, который блокирует правку защищённого файла кодом выхода 2, три полезных рецепта на PostToolUse, Notification и Stop, и границу, о которой забывают даже опытные.

Ты пишешь в 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 видит объяснение и меняет план, вместо того чтобы молча упереться в ошибку. Важная деталь: PreToolUse срабатывает до проверки режима разрешений. Поэтому блок держится в любом режиме, даже в Auto.

Простой охранник может выглядеть так — сохрани его в .claude/hooks/protect-files.sh и сделай исполняемым (chmod +x):

#!/bin/bash
file=$(jq -r '.tool_input.file_path // empty')
case "$file" in
  */package-lock.json|*/.env)
    echo "Blocked: $file защищён, не правь его" >&2
    exit 2 ;;
esac
exit 0

И зарегистрируй в .claude/settings.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} подставляет путь к проекту, чтобы хук находился, откуда бы ты ни запустил Claude;
  • с "args": [] скрипт запускается напрямую, без оболочки, и путь не нужно брать в кавычки.

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

Проверь хук без Claude

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

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

Видишь exit 2 — значит, хук сработает и в сессии. Видишь exit 0 на защищённом файле — ищи ошибку в скрипте до того, как она молча сломает тебе каждую сессию.

Три рецепта, которые окупаются сразу

Блокировать — не единственное, что умеют хуки.

Прибраться после правки — PostToolUse. Повесь его на Edit|Write, и после каждой правки файла запустится форматтер или линтер. Целый класс просьб «а теперь поправь отступы» исчезает.

Позвать тебя — Notification. Ты ушёл за чаем, а Claude давно ждёт подтверждения. Хук на Notification покажет системное уведомление или проиграет звук. Такой хук — про тебя, а не про проект: на Mac и Linux уведомления делаются по-разному. Поэтому регистрируй его в своём ~/.claude/settings.json, а не в настройках репозитория.

Проверить в конце — Stop. Stop срабатывает, когда Claude закончил отвечать. Это лучшее место, чтобы одним махом проверить всё рабочее дерево: не изменились ли защищённые файлы, проходят ли быстрые тесты.

Быстрое — в PostToolUse, тяжёлое — в Stop

Хук выполняется на каждом событии. Полный прогон тестов в PostToolUse замедлит каждую правку. Туда клади быстрое: форматирование, проверку одного файла. Тяжёлые проверки ставь на Stop — один раз на ответ.

Граница, о которой забывают

Охранник с matcher: "Edit|Write" видит только инструменты редактирования. Если Claude изменит файл командой оболочки — echo X >> .env, sed -i, rm, — хук ничего не заметит: команды идут через инструмент Bash.

Закрыть эту дыру можно двумя способами:

  • отдельный хук с matcher: "Bash", который разбирает команду;
  • хук на Stop, который в конце ответа проверяет рабочее дерево. Ему всё равно, как сделано изменение, — он смотрит на результат.

Для действительно важных файлов разумно иметь оба: охранник на PreToolUse останавливает очевидную правку сразу, а проверка на Stop ловит всё остальное.

Хуки — это код с твоими правами

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

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

Чем хук отличается от правила в CLAUDE.md?

CLAUDE.md — это контекст, который модель учитывает, но может упустить. Хук — команда, которую Claude Code запускает сам на заданном событии, всегда. Всё, что должно выполняться без исключений, оформляй хуком.

Как хук PreToolUse блокирует действие?

Скрипт хука завершается с кодом выхода 2. Вызов инструмента отменяется, а текст из stderr уходит Claude как причина. Код 0 пропускает действие дальше.

Работает ли блокировка в режиме Auto?

Да. PreToolUse срабатывает до проверки режима разрешений, поэтому блок держится в любом режиме.

Почему хук на Edit|Write не заметил изменение .env?

Скорее всего, файл поменяли командой оболочки, например echo X >> .env. Такие команды идут через инструмент Bash. Для них нужен отдельный хук с matcher Bash или хук на Stop, который проверяет рабочее дерево.

Где потренироваться

Второй уровень курса «Claude Code: уровень профи» начинается именно с этого: урок «Хуки: правило, которое нельзя забыть» и урок «Рецепты хуков», оба с тренажёром в браузере. Если хочешь начать с самых основ, загляни в наш ранний разбор «Hooks в Claude Code», а все события и флаги в одном месте собраны в шпаргалке по Claude Code.

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

Попробуй на практике

Бесплатные интерактивные курсы по теме — прямо в браузере, с нуля.