Усі статті

Хуки Claude Code: приклади блокування з тестами

Хуки Claude Code — це команди, які виконуються у визначених точках сесії: перед запуском інструменту, після нього, при надсиланні запиту, при зупинці сесії. Саме так можна перетворити «агент не повинен цього робити» на те, що реально перевіряється. Ця стаття показує приклади хуків Claude Code, які блокують те, що треба блокувати, як їх тестувати та які помилки стоять за більшістю запитів «hook error».

Усе нижче ґрунтується на офіційному довіднику хуків і документації з дозволів. Ми щодня використовуємо Claude Code з хуками у власній студії; один із наших — це Stop-хук, який попереджає, коли використання токенів у сесії перевищує ліміт.

Де налаштовуються хуки Claude Code

Хуки живуть у файлах налаштувань:

Файл Застосовується до Спільний
~/.claude/settings.json усі ваші проєкти ні
.claude/settings.json один проєкт так, можна закомітити
.claude/settings.local.json один проєкт ні

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

Запис хука має три рівні: подія, група матчерів і обробники:

{
  "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.

Матчер PreToolUse без сюрпризів

Матчер фільтрує за назвою інструменту:

  • Bash або список на кшталт Edit|Write — точні назви.
  • Усе з іншими символами — це регулярний вираз без прив’язки: ^Notebook, mcp__memory__.*.
  • Інструменти MCP називаються mcp__<server>__<tool>. Матчер лише mcp__memory не збігається ні з чим; потрібен mcp__memory__.*.
  • *, порожній рядок або відсутність матчера означає всі інструменти.

Є також поле 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. Матчер, який ніколи не збігається, як-от 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-правила дозволів?

Для простих правил спершу застосовуються deny-правила: їх перевіряють навіть тоді, коли хук повертає allow. Хуки потрібні для логіки, яку не виразити шаблоном, наприклад для аналізу повного тексту команди перед її виконанням.

Чи зупиняють deny-правила для 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