#Закрепите правило хуком
Средний уровень · Урок 5 из 8 · около 20 минут · Нужно: Разрешения, области настроек и песочница · Сверено с Claude Code v2.1.285 (stable) 06.10.2026
#Цель
К концу урока вы сможете добавить хук, который применяет правило каждый раз, когда Claude правит файл, и показать, что он срабатывает.
#Что понадобится
- Репозиторий из урока 4 с его
.claude/settings.jsonи ваша копия шаблона для практики с Node.js LTS: проверка запускается из копии. jq, который используют скрипты хуков, иpython3, который используетformat-after-edit.sh.- Расход лимита: небольшой.
#Идея
Правило в CLAUDE.md — это совет, который Claude может пропустить. Хук — это ваша собственная команда, которую Claude Code запускает в определённый момент сессии каждый раз, что бы ни решил Claude. Claude Code передаёт хуку JSON с описанием события на stdin. Хук PreToolUse запускается перед вызовом инструмента; если он завершается с кодом 2, вызов блокируется, а то, что хук вывел в stderr, уходит Claude как причина (Hooks reference, Block edits to protected files).
Вот события, которые использует этот урок, и их место в ходе:
flowchart LR accTitle: Где в ходе срабатывают события хуков accDescr: Сессия начинается с SessionStart. Каждый промпт вызывает UserPromptSubmit. Перед каждым вызовом инструмента запускается PreToolUse; код выхода 2 блокирует вызов. После успешного вызова запускается PostToolUse, затем Claude может вызвать следующий инструмент. Когда Claude заканчивает отвечать, срабатывает Stop. Notification срабатывает отдельно — всякий раз, когда Claude Code нужно ваше внимание. S[SessionStart] --> U[UserPromptSubmit] U --> P[PreToolUse] P -->|exit 2| B[Вызов заблокирован, stderr уходит Claude] P -->|exit 0| T[Проверка разрешений, затем инструмент работает] T --> Q[PostToolUse] Q -->|следующий вызов| P Q --> E[Stop] N[Notification — когда Claude Code нужны вы]
Матчер выбирает инструменты, за которыми следит хук: Edit|Write запускает его только для этих двух инструментов (Filter hooks with matchers). Хуки PreToolUse срабатывают до проверки режима разрешений, поэтому блокировка действует в любом режиме (Hooks and permission modes).
#Разбор примера
- Скачайте в свой репозиторий два примера хуков из этого руководства и сделайте их исполняемыми. Прочитайте их, прежде чем использовать:
mkdir -p .claude/hooks
for f in protect-files format-after-edit; do
curl -fsSL "https://raw.githubusercontent.com/wesammustafa/Claude-Code-Everything-You-Need-to-Know/main/examples/intermediate/05-hooks/dot-claude/hooks/$f.sh" -o ".claude/hooks/$f.sh"
done
chmod +x .claude/hooks/*.sh
protect-files.sh — скрипт из руководства по хукам, блокирующий правки .env, package-lock.json и .git/. format-after-edit.sh убирает пробелы в конце строк исходного файла после того, как Claude его отредактировал.
2. Зарегистрируйте их в .claude/settings.json рядом с блоком permissions из урока 4:
"hooks": {
"PreToolUse": [
{ "matcher": "Edit|Write", "hooks": [ { "type": "command", "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/protect-files.sh", "args": [] } ] }
],
"PostToolUse": [
{ "matcher": "Edit|Write", "hooks": [ { "type": "command", "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/format-after-edit.sh", "args": [] } ] }
]
}
С "args": [] Claude Code запускает скрипт напрямую, без оболочки, поэтому путь не нужно брать в кавычки (Exec form and shell form).
3. Проверьте хук без Claude, подав на вход JSON, который отправил бы вызов Edit. Edit и Write всегда передают абсолютный путь (PreToolUse input), поэтому соберите его из $PWD:
echo "{\"tool_input\":{\"file_path\":\"$PWD/package-lock.json\"}}" | .claude/hooks/protect-files.sh; echo "exit $?"
Скрипт выведет строку Blocked: и exit 2.
4. Запустите claude и выполните /hooks: ваши хуки появятся в разделах PreToolUse и PostToolUse (Debug your configuration).
5. Попросите правку, от которой защищает хук. В шаблоне для практики есть package-lock.json; в своём репозитории назовите защищённый файл, который в нём есть:
Use your Edit tool, not a shell command, to change the top-level version in package-lock.json to 1.0.1.
Правка блокируется: Claude Code передаёт сообщение Blocked: вашего скрипта Claude как обратную связь (Exit code output). Здесь просите инструмент Edit по имени: Claude может отредактировать файл и командой оболочки, а её хук Edit|Write не видит.
#Ваша очередь
Скрипт из руководства сравнивает подстроки. *".env"* блокирует и .env.example, который команды коммитят намеренно, и файл вроде src/config.envelope.ts; а папку secrets/ не блокирует ничто. Замените .claude/hooks/protect-files.sh этой заготовкой — она сохраняет блокировки package-lock.json и .git/ из руководства — и допишите её:
#!/bin/bash
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
FILE_PATH="${FILE_PATH//\\//}"
NAME=$(basename "$FILE_PATH")
case "/$FILE_PATH" in
*/package-lock.json | */.git/*)
echo "Blocked: $FILE_PATH is protected" >&2
exit 2
;;
esac
# TODO: block a file named .env, or .env. followed by anything except example
# TODO: block any file inside a secrets/ folder
exit 0
- Каждая блокировка выводит причину
Blocked:в stderr и завершается с кодом 2; всё остальное завершается с кодом 0. - Прогоняйте таблицу тестов из раздела «Проверка», пока каждая строка не даст ожидаемый код выхода.
- В сессии попросите Claude создать
secrets/test.keyинструментом Write. Ваш хук это заблокирует. - Закоммитьте скрипт и
.claude/settings.json. Скрипт должен остаться исполняемым: выводgit ls-files -s .claude/hooks/protect-files.shначинается с100755.
#Проверка
Урок пройден, когда выполнено всё это:
- Каждый путь даёт ожидаемый код выхода: 2 для
.env,config/.env.local,secrets/api.key,package-lock.jsonи.git/config; 0 для.env.example,src/config.envelope.tsиsrc/app.js. Запустите это из корня репозитория:
for p in .env config/.env.local .env.example secrets/api.key src/config.envelope.ts src/app.js package-lock.json .git/config; do
printf '%s ' "$p"; echo "{\"tool_input\":{\"file_path\":\"$PWD/$p\"}}" | .claude/hooks/protect-files.sh 2>/dev/null; echo $?
done
- Скрипт закоммичен и исполняем, а закоммиченный
.claude/settings.jsonзапускает его как хукPreToolUseдляEdit|Write:git show HEAD:.claude/settings.json | jq .hooks.PreToolUseэто показывает. - Самопроверка (не тестируется): попытка Claude создать
secrets/test.keyбыла заблокирована с вашим сообщениемBlocked:.
Запустите npm run check -- i-5 --dir <your repo> из своей копии для практики или npm run check -- i-5 в самой копии.
Если какая-то строка неверна, проверьте этот путь отдельно и выведите имя, которое видит скрипт: basename от .env.local — это .env.local, поэтому шаблон case .env.* с ним совпадает. Проверка запускает закоммиченный скрипт, поэтому коммитьте каждое исправление перед запуском. Если второй пункт не проходит из-за режима файла, выполните chmod +x .claude/hooks/protect-files.sh, затем git add и закоммитьте снова.
#Осторожно
- Хуки выполняются с правами вашего пользователя: в интерактивной сессии — как только вы доверились папке, а при запуске
claude -p— без вопросов (Workspace trust). Прочитайте хуки репозитория, прежде чем доверять ему или запускать в нём Claude Code из скрипта. - Хук
Edit|Writeне видит команд оболочки:echo X >> .envидёт через Bash. ПравилаReadиз урока 4 не дают командам вродеcat .envчитать эти файлы, но запись вроде этого>>проверяется по правиламEdit, которых урок 4 не добавляет (Redirections). Для хука, который видит любое изменение, руководство по хукам добавляет матчерBash|PowerShellили хукStop, сканирующий рабочее дерево (Filter hooks with matchers). - Хук Notification, например пример
desktop-notify.sh, касается вас, а не проекта: руководство по хукам регистрирует свои примеры уведомлений в~/.claude/settings.json. Сделайте так же, указав путь к месту, где вы храните скрипт.
#Что дальше
- Automate actions with hooks: другие готовые хуки, включая уведомления и повторное внедрение контекста после сжатия.
- Hooks reference: каждое событие, его вход и выход.
- Debug your configuration: что проверить, если хук не срабатывает.
Источники: Automate actions with hooks · Hooks reference · Configure permissions · Debug your configuration
← Разрешения, области настроек и песочница · Оглавление Среднего уровня · Делегируйте задачу своему субагенту → · Тема: Хуки · Застряли на уроке?