Claude Code умеет писать код, запускать команды в терминале, редактировать любые файлы и пушить в репозиторий. Удобно ровно до момента, когда агент случайно сделает git push --force в main, запишет ключ от продакшна в логи или удалит миграцию, которую вы три недели готовили.
Хуки — это страховка. Маленькие скрипты, которые срабатывают в нужный момент жизненного цикла Claude Code и либо блокируют опасное действие, либо что-то делают за вас автоматически (форматируют файл, логируют команду, шлют уведомление).
В этой статье собрали 10 готовых защитных хуков с копипастом, разобрали жизненный цикл событий, объяснили exit codes и показали, как тестировать хук, не ломая боевой проект. Базу про сам инструмент мы разбирали в обзорной статье «Что такое Claude Code» — там про установку, тарифы и первый запуск.
Если вы ещё не знакомы с другими «китами» расширений CC, рядом полезно держать материалы про slash-команды Claude Code и про MCP-серверы: вместе с хуками они закрывают почти всё, что нужно от кастомизации агента.
Гайд написан так, чтобы пригодился и разработчику, и маркетологу, который пользуется Claude Code для работы с текстами и таблицами. Программистские примеры даём с разбором, что делает каждая строчка. Если хочется системно освоить нейросетевые инструменты, загляните в нашу подборку курсов по нейросетям и искусственному интеллекту: 316 программ от коротких интенсивов до годовых.
Что такое hooks в Claude Code простыми словами
Hook — это shell-команда, HTTP-запрос или вызов MCP-инструмента, который Claude Code запускает сам, без вашего участия, когда наступает определённое событие: агент собирается отредактировать файл, закончил отвечать, выполнил bash, стартовал новую сессию.
Главное отличие хука от skills и MCP-серверов — детерминизм. Skill — это инструкция, которой модель может последовать, а может и нет (решает Claude). MCP-сервер — это инструмент, который модель может вызвать, если посчитает нужным. Хук срабатывает всегда, когда выполнено его условие, и модель не может его обойти. Поэтому хуки годятся для правил безопасности: «никогда не давай агенту удалять файлы БД», «всегда форматируй Python после правки», «обязательно проверь, что в коммите нет ключей».
Для непрограммистов: представьте, что Claude — это стажёр, которому вы дали ключи от офиса и разрешили работать ночью. Skill — это наклейка на холодильнике «не забудь выключить свет». MCP — это связка ключей от разных кабинетов. Хук — это датчик движения, который автоматически блокирует серверную, если стажёр туда заходит после полуночи.
Когда срабатывают хуки
В Claude Code есть больше двух десятков событий жизненного цикла. Большинство хуков пишут под четыре самых ходовых, остальные обычно нужны для редких сценариев. Вот таблица с разбором, что когда стреляет.
| Событие | Когда срабатывает | Может ли заблокировать действие |
|---|---|---|
PreToolUse |
До вызова любого инструмента (Bash, Edit, Write и т. д.) | Да |
PostToolUse |
После успешного выполнения инструмента | Нет, инструмент уже отработал |
UserPromptSubmit |
После отправки сообщения, до ответа модели | Да |
Stop |
Когда Claude закончил отвечать | Да, можно заставить продолжить |
SessionStart |
В начале сессии или при возобновлении | Нет |
SessionEnd |
При выходе из сессии | Нет, только для очистки |
SubagentStop |
Когда субагент закончил задачу | Да |
PreCompact |
До сжатия контекста | Да |
Notification |
Когда Claude шлёт уведомление | Нет |
Из всех них на долю PreToolUse и PostToolUse приходится примерно 80 % всех боевых хуков. Первый проверяет действия до выполнения и умеет блокировать, второй реагирует на уже совершённое и используется для уборки и уведомлений.
Полный референс со всеми событиями и полями ввода-вывода лежит в официальной документации Anthropic. Заглядывайте туда, когда нужен экзотический случай вроде WorktreeCreate или FileChanged.
Где живут хуки и как их подключить
Хуки описывают в файле settings.json. Файл этот может лежать в трёх местах, и это важно понимать, потому что от местоположения зависит, на каких проектах хук будет работать.
| Где лежит | На каких проектах работает | Коммитится ли в git |
|---|---|---|
~/.claude/settings.json |
На всех ваших проектах | Нет, личный конфиг |
.claude/settings.json в корне проекта |
Только в этом проекте | Да, шарится с командой |
.claude/settings.local.json в проекте |
Только в этом проекте | Нет, в .gitignore |
Правило большого пальца: защитные хуки против себя самого (запрет force-push, защита .env) кладите в ~/.claude/settings.json, чтобы работали везде. Командные правила (форматирование, валидация коммитов) кладите в .claude/settings.json в корне проекта, чтобы автоматически подхватились у коллег после git pull. Эксперименты и что-то сугубо личное — в .claude/settings.local.json.
Базовая структура одинаковая для всех мест:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "/Users/me/.claude/hooks/check-bash.sh"
}
]
}
]
}
}
Разберём по слоям. hooks — корневой ключ. Внутри — имя события (PreToolUse). Внутри события — массив правил, у каждого есть matcher (на какие инструменты реагировать — Bash, Edit, Write|Edit, mcp__memory__.* или пусто/* для всех) и массив hooks с конкретными обработчиками. Каждый обработчик — это объект с типом (command, http, mcp_tool, prompt, agent) и тем, что запускать.
Для проверки настройки используйте slash-команду /hooks прямо в Claude Code — она открывает встроенный браузер со всеми подключёнными хуками по событиям. Полный список slash-команд мы разбирали в статье «37 команд Claude Code».
Exit codes — главный механизм блокировки
Хук общается с Claude Code через стандартные потоки и exit code. Запомните три числа:
- Exit 0 — всё хорошо. Если в stdout есть JSON, Claude его разберёт и применит решения оттуда. Если ничего нет — действие пропускается дальше.
- Exit 2 — блокирующая ошибка. Содержимое stderr Claude покажет как сообщение об ошибке и остановит действие (если событие умеет блокировать — см. таблицу выше).
- Любой другой ненулевой — неблокирующая ошибка. Stderr попадёт в debug-лог, но действие пройдёт.
Это значит, что любой защитный хук работает по одному и тому же шаблону: проверь условие, если плохо — напиши причину в stderr и сделай exit 2, иначе exit 0.
На вход хук получает JSON в stdin с информацией о событии: какой инструмент вызывается, с какими аргументами, в какой директории, какой ID сессии. Для PreToolUse с matcher Bash, например, придёт примерно такое:
{
"session_id": "abc123",
"cwd": "/Users/me/projects/checkroi",
"hook_event_name": "PreToolUse",
"tool_name": "Bash",
"tool_input": {
"command": "git push --force origin main"
}
}
Хук читает этот JSON, парсит, решает, что делать, и возвращает результат через exit code.
10 защитных хуков для Claude Code
Дальше — готовые шаблоны. Все скрипты пишем на bash, потому что он есть везде и для простых проверок этого хватает. Кладите их в ~/.claude/hooks/, не забывайте chmod +x, прописывайте в settings.json.
Чтобы парсить входящий JSON, используем утилиту jq — ставится из brew/apt одной командой и работает в однострочниках лучше, чем sed/grep.
1 — Запрет git push —force в main
Зачем: один git push --force origin main от агента, и вы потеряли историю коммитов вместе с работой коллег.
Скрипт ~/.claude/hooks/block-force-push.sh:
#!/usr/bin/env bash
input=$(cat)
cmd=$(echo "$input" | jq -r '.tool_input.command // ""')
if echo "$cmd" | grep -Eq 'git push.*(--force|-f)(\s|$).*\b(main|master|production)\b'; then
echo "Блокирую: force-push в защищённую ветку. Используй git push без --force или создай PR." >&2
exit 2
fi
exit 0
Конфиг в ~/.claude/settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{ "type": "command", "command": "/Users/me/.claude/hooks/block-force-push.sh" }
]
}
]
}
}
2 — Защита env-файлов и секретов от чтения
Зачем: если агент прочитает .env, ключи попадут в контекст модели и могут утечь в логи Anthropic, в транскрипты или в коммит-сообщение. Лучше просто запретить.
Скрипт ~/.claude/hooks/protect-secrets.sh:
#!/usr/bin/env bash
input=$(cat)
tool=$(echo "$input" | jq -r '.tool_name // ""')
path=$(echo "$input" | jq -r '.tool_input.file_path // .tool_input.path // ""')
case "$path" in
*.env|*.env.local|*.env.production|*/credentials|*/credentials.json|*id_rsa|*id_ed25519|*.pem|*.key)
echo "Блокирую $tool для $path: файл содержит секреты. Если правка нужна — отредактируй вручную." >&2
exit 2
;;
esac
exit 0
Подключение — matcher Read|Edit|Write (это регулярка, ловит три инструмента сразу):
{
"hooks": {
"PreToolUse": [
{
"matcher": "Read|Edit|Write",
"hooks": [
{ "type": "command", "command": "/Users/me/.claude/hooks/protect-secrets.sh" }
]
}
]
}
}
3 — Блокировка опасных bash-команд
Зачем: rm -rf /, DROP TABLE, terraform destroy, kubectl delete namespace — все они потенциально необратимы. Лучше один раз отбить, чем потом восстанавливать.
Скрипт ~/.claude/hooks/block-dangerous.sh:
#!/usr/bin/env bash
input=$(cat)
cmd=$(echo "$input" | jq -r '.tool_input.command // ""')
patterns=(
'rm[[:space:]]+-rf?[[:space:]]+/'
'rm[[:space:]]+-rf?[[:space:]]+~'
'\bDROP[[:space:]]+(TABLE|DATABASE|SCHEMA)\b'
'\bTRUNCATE[[:space:]]+TABLE\b'
'terraform[[:space:]]+destroy'
'kubectl[[:space:]]+delete[[:space:]]+namespace'
'dd[[:space:]]+if=.*of=/dev/[sh]d'
':\(\)\{.*\|.*&\}'
'mkfs\.'
)
for p in "${patterns[@]}"; do
if echo "$cmd" | grep -Eiq "$p"; then
echo "Блокирую опасную команду: $cmd" >&2
echo "Сработал паттерн: $p" >&2
exit 2
fi
done
exit 0
Цепляется на PreToolUse с matcher Bash — как и первый хук. Кстати, эти хуки можно ставить в один матчер: Claude вызовет их все по очереди, и если хотя бы один вернёт exit 2 — действие заблокируется.
4 — Валидация сообщения коммита
Зачем: чтобы агент не писал в коммитах «fix», «update», «wip». Хороший коммит начинается с типа (feat, fix, refactor, docs, chore, test) и короткого описания.
Скрипт ~/.claude/hooks/validate-commit-msg.sh:
#!/usr/bin/env bash
input=$(cat)
cmd=$(echo "$input" | jq -r '.tool_input.command // ""')
if ! echo "$cmd" | grep -qE '^git commit'; then
exit 0
fi
msg=$(echo "$cmd" | grep -oE -- '-m[[:space:]]*"[^"]+"' | sed -E 's/^-m[[:space:]]*"(.+)"$/\1/' | head -1)
if [ -z "$msg" ]; then
echo "Не нашёл сообщение коммита через -m. Если используешь -F или редактор — добавь --no-verify в bash-команду для пропуска." >&2
exit 2
fi
if ! echo "$msg" | grep -qE '^(feat|fix|refactor|docs|chore|test|style|perf)(\(.+\))?:[[:space:]].{10,}'; then
echo "Сообщение коммита не проходит проверку Conventional Commits." >&2
echo "Текущее: $msg" >&2
echo "Формат: <тип>: <описание минимум 10 символов>. Примеры типов: feat, fix, refactor, docs, chore, test." >&2
exit 2
fi
exit 0
5 — Авто-форматирование после Edit
Зачем: чтобы вам не приходилось каждый раз напоминать «отформатируй файл». Сразу после правки запускается prettier, black или gofmt — в зависимости от расширения.
Это уже PostToolUse, не PreToolUse: блокировать тут нечего, файл уже изменён.
Скрипт ~/.claude/hooks/auto-format.sh:
#!/usr/bin/env bash
input=$(cat)
path=$(echo "$input" | jq -r '.tool_input.file_path // ""')
[ -z "$path" ] || [ ! -f "$path" ] && exit 0
case "$path" in
*.js|*.jsx|*.ts|*.tsx|*.json|*.css|*.scss|*.md|*.html|*.yaml|*.yml)
command -v prettier >/dev/null && prettier --write --log-level error "$path" 2>/dev/null
;;
*.py)
command -v black >/dev/null && black --quiet "$path" 2>/dev/null
;;
*.go)
command -v gofmt >/dev/null && gofmt -w "$path" 2>/dev/null
;;
*.rs)
command -v rustfmt >/dev/null && rustfmt --quiet "$path" 2>/dev/null
;;
esac
exit 0
Конфиг:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write|MultiEdit",
"hooks": [
{ "type": "command", "command": "/Users/me/.claude/hooks/auto-format.sh" }
]
}
]
}
}
6 — Защита миграций и lock-файлов от удаления
Зачем: package-lock.json, yarn.lock, Cargo.lock, файлы миграций в migrations/ — это история состояния проекта. Их удаление через rm или перезапись пустотой — почти всегда ошибка.
Скрипт ~/.claude/hooks/protect-history.sh:
#!/usr/bin/env bash
input=$(cat)
tool=$(echo "$input" | jq -r '.tool_name // ""')
cmd=$(echo "$input" | jq -r '.tool_input.command // ""')
path=$(echo "$input" | jq -r '.tool_input.file_path // ""')
protected_regex='(package-lock\.json|yarn\.lock|pnpm-lock\.yaml|Cargo\.lock|Gemfile\.lock|poetry\.lock|go\.sum)$|/migrations/'
if [ "$tool" = "Bash" ] && echo "$cmd" | grep -Eq "rm[[:space:]]+.*($protected_regex)"; then
echo "Блокирую удаление защищённого файла. Это критичный артефакт состояния проекта." >&2
exit 2
fi
if [ -n "$path" ] && echo "$path" | grep -Eq "$protected_regex"; then
if [ "$tool" = "Write" ]; then
echo "Блокирую перезапись $path. Используй пакетный менеджер для обновления lock-файлов." >&2
exit 2
fi
fi
exit 0
7 — Лог всех bash-команд в файл
Зачем: чтобы потом можно было разобрать, что именно агент делал. Особенно полезно, когда оставляете Claude работать в auto-режиме на ночь.
Скрипт ~/.claude/hooks/log-bash.sh:
#!/usr/bin/env bash
input=$(cat)
cmd=$(echo "$input" | jq -r '.tool_input.command // ""')
sid=$(echo "$input" | jq -r '.session_id // "no-session"')
cwd=$(echo "$input" | jq -r '.cwd // ""')
mkdir -p ~/.claude/logs
ts=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$ts] [$sid] [$cwd] $cmd" >> ~/.claude/logs/bash-history.log
exit 0
Подключается на PreToolUse с matcher Bash. Срабатывает раньше выполнения, поэтому в логе видно даже те команды, которые потом заблокировали другие хуки.
8 — Уведомление, когда Claude закончил долгую задачу
Зачем: вы запустили большой рефакторинг на 15 минут, ушли заваривать кофе. Хорошо бы получить пинг, когда агент закончил, а не обнаружить через час.
Скрипт ~/.claude/hooks/notify-done.sh для macOS:
#!/usr/bin/env bash
osascript -e 'display notification "Claude закончил работу" with title "Claude Code" sound name "Glass"'
exit 0
Для Linux:
#!/usr/bin/env bash
notify-send "Claude Code" "Claude закончил работу" 2>/dev/null
exit 0
Конфиг — событие Stop, без matcher:
{
"hooks": {
"Stop": [
{
"hooks": [
{ "type": "command", "command": "/Users/me/.claude/hooks/notify-done.sh" }
]
}
]
}
}
9 — Авто-подгрузка переменных окружения в начале сессии
Зачем: чтобы при старте сессии у агента сразу были нужные переменные (например, NODE_ENV=development, DATABASE_URL, путь к .env.development). Не нужно каждый раз напоминать «загрузи env».
Скрипт ~/.claude/hooks/load-env.sh:
#!/usr/bin/env bash
input=$(cat)
cwd=$(echo "$input" | jq -r '.cwd // ""')
env_file="$cwd/.env.development"
[ -f "$env_file" ] || exit 0
while IFS='=' read -r key val; do
[[ "$key" =~ ^[A-Z_][A-Z0-9_]*$ ]] || continue
echo "$key=$val" >> "$CLAUDE_ENV_FILE"
done < "$env_file"
exit 0
Подключается на SessionStart с matcher startup (чтобы не стрелял при возобновлении и /clear):
{
"hooks": {
"SessionStart": [
{
"matcher": "startup",
"hooks": [
{ "type": "command", "command": "/Users/me/.claude/hooks/load-env.sh" }
]
}
]
}
}
Переменная CLAUDE_ENV_FILE доступна именно в SessionStart: в неё нужно дописать пары KEY=VALUE, и Claude подцепит их в окружение для всех последующих bash-команд.
10 — Запрет редактирования production-конфигов
Зачем: чтобы агент никогда не трогал config/production.yml, terraform/production/* или .github/workflows/deploy.yml без явного снятия защиты.
Скрипт ~/.claude/hooks/protect-prod.sh:
#!/usr/bin/env bash
input=$(cat)
path=$(echo "$input" | jq -r '.tool_input.file_path // ""')
protected=(
'config/production'
'terraform/production'
'terraform/prod'
'k8s/production'
'\.github/workflows/deploy'
'\.github/workflows/release'
'docker-compose\.prod'
)
for p in "${protected[@]}"; do
if echo "$path" | grep -Eq "$p"; then
echo "Блокирую правку $path: это production-конфиг. Снять защиту можно через временное отключение хука в settings.local.json." >&2
exit 2
fi
done
exit 0
Цепляется на PreToolUse с matcher Edit|Write|MultiEdit.
Как протестировать хук, не ломая проект
Боевой запуск нового хука прямо на рабочем коде — плохая идея. Если хук сломан, он будет либо пропускать опасные действия (хуже всего), либо блокировать вообще всё (тоже неприятно). Поэтому два правила.
Правило 1. Сначала прогоните скрипт вручную с имитацией входа:
echo '{"tool_input":{"command":"git push --force origin main"}}' \
| ~/.claude/hooks/block-force-push.sh
echo "exit: $?"
Должно вывести причину блокировки в stderr и exit: 2. Если не блокирует или валится, чините до того, как подключите в settings.json.
Правило 2. Подключайте новый хук сначала в .claude/settings.local.json учебного проекта (не боевого). Поработайте день, посмотрите, что не стреляет лишний раз, что не пропускает нужное. И только потом переносите в ~/.claude/settings.json, чтобы хук работал везде.
Для диагностики уже подключённых хуков пригодится команда /hooks внутри Claude Code: она показывает все события с количеством хуков, источник (User, Project, Local, Plugin) и полные детали. А ещё все ошибки хуков пишутся в ~/.claude/logs/ — заглядывайте туда, когда что-то ведёт себя странно.
Частые ошибки при настройке хуков
Скрипт без shebang или без chmod +x. Bash-файл, который не начинается с #!/usr/bin/env bash и не имеет прав на исполнение, Claude молча проигнорирует. Симптом — хук «как бы есть», но ничего не делает. Лечится двумя командами: добавить shebang первой строкой и chmod +x ~/.claude/hooks/*.sh.
Относительные пути в settings.json. Если написать "command": "./block-push.sh", Claude будет искать его относительно текущей директории сессии, а не относительно settings.json. Пишите полные пути или используйте плейсхолдер ${CLAUDE_PROJECT_DIR}/scripts/... для проектных хуков.
Кавычки внутри JSON. Особенно когда хук цепляется к инструменту через несколько имён: "matcher": "Edit|Write" — это регулярное выражение, его не надо экранировать. А вот команда с кавычками внутри — надо. Лучше для всего, что сложнее одной строки, использовать форму с "args": [...].
Хук, который что-то выводит в stdout без причины. Если в stdout появляется текст, Claude попытается распарсить его как JSON. Если не распарсит, проигнорирует. Распарсит — применит решения оттуда. Поэтому либо ничего не пишите в stdout, либо пишите валидный JSON.
Слишком тяжёлый PreToolUse. Хук срабатывает перед каждым вызовом инструмента. Если он делает запрос в сеть на три секунды, агент будет тормозить мучительно. По умолчанию у команд тайм-аут 600 секунд, но это не значит, что им надо пользоваться. Защитные хуки должны отрабатывать за десятки миллисекунд.
Хук блокирует слишком жёстко и слишком тихо. Если в stderr ничего не написать, Claude не поймёт, что произошло, и будет пытаться выполнить действие снова и снова, потому что модель не видит причину отказа. Всегда пишите осмысленное сообщение: оно нужно и вам, и агенту.
Где научиться работать с Claude Code и AI-агентами
Хуки — это инфраструктурный слой, но ремесло работы с ИИ-агентами шире: промпт-инжиниринг, контекст-менеджмент, разбивка задач, отладка цепочек рассуждений. Этому удобнее учиться системно, а не по туториалам в твиттере.
Чтобы не собирать знание по крупицам, ниже подборка курсов по нейросетям и ИИ-инструментам от школ-агрегаторов. В ней есть и короткие интенсивы про конкретные инструменты (Claude, ChatGPT, Midjourney), и программы поглубже — про работу с AI-агентами, prompt-инженерию и интеграцию ИИ в рабочие процессы.
| Курс | Школа | Стоимость со скидкой | В рассрочку | Длительность | Обзор курса от Checkroi |
|---|---|---|---|---|---|
| Искусственный интеллект Перейти на сайт курса | GeekBrains | 156 162 ₽ | 4688 ₽/мес. | 12 месяцев | Обзор курса |
| Нейросети на практике Перейти на сайт курса | Академия Эдюсон | 54 515 ₽ | 4542 ₽/мес. | 2 месяца | Обзор курса |
| Магистратура «Прикладной искусственный интеллект» с УрФУ Перейти на сайт курса | Нетология | 162 500 ₽ | 244 ₽/мес. | 24 месяца | Обзор курса |
| Нейросети для анализа данных Перейти на сайт курса | Нетология | 31 700 ₽ | 2351 ₽/мес. | 8 недель | Обзор курса |
| Нейросети для изображений и видео Перейти на сайт курса | Академия Эдюсон | 69 100 ₽ | 5758 ₽/мес. | 2 месяца | Обзор курса |
| Нейросети для дизайна Перейти на сайт курса | Яндекс Практикум | 64 000 ₽ | 2612 ₽/мес. | 2 месяца | Обзор курса |
| Нейросети: практический курс Перейти на сайт курса | Skypro | 25 990 ₽ | 181 667 ₽/мес. | 3 месяца | Обзор курса |
| Нейросети для финансистов Перейти на сайт курса | Академия Эдюсон | 65 600 ₽ | 5466 ₽/мес. | 2 месяца | Обзор курса |
| Нейросети для Бухгалтера Перейти на сайт курса | Академия Эдюсон | 49 000 ₽ | 4083 ₽/мес. | 2 месяца | Обзор курса |
| Нейросети для рабочих задач Перейти на сайт курса | Skillbox | 29 800 ₽ | 2483 ₽/мес. | 1 месяц | Обзор курса |
Больше программ — в полном каталоге курсов по нейросетям и искусственному интеллекту
Если хочется сначала понять базу, рядом полезно держать обзор «Что такое нейросети простыми словами» и сравнение моделей «Opus 4.7 vs Sonnet 4.6 vs Haiku 4.5». Тем, кто только переходит из других редакторов, пригодится материал «Claude Code vs Cursor» с разбором по 12 параметрам.
А если в тексте встретилось слово, значение которого хочется уточнить, загляните в словарь айтишника с 150+ терминами простыми словами.

![Статья: Subagents в Claude Code: создание, 7 готовых ролей и сравнение со Skills, Slash-commands и Agent Teams в 2026 Subagents в Claude Code: создание, 7 готовых ролей и сравнение со Skills, Slash-commands и Agent Teams в [current_year]](https://checkroi.ru/wp-content/uploads/2026/05/og-cover-58352-1779036868.jpg)

![Статья: Бесплатные альтернативы Claude Code в 2026 году: китайские модели, локальные LLM и российские нейросети Бесплатные альтернативы Claude Code в [current_year] году: китайские модели, локальные LLM и российские нейросети](https://checkroi.ru/wp-content/uploads/2026/05/og-cover-58341-1779030778.jpg)
