8 хуков Claude Code, которые автоматизируют то, что вы вечно забываете

Вы говорите Claude Code отформатировать файл, а он этого не делает. Просите не трогать .env, а он лезет туда первым делом. Напоминаете прогнать тесты перед завершением, а он забывает. Знакомо?
Все потому, что CLAUDE.md по сути является рекомендацией. Claude читает его и следует ему примерно в 80% случаев. Хуки работают иначе. Это автоматические действия, которые срабатывают каждый раз, когда Claude редактирует файл, выполняет команду или завершает задачу.
Ниже разберем 8 готовых хуков, которые можно скопировать прямо в settings.json и больше о них не вспоминать.
Как работают хуки (за 30 секунд)
Хуки – это автоматические действия, которые выполняются каждый раз, когда Claude Code что-то делает: редактирует файл, запускает команду. Вы настраиваете их один раз, и дальше они работают в фоне.
Два основных типа, которые вам пригодятся:
PreToolUse срабатывает до того, как Claude выполнит действие. Можно проверить, что он собирается сделать, и заблокировать это, вернув exit code 2. Считайте это фейс-контролем.
PostToolUse срабатывает после того, как Claude что-то сделал. Можно запустить форматирование, тесты, логирование. Это контроль качества на выходе.
Где живут хуки:
.claude/settings.json – уровень проекта (коммитится в git)
~/.claude/settings.json – уровень пользователя (для всех проектов)
.claude/settings.local.json – локальный (не коммитится)
Конфиг кладется в .claude/settings.json в корне проекта. Файл попадает в git, и вся команда автоматически получает одинаковые хуки.
Полная документация: https://code.claude.com/docs/en/hooks
1. Автоформат каждого файла, который Claude трогает
Проблема: Claude пишет рабочий код, но нарушает ваши правила форматирования. Вы добавляете “всегда запускай Prettier” в CLAUDE.md, и это работает почти всегда, но не на 100%.
Хук: Prettier запускается автоматически после каждой записи или редактирования файла.
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path' | xargs npx prettier --write 2>/dev/null; exit 0"
}
]
}
]
}
}
Замените npx prettier --write на свой форматтер: black для Python, gofmt для Go, rustfmt для Rust. Паттерн один и тот же.
Это был первый хук, который я настроил, и по-хорошему он должен быть дефолтным для любого проекта. Больше никаких коммитов “Claude забыл отформатировать”.
2. Блокировка опасных команд
Проблема: Claude достаточно мощный, чтобы выполнить rm -rf, git reset --hard, DROP TABLE или curl на случайный URL. Скорее всего он этого не сделает, но “скорее всего” – не аргумент, когда речь о продакшн-базе.
Хук: блокирует деструктивные команды до их выполнения.
Создайте файл .claude/hooks/block-dangerous.sh:
#!/usr/bin/env bash
set -euo pipefail
cmd=$(jq -r '.tool_input.command // ""')
dangerous_patterns=(
"rm -rf"
"git reset --hard"
"git push.*--force"
"DROP TABLE"
"DROP DATABASE"
"curl.*|.*sh"
"wget.*|.*bash"
)
for pattern in "${dangerous_patterns[@]}"; do
if echo "$cmd" | grep -qiE "$pattern"; then
echo "Blocked: '$cmd' matches dangerous pattern '$pattern'. Propose a safer alternative." >&2
exit 2
fi
done
exit 0
Затем добавьте в settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/block-dangerous.sh"
}
]
}
]
}
}
Exit code 2 – ключевой момент. Он блокирует действие и отправляет сообщение об ошибке обратно Claude, чтобы тот попробовал более безопасный подход. Exit code 0 означает “продолжай”. Все остальное логирует предупреждение, но не блокирует.
3. Защита чувствительных файлов от редактирования
Проблема: Claude может читать и редактировать любой файл в проекте. Включая .env, package-lock.json, конфиги и все, что вы предпочли бы оставить нетронутым.
Хук: блокирует редактирование файлов, которые должны быть под защитой.
Создайте .claude/hooks/protect-files.sh:
#!/usr/bin/env bash
set -euo pipefail
file=$(jq -r '.tool_input.file_path // .tool_input.path // ""')
protected=(
".env*"
".git/*"
"package-lock.json"
"yarn.lock"
"*.pem"
"*.key"
"secrets/*"
)
for pattern in "${protected[@]}"; do
if echo "$file" | grep -qiE "^${pattern//\*/.*}$"; then
echo "Blocked: '$file' is protected. Explain why this edit is necessary." >&2
exit 2
fi
done
exit 0
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/protect-files.sh"
}
]
}
]
}
}
4. Запуск тестов после каждого изменения
Проблема: Claude вносит правку, говорит “готово”, а вы через 20 минут обнаруживаете, что тесты сломаны, когда пытаетесь закоммитить.
Хук: автоматически запускает тесты после каждого изменения кода. Если тесты падают, Claude видит это и может сразу починить.
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "npm run test --silent 2>&1 | tail -5; exit 0"
}
]
}
]
}
}
tail -5 оставляет вывод коротким, чтобы не засорять контекст Claude. Вам нужно, чтобы Claude увидел “3 tests failed”, а не полный вывод на 200 строк.
Борис Черный, создатель Claude Code, говорит, что такой цикл обратной связи улучшает качество результата в 2-3 раза. Вместо того чтобы писать код и надеяться, что он работает, Claude пишет код, видит результаты тестов и сам исправляет ошибки.
5. Обязательные тесты перед созданием PR
Проблема: Claude заканчивает фичу и сразу создает PR. Тесты падают. Ревьюер видит красный CI и отправляет обратно.
Хук: блокирует создание PR, если тесты не проходят.
Создайте .claude/hooks/require-tests-for-pr.sh:
#!/usr/bin/env bash
set -euo pipefail
if npm run test --silent; then
exit 0
else
echo "Tests are failing. Fix all test failures before creating a PR." >&2
exit 2
fi
{
"hooks": {
"PreToolUse": [
{
"matcher": "mcp__github__create_pull_request",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/require-tests-for-pr.sh"
}
]
}
]
}
}
Это жесткий гейт. Нет зеленых тестов – нет PR. Claude сначала починит ошибки, потому что exit code 2 сообщает ему, что действие заблокировано и почему.
6. Автолинт и отчет об ошибках
Проблема: Claude пишет рабочий код, но нарушает правила ESLint, style guide или type checks. Вы ловите это на ревью и отправляете обратно.
Хук: линтер запускается после каждого изменения. Если линт падает, Claude видит ошибки и исправляет их до того, как вы вообще посмотрите на код.
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "npx eslint --fix $(jq -r '.tool_input.file_path') 2>&1 | tail -10; exit 0"
}
]
}
]
}
}
Можно объединить с хуком автоформата из пункта 1. Сначала Prettier, потом ESLint. К моменту, когда вы посмотрите на код, он уже отформатирован и чист.
7. Логирование каждой команды Claude
Проблема: Claude выполняет кучу shell-команд за сессию. Если что-то пошло не так, хочется знать, что именно он делал и когда.
Хук: записывает каждую Bash-команду в лог-файл с таймстампами.
Создайте .claude/hooks/log-commands.sh:
#!/usr/bin/env bash
set -euo pipefail
cmd=$(jq -r '.tool_input.command // ""')
printf '%s %s\n' "$(date -Is)" "$cmd" >> .claude/command-log.txt
exit 0
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/log-commands.sh"
}
]
}
]
}
}
Теперь у вас есть аудит-лог с таймстампами для каждой команды, которую Claude выполнил. Добавьте .claude/command-log.txt в .gitignore, чтобы не засорять репозиторий.
Особенно полезно для дебага: если Claude что-то сломал три сессии назад, можно открыть лог и найти, когда и что именно он запустил.
8. Автокоммит после каждой завершенной задачи
Проблема: Claude заканчивает задачу, а вы забываете закоммитить. Потом он начинает следующую, и у вас два несвязанных изменения в одном коммите.
Хук: автоматически коммитит все изменения, когда Claude завершает работу.
Создайте .claude/hooks/auto-commit.sh:
#!/usr/bin/env bash
set -euo pipefail
git add -A
if ! git diff --cached --quiet; then
git commit -m "chore(ai): apply Claude edit"
fi
exit 0
{
"hooks": {
"Stop": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/auto-commit.sh"
}
]
}
]
}
}
Каждый раз, когда Claude завершает ответ, изменения автоматически коммитятся. История git остается чистой с атомарными коммитами на каждую задачу, а не одним гигантским “Claude changes” в конце дня.
Скомбинируйте с claude -w feature-branch (worktrees), и вы получите изолированные, автоматически коммитящиеся ветки для каждой задачи.
Полный settings.json
Вот все хуки в одном файле, который можно скопировать целиком:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/block-dangerous.sh"
},
{
"type": "command",
"command": ".claude/hooks/log-commands.sh"
}
]
},
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/protect-files.sh"
}
]
},
{
"matcher": "mcp__github__create_pull_request",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/require-tests-for-pr.sh"
}
]
}
],
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path' | xargs npx prettier --write 2>/dev/null; exit 0"
},
{
"type": "command",
"command": "npx eslint --fix $(jq -r '.tool_input.file_path') 2>&1 | tail -10; exit 0"
}
]
}
],
"Stop": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/auto-commit.sh"
}
]
}
]
}
}
Скопируйте этот файл в .claude/settings.json, создайте скрипты хуков в .claude/hooks/, сделайте их исполняемыми через chmod +x .claude/hooks/*.sh и закоммитьте все в git. Вся команда автоматически получит одинаковые защитные механизмы.
Разница между хорошим и отличным сетапом Claude Code не в модели и не в промптах. Она в хуках. Это та часть, которая работает, когда вы не смотрите, ловя ошибки, которые вы иначе нашли бы на код-ревью или, что хуже, в продакшне.
Начните с хука #1 (автоформат) и #2 (блокировка опасных команд) сегодня. Одного этого хватит, чтобы избежать самых частых ошибок Claude Code. Остальные добавляйте по мере необходимости.
Источник: https://x.com/zodchiii/article/2040000216456143002



