Все статьи

Хуки Claude Code: примеры блокировки с тестами

Хуки Claude Code — это команды, которые выполняются в определённых точках сессии: перед запуском инструмента, после него, при отправке промпта, при остановке сессии. Именно они превращают «агент не должен этого делать» в правило, которое реально проверяется. В этой статье — хуки Claude Code с примерами, которые блокируют то, что должно быть заблокировано, способы их тестирования и причины большинства поисковых запросов вида «hook error».

Всё ниже соответствует официальному справочнику по хукам и документации по разрешениям. Мы ежедневно используем Claude Code с хуками в собственной студии; один из наших хуков — Stop-хук, предупреждающий, когда расход токенов сессии превышает лимит.

Где настраиваются хуки Claude Code

Хуки хранятся в файлах настроек:

Файл Область действия Общий доступ
~/.claude/settings.json все ваши проекты нет
.claude/settings.json один проект да, можно коммитить
.claude/settings.local.json один проект нет

Записи из этих файлов объединяются, а не заменяют друг друга. Плагины, навыки и субагенты тоже могут приносить свои хуки.

Запись хука имеет три уровня: событие, группа matcher и обработчики:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          { "type": "command", "command": "python3 ${CLAUDE_PROJECT_DIR}/.claude/hooks/block_rm.py" }
        ]
      }
    ]
  }
}

CLAUDE_PROJECT_DIR — корневая папка проекта, в которой была запущена сессия. В Windows вызывайте Python так, как принято в вашей системе.

Хук PreToolUse, блокирующий опасную команду

Хук PreToolUse получает запланированный вызов инструмента в виде JSON на стандартный ввод: tool_name, tool_input и несколько полей сессии. Для Bash tool_input.command — это текст команды.

#!/usr/bin/env python3
import json, re, sys

data = json.load(sys.stdin)
cmd = data.get("tool_input", {}).get("command", "")

if re.search(r"\brm\s+-\w*(rf|fr)\w*\b", cmd):
    print("Blocked: recursive force delete. Ask the user to run it.", file=sys.stderr)
    sys.exit(2)
sys.exit(0)

Главное правило: вызов блокирует код выхода 2, а stderr становится причиной, которую видит Claude. Код 0 пропускает команду. Любой другой код — неблокирующая ошибка: действие выполняется, вы получаете лишь уведомление.

Текстовый шаблон ловит привычную форму команды, но не все формы: этот останавливает rm -rf и rm -fr, но rm -r -f с раздельными флагами пройдёт. Поэтому каждое правило нужно тестировать, и поэтому рядом с хуками существуют правила разрешений и песочница.

Если вам ближе структурированный вывод, хук может завершиться с кодом 0 и вывести JSON с hookSpecificOutput, где hookEventName — PreToolUse, а permissionDecision — allow, deny, ask или defer, вместе с permissionDecisionReason.

Matcher для PreToolUse без сюрпризов

Matcher фильтрует по имени инструмента:

  • Bash или список вроде Edit|Write — точные имена.
  • Всё, что содержит другие символы, — регулярное выражение без привязки: ^Notebook, mcp__memory__.*.
  • Инструменты MCP именуются mcp__<server>__<tool>. Matcher вида mcp__memory сам по себе не совпадёт ни с чем; нужно mcp__memory__.*.
  • *, пустая строка или отсутствие matcher означают все инструменты.

Есть также поле if, использующее синтаксис правил разрешений, например Bash(git *). Документация называет его «best-effort»: для жёсткого allow или deny используйте систему разрешений.

Тестируйте каждый хук: один вызов заблокирован, один пропущен

Хук без теста — это хук, на который вы просто надеетесь. Самый дешёвый тест — подать ему тот же JSON, который отправил бы Claude Code, и проверить код выхода:

echo '{"tool_name":"Bash","tool_input":{"command":"rm -rf build"}}' | python3 .claude/hooks/block_rm.py; echo "exit $?"   # expect 2
echo '{"tool_name":"Bash","tool_input":{"command":"ls build"}}'    | python3 .claude/hooks/block_rm.py; echo "exit $?"   # expect 0

Наше правило для каждого хука: одно действие, которое должно быть заблокировано, и одно, которое должно пройти, — оба в тестовом файле. Второй тест ловит другую частую проблему: слишком широкий шаблон, блокирующий нормальную работу.

Почему ошибка хука PreToolUse ничего не останавливает

Типичные причины, все из справочника:

  1. Код выхода 1 вместо 2. Появляется уведомление об ошибке, но инструмент всё равно выполняется.
  2. Таймаут. Хук PreToolUse, завершившийся по таймауту, не блокирует; вызов проходит обычный путь через систему разрешений. По умолчанию у командных хуков 600 секунд.
  3. Matcher, который никогда не совпадает, например mcp__memory без .*.
  4. Падающий скрипт. По умолчанию упавший хук не блокирует. Последние версии поддерживают "onFailure": "block" (v2.1.295 и новее), чтобы блокировать, когда командный хук падает, висит по таймауту или возвращает некорректный вывод.

Хуки, правила разрешений и навыки: кто за что отвечает

  • Правила разрешений (allow, ask, deny в settings.json) проверяются в таком порядке: deny, затем ask, затем allow. Правило deny применяется даже когда хук PreToolUse возвращает allow.
  • Блокирующий хук (код 2) останавливает вызов до проверки правил разрешений, поэтому он также побеждает правило allow.
  • Навыки — это инструкции и ресурсы, которые агент загружает по мере необходимости. Они подсказывают, но ничего не запрещают.

Для конфиденциальных папок начните с правил deny вроде Read(./secrets/**). Знайте их предел: они охватывают встроенные инструменты работы с файлами и команды вроде cat, head и tail, но не grep -r, запущенный из папки, и не скрипт, который сам открывает файлы. Хук PreToolUse в таких случаях может проанализировать полный текст команды, а для жёсткого запрета на уровне операционной системы документация рекомендует песочницу.

Когда передать это нам

Если ваша агентская инфраструктура выросла быстро и вы не уверены, какие правила реально работают, мы составляем карту агентов, пишем правила хуков с тестами и показываем прогон тестов, а не только конфиг. Как устроена наша собственная система, можно посмотреть на странице работ.

Вопросы

Почему мой хук PreToolUse ничего не блокирует?

Чаще всего он завершается с кодом 1. Вызов инструмента блокирует только код выхода 2; любой другой ненулевой код — это неблокирующая ошибка, и действие выполняется. Хук, завершившийся по таймауту, тоже не блокирует.

Нужны ли хуки, если уже есть правила запрета в разрешениях?

Для простых случаев правила deny применяются в первую очередь: они проверяются даже когда хук возвращает allow. Хуки нужны для логики, которую нельзя выразить шаблоном — например, для анализа полного текста команды перед выполнением.

Останавливают ли правила Read запретов команды cat и grep в Bash?

Они охватывают встроенные инструменты работы с файлами и те файловые команды, которые Claude Code распознаёт в Bash: cat, head и tail. Они не охватывают команду, читающую файлы без указания имён, например grep -r из папки, или скрипт, который сам открывает файлы. Для таких случаев документация рекомендует песочницу.

Где хранятся хуки Claude Code?

В файлах настроек: ~/.claude/settings.json для всех ваших проектов, .claude/settings.json для одного проекта и всей команды или .claude/settings.local.json только для вас. Записи из нескольких файлов объединяются.

Контакты

Этот ящик читает один человек — тот же, кто делает то, что вы заказываете.

Опишите задачу

Напишите, что у вас есть и какой результат нужен, — даже если это одна небольшая задача. Техзадание не нужно: в течение 48 часов пришлём план и цену письменно, уточняющий вопрос или честно скажем, что задача не наша.

Укажите ситуацию, файлы или ссылки, срок, язык, границы приватности и бюджет, если он есть.

Файл (по желанию)
Файл не выбран

Бриф, фотография, таблица — то, что объяснит задачу быстрее слов. До 8 МБ, хранится у нашего хостинг-провайдера. Пожалуйста, не отправляйте через сайт чувствительные личные или медицинские документы.

Отправка заявки не создаёт заказ и не требует оплаты. Отвечаем в течение 48 часов. Удобнее email? contact@castel.studio

Поговорить с нами

Удобнее голосом или в мессенджере? Пишите и звоните — отвечает основатель студии.

Связаться в LinkedIn

Телефон · WhatsApp · Telegram

Франция+33 7 49 57 41 69WhatsAppTelegram

Украина+38 063 95 77 111WhatsAppTelegram

Удобнее через площадку?

Ту же работу можно заказать там — с безопасной оплатой площадки.

Соло-студия ИИ-систем в Ницце. Кто отвечает на ваше сообщение, тот и делает работу — без менеджеров-посредников. Файлы обрабатываются на нашей машине, а не в чужом облаке.

Ницца 06100, Франция · Открыть на карте →

SIREN 103 115 705