Ты пишешь в 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.
Регистрация хука
Хуки описываются в файле настроек, рядом с правилами из прошлого уровня:
{
"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, и посмотри код выхода.
echo "{\"tool_input\":{\"file_path\":\"$PWD/package-lock.json\"}}" | .claude/hooks/protect-files.sh; echo "exit $?"
Ожидаешь exit 2 — значит, хук сработает и в сессии.
Мини-проверка
Хук на Edit|Write защищает .env. Claude выполнил команду echo X >> .env. Остановит ли его хук?
Осторожно
Хуки выполняются с правами твоего пользователя: в интерактивной сессии — после того как ты доверил папку, а в claude -p — без всякого вопроса. Прежде чем доверять чужому репозиторию или запускать в нём Claude из скрипта, прочитай его хуки.
Практика в терминале