Дві екосистеми: Claude Code і OpenAI Codex
Claude Hooks: автоматичні перевірки на подіях агента
Claude Hooks: автоматичні перевірки на подіях агента: Навчальний розділ курсу «AI Development» (Artificial Intelligence, штучний інтелект) · зріз…
Навчальний розділ курсу «AI Development» (Artificial Intelligence, штучний інтелект) · зріз мінливої документації: 10.10.2026
Claude може отримати чітку інструкцію «не редагуй файл із правилами тарифікації», але інструкція лишається текстом, який модель має правильно зрозуміти й застосувати в потрібний момент. Hook (гачок, або обробник події) дає змогу запустити визначену дію у конкретній точці життєвого циклу Claude Code: наприклад, перевірити аргумент до виклику інструмента, відформатувати вже записаний файл або показати людині сповіщення.
Hook автоматизує певний крок, але не перетворює весь проєкт на захищену зону. Перевірка перед викликом охоплює лише ті події та шляхи виконання, до яких її прив’язали. Перевірка після виклику вже не скасовує запис, відправлену мережею команду чи інший побічний ефект. Тому важливо знати і точну поведінку інструмента, і те, чого він не контролює.
Наведена нижче поведінка звірена з поточною документацією Claude Code 10 жовтня 2026 року. Найновіший випуск у журналі змін на дату зрізу — 2.1.296 від 9 жовтня; це не твердження про версію, встановлену на кожній машині. Для критичних правил звіряйте довідку та версію конкретного середовища перед використанням.
34.1. Інструкція, автоматична перевірка й межа операційної системи
Уявімо правило: «Не відкривай і не змінюй файли з паролями». Воно може стояти в CLAUDE.md чи запиті. Це корисний контекст, але воно не перехоплює виклик інструмента й не відбирає в процесу доступ до диска.
Подія PreToolUse (до виклику інструмента) може передати дані конкретного виклику скрипту, який порівняє їх із переліком заборонених шляхів і відхилить саме цей виклик. Це вже автоматичний контроль події, яку Claude Code передав hook-у. Однак якщо файл можна змінити іншим шляхом, наприклад через інше командне середовище або зовнішній процес, така перевірка не стає універсальною забороною.
Дозволи Claude Code визначають, які виклики можна виконувати, які потребують схвалення, а які треба відхиляти. Пісочниця (sandbox, ізольоване середовище) обмежує ресурси, до яких можуть дістатися підтримувані команди; права операційної системи (operating system, OS) визначають, що може зробити сам обліковий запис процесу. Це різні рівні з різним охопленням. У режимі ручного схвалення Claude Code, наприклад, окремо керує дозволами читання та запису; пісочниця оболонки може додати ізоляцію файлової системи й мережі. Документація з безпеки Claude Code описує ці механізми окремо.
| Засіб | Що контролює | Чого сам по собі не доводить |
|---|---|---|
| Інструкція в тексті | Що модель має врахувати | Що перевірка неодмінно відбудеться або що інструмент фізично не зможе діяти |
| Hook | Події Claude Code, до яких його налаштовано; для деяких подій — рішення до виконання | Що охоплено альтернативні інструменти, зовнішні процеси й наслідки вже виконаної дії |
| Дозволи Claude Code | Інструменти, команди й запити на схвалення в межах правил поточного середовища | Що процес поза Claude Code підкорятиметься цим правилам |
| Пісочниця та права системи | Реально доступні процесу файли, мережу й ресурси | Що бізнес-рішення правильне або що кожна операція пройшла потрібну перевірку |
Отже, hook доречний, коли правило можна прив’язати до чіткої події й алгоритмічно перевірити. Для заборони доступу до секрету не покладайтеся лише на текст чи фільтр аргументів: потрібні відповідні дозволи, ізоляція або права облікового запису.
34.2. Події, фільтри й типи hook-обробників
Claude Code зберігає налаштування в JSON (JavaScript Object Notation, текстовому форматі структурованих даних). У полі hooks задають назву події, за потреби — фільтр matcher, а потім один чи кілька обробників. Фільтр визначає, на які входження події реагувати: наприклад, лише на Edit та Write, а не на кожен інструмент. Синтаксис matcher залежить від події: для інструментів це назви інструментів або шаблони, для SessionStart — джерело запуску, для ConfigChange — джерело зміни налаштування. Не вважайте довільний шаблон точним збігом без звірки з правилами matcher у довіднику.
Найважливіші для цієї глави події:
| Подія | Коли спрацьовує | Чи може запобігти дії |
|---|---|---|
| PreToolUse | Після підготовки параметрів інструмента, але до опрацювання виклику | Так: може дозволити, відхилити, попросити підтвердження або відкласти виклик |
| PostToolUse | Після успішного виконання інструмента | Ні: може надати Claude зворотний зв’язок, але інструмент уже відпрацював |
| PostToolUseFailure | Після помилки інструмента, який почав виконуватися | Ні: інструмент уже повернув помилку |
| UserPromptSubmit | Коли користувач надіслав запит, перш ніж Claude його опрацьовує | Так: може доповнити контекст або заблокувати опрацювання запиту |
| Stop | Коли Claude збирається завершити хід | Так: може попросити продовжити роботу |
| SessionStart / SessionEnd | На початку / завершенні сесії | SessionStart може додати контекст; SessionEnd не може затримати завершення й має спільний типовий бюджет 1,5 секунди |
| PreCompact / PostCompact | До / після стискання історії діалогу | Перша може зупинити стискання; друга працює після нього |
| ConfigChange | Коли змінюються відповідні налаштування | Для більшості джерел може не допустити застосування зміни; політичні налаштування мають виняток |
Це не повний перелік подій: Claude Code також підтримує сповіщення, зміни робочого каталогу, моделі, файлів, агентні події та інші точки життєвого циклу. Їхня наявність не означає, що кожна з них може блокувати дію. Точні назви, типи фільтрів і наслідки кожної події наведені в Hooks reference.
Для обробника поле type вказує спосіб виконання. Поточна документація описує п’ять типів:
- command запускає команду; вхід приходить стандартним потоком введення (stdin — standard input), а результат повідомляється кодом завершення, стандартним потоком виведення (stdout — standard output) і потоком помилок (stderr — standard error).
- http надсилає дані як запит через HTTP (Hypertext Transfer Protocol, протокол передавання гіпертексту); блокувальне рішення задають у валідному JSON тіла успішної відповіді, а не самим HTTP-статусом. Неуспішний статус або помилка з’єднання за замовчуванням дають неблокувальну помилку;
onFailure: "block"може зробити збій hook-а блокувальним. [1] - mcp_tool викликає інструмент уже під’єднаного сервера MCP (Model Context Protocol, протокол контексту моделі). Він доступний не в кожній події: наприклад, на початку сесії сервери можуть бути ще недоступні.
- prompt просить модель оцінити умову й повернути структуроване рішення. Це доречно для перевірки, що потребує судження, але не робить результат детермінованим.
- agent запускає субагента, який може перевірити файли або результати інструментів. Цей тип позначено експериментальним; він підтримує ті самі події, що й prompt-hook, крім PermissionRequest. [1]
Для звичайної перевірки команда краща за виклик моделі, коли правило чітке: її результат можна повторити й пояснити. Якщо рішення вимагає прочитати контекст або оцінити зміст, модельний hook може бути помічником, але його висновок слід подавати як оцінку, а не як безпомилкову політику. Посібник Anthropic з автоматизації діями hook-ів пояснює це розрізнення.
34.3. Вхід і вихід: що насправді бачить hook
Командний hook отримує об’єкт JSON зі стандартного потоку введення. У ньому є спільні поля й поля конкретної події. Наприклад, для PreToolUse типовий задокументований вхід має такий вигляд:
{
"session_id": "demo-session",
"transcript_path": "/workspace/store/.claude/transcript.jsonl",
"cwd": "/workspace/store",
"permission_mode": "default",
"hook_event_name": "PreToolUse",
"tool_name": "Edit",
"tool_input": {
"file_path": "/workspace/store/config/pricing-policy.json",
"old_string": "...",
"new_string": "..."
},
"tool_use_id": "toolu_demo"
}
session_id — ідентифікатор сесії, transcript_path — шлях до її файла історії, cwd — робочий каталог, permission_mode — режим дозволів, hook_event_name — назва події. tool_name і tool_input називають інструмент та його параметри; схема параметрів змінюється залежно від інструмента. tool_use_id — ідентифікатор виклику. У прикладі значення вигадані; назви полів узято з довідки. permission_mode відсутній у деяких подіях, а історія за transcript_path може відставати від щойно виконаних повідомлень. Не виводьте значення поля, якого немає у схемі конкретної події. Довідник зі спільних полів і схем подій перелічує їх окремо.
Параметри tool_input — це дані, а не готовий shell-код. Якщо в командному hook-у використати аргумент без розбору й належного екранування, шлях або фрагмент тексту можуть перетворитися на ін’єкцію команд. Для перевірки шляху читайте структуроване значення JSON-бібліотекою й порівнюйте нормалізований абсолютний шлях; для оболонки передавайте виконуваний файл та аргументи окремо, коли це можливо. У Windows шляхи Read/Edit/Write можуть містити зворотні скісні риски навіть тоді, коли hook працює в Git Bash, тому нормалізуйте роздільники перед перевіркою шаблону шляху.
Для PostToolUse додається tool_response — результат інструмента, а також може бути duration_ms. Для PostToolUseFailure наявні поля помилки, зокрема error та необов’язкові is_interrupt і duration_ms. Формат error залежить від інструмента, тому це не стабільне машинне поле для кожної деталі. Помилка валідації невідомого інструмента чи його параметрів може виникнути до виконання й не викликати ані PreToolUse, ані PostToolUseFailure; відхилення дозволами натомість викликає PreToolUse, але не PostToolUseFailure. Навіть журнал «усіх помилок інструментів» через один hook може мати прогалини.
Код завершення та вивід мають точну семантику:
- Код 0 означає успішне завершення обробника; сам по собі він нічого не дозволяє й не забороняє. Це типовий код для структурованої відповіді JSON.
- Код 2 позначає блокувальну помилку там, де подія підтримує блокування. Для PreToolUse він блокує виклик; для PostToolUse уже виконана дія залишається, а текст помилки може бути показаний Claude як відгук. Для інших подій значення відрізняється.
- Інший ненульовий код зазвичай самостійно не блокує. Зокрема, код 1 — не універсальне «заборонити». Для більшості подій він дає неблокувальну помилку й дія продовжується.
- Структурований JSON має йти в stdout без стороннього тексту. Наприклад, PreToolUse може повернути рішення так:
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "Цей шлях редагується лише через затверджений процес"
}
}
Для PreToolUse поля рішення лежать саме у hookSpecificOutput; актуальний перелік варіантів: allow, deny, ask і defer. allow може прибрати запит підтвердження, але правила deny та ask усе одно застосовуються; він також не замінює необхідної взаємодії для AskUserQuestion, ExitPlanMode та MCP-інструментів, які її вимагають. Вихід updatedInput замінює весь об’єкт параметрів, тож треба зберегти поля, яких не змінюють; нові параметри також проходять перевірку дозволів. Якщо кілька hook-ів повертають рішення одночасно, пріоритет такий: deny, далі defer, потім ask, а після них allow. Рішення defer призначене для інтеграцій, що запускають Claude Code у неінтерактивному режимі claude -p: інтерактивна сесія покаже попередження й проігнорує його. Воно працює лише для одиничного виклику інструмента в ході; при паралельній групі викликів defer також ігнорується, а інструменти йдуть звичайним шляхом дозволів. [1]
На противагу цьому, PostToolUse може додати пояснення або замінити вивід інструмента через updatedToolOutput, але лише для того, що побачить Claude: сам виклик уже відбувся, а форма заміни має відповідати формі виводу інструмента. Навіть вихід із кодом 2 на PostToolUse не відкочує файл і не скасовує відправлений запит. Усі відповідні обробники запускаються паралельно, отже не закладайте в них послідовність на кшталт «перший змінить файл, другий прочитає саме нову версію» без окремої координації.
34.4. До чи після: вибір правильної точки контролю
PreToolUse запускається, коли Claude підготував параметри виклику, але ще до його виконання. Він може відхилити редагування певного шляху або попросити підтвердження перед ризикованою дією. Це найкраща точка для перевірки аргументів і правил, які мають застосовуватись до самого виклику. Однак ця подія бачить лише виклики інструментів, які Claude Code передає їй. Наприклад, файл, доданий через @ у запиті, не є викликом Read, тож hook, що фільтрує Read, його не побачить.
PostToolUse спрацьовує після успішного виклику. Він може перевірити синтаксис записаного документа, додати результат до контексту Claude чи замінити текст відповіді для моделі. Файл, команда або зовнішня дія вже змінили стан системи; повідомлення «помилка» не повертає його назад. Щоб зреагувати на помилку виконання, існує окрема подія PostToolUseFailure; вона також не відкочує те, що встигло статися.
Є й подія FileChanged, яка реагує на фактичну зміну визначеного файла незалежно від того, який процес її зробив. Вона виконується після зміни та не має рішення для блокування. З іншого боку, PostToolUse на Edit|Write може не побачити зміну, якщо її зробила Bash-команда або процес поза Claude Code. Офіційна інструкція з hook-сценаріями показує форматування після редагування та блокування захищеного шляху як різні сценарії: один контролює параметр до дії, інший працює вже з результатом.
Детермінованій процедурі відповідає детермінована перевірка:
- перевірити, що шлях розташований у дозволеному каталозі;
- перевірити обов’язковий параметр у запиті до інструмента;
- відформатувати файл за однаковим стилем;
- записати до журналу ідентифікатор події й рішення без секретних значень.
Натомість «чи відповідає ця міграція бізнес-політиці?» — не просто регулярний вираз (regular expression, regex) по тексту. Регулярний вираз може знайти формат дати чи підозрілий рядок, але не доведе, що ставка застосовується до правильного клієнта, розрахунок не змінює попередні транзакції, а рішення узгоджене з вимогою. Для такого судження потрібні вимоги, тести й людський review; модельний hook може підготувати сигнал для розгляду, але не замінює ці докази.
34.5. Тайм-аут, помилка й вибір «зупинитися чи продовжити»
Поле timeout задається в секундах. Значення за замовчуванням відрізняється за типом hook-а та подією: для звичайних command, http і mcp_tool документація вказує 600 секунд; для prompt — 30, для agent — 60. Для окремих подій command/http/mcp_tool межі нижчі: 30 секунд для UserPromptSubmit, PreModelSwitch і PostModelSwitch, а також 10 для MessageDisplay. SessionEnd має спільний бюджет 1,5 секунди; CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS може підняти загальний бюджет до 60 секунд, але hook без власного timeout лишається на типовому ліміті, а plugin hook його не збільшує. Командний hook з async: true працює у фоні й після запуску не отримує timeout; його результат надходить у наступному ході, а claude -p скасовує фоновий процес під час завершення сесії. Не запускайте важку перевірку синхронно перед кожною дією без потреби: користувач чекатиме на кожен такий запит. [1]
Якщо синхронний командний, HTTP або MCP-tool hook досягає свого тайм-ауту, Claude Code скасовує його та відкидає його вихід. Для PreToolUse тайм-аут переходить у звичайний процес дозволів: сам по собі він не блокує інструмент. Callback Agent SDK на PreToolUse має інший контракт: його тайм-аут блокує виклик. На UserPromptSubmit timeout синхронного command/http/mcp_tool hook-а відкидає вивід, але запит усе одно доходить до Claude; тайм-аут SDK callback блокує запит. На PreModelSwitch тайм-аут блокує зміну моделі. Перед застосуванням з’ясуйте контракт саме цієї події.
Вибір fail-closed (при помилці — зупинити ризиковану операцію) чи fail-open (при помилці — дозволити продовження) визначається наслідком. Для форматувальника змін низького ризику може бути розумним продовжити, залишити результат явно неперевіреним і повідомити Claude. Для оплати, публікації або розгортання продовження без перевірки може бути неприйнятним. Але слово «fail-closed» не змінює поведінку платформи: якщо тайм-аут PreToolUse за документацією продовжує звичайний процес дозволів, обмеження потрібно закріпити в цьому процесі, на стороні цільової системи або операційного середовища. Hook може передати deny лише якщо отримав змогу виконатися й повернути рішення.
Реальний приклад варто читати з його межами. У відкритому повідомленні про збій у anthropics/claude-code, issue #85250, автор описав зависання дочірнього процесу Node.js у Windows із Claude Code 2.1.226: команда нібито не починала виконувати скрипт, а зазначений двосекундний timeout не завершував процес. На сторінці стоїть позначка reproducedBug, і стан issue лишався відкритим під час перевірки 10 жовтня. Це конкретний звіт для тієї версії й умов, а не доказ, що кожен тайм-аут у поточній версії поводиться так само. На дату зрізу найновішим був випуск 2.1.296; ми не робимо висновку, що issue виправлена або що цей випадок обов’язково трапляється в цій версії. Довідник описує очікувану поведінку тайм-аутів, але такі повідомлення пояснюють, навіщо перевіряти її під власним навантаженням і мати окрему межу безпеки.
Повтор і побічні ефекти потребують такої самої уваги. Не вважайте, що подія викликається рівно один раз або що процес не перезапуститься після помилки. Якщо hook записує аудит, додавайте ідентифікатор виклику tool_use_id та робіть повтор безпечним: повторне отримання тієї самої події не повинно створювати зайву транзакцію чи дублювати повідомлення. Не запускайте з hook-а ще одну сесію Claude без явної причини й захисту від повторного запуску: та сесія може прочитати ті самі налаштування та знову викликати hook. Асинхронні hook-и працюють кожен у своєму фоновому процесі без автоматичного усунення дублікатів; їхній результат з’являється в наступному ході, коли Claude його зможе прочитати.
34.6. Захист самого hook-а й межі покриття
Командний hook — це виконувана програма. Claude Code попереджає, що вона працює з правами користувача й потенційно може читати, змінювати чи видаляти файли, доступні цьому обліковому запису. Тому її скрипт сам стає частиною межі довіри, а не безпечним «датчиком» за замовчуванням. Правила безпеки hook-ів Anthropic радять перевіряти й очищувати вхід, завжди цитувати змінні оболонки, враховувати обхід шляхом .., використовувати абсолютні шляхи до скриптів і не виключати чутливі файли з-під захисту.
До розгляду налаштування спільного репозиторію перевірте його походження. В інтерактивній сесії Claude Code затримує hook-и із файлів налаштувань до прийняття довіри до робочого каталогу. У неінтерактивному режимі та сесії через SDK (Software Development Kit — програмний набір засобів розробки) діалог довіри не показується, а каталог вважається довіреним: отже, файл налаштувань проєкту з hook-ом може запустити його навіть у каталозі, якому користувач окремо не довіряв. Налаштування команди лежать у .claude/settings.json; особисті винятки можуть бути в .claude/settings.local.json; організаційні політики можуть додаватися окремо. Документація з налаштувань Claude Code пояснює їхні межі та джерела.
Перед запуском перевірки запитайте:
- Чи не вставляє скрипт недовірені аргументи у командний рядок без безпечного цитування? Краще передати аргументи окремо або передати машинно сформований JSON.
- Які права має hook? Чи може він випадково надіслати секрет мережею або записати його в журнал, повідомлення помилки чи діагностику?
- Звідки завантажується виконуваний файл? Відносний шлях чи змінний PATH може привести до іншої програми; відомий абсолютний шлях і контрольований скрипт краще перевірити окремо.
- Чи можна змінити сам .claude/settings.json або його скрипт? Для політики команди потрібні відповідний власник, рев’ю та контроль змін; інакше перевірюваний код може змінити і правило, і перевірку.
- Чи отримує програма змінні середовища з токенами й ключами? Не включайте їх у параметри чи логи; по можливості передавайте лише необхідні значення.
- Чи не перетворився hook із детермінованої перевірки на новий необмежений виклик мережі? Доступ до мережі додає ще одну залежність і точку витоку.
Покриття може зламатися не лише через помилку скрипта. Інший інструмент може змінити той самий файл; команда може викликати дочірній процес; окремий процес може обійти життєвий цикл Claude Code; дозволи чи налаштування можуть не завантажитись; matcher-и можуть не відповідати тому імені, яке очікували. Документація попереджає: якщо скрипт не запускається або його вихід не проходить перевірку схеми, більшість подій продовжують роботу без рішення hook-а. Перевіряйте фактичні джерела конфігурації, повідомлення помилок і записи діагностики, а не лише наявність файла JSON у Git.
У цьому курсі межі розподілені між розділами: правила, дозволи, пісочниця й review доповнюють одне одного, але не дублюються автоматично. Hook краще зберегти для подієвого контролю та повторюваної автоматизації. Дозволи виражають, що агенту дозволено викликати; ізоляція й права процесу обмежують доступ на рівні виконання; review підтверджує рішення й наслідки. Повніший розгляд безпеки та інтеграції безперервної інтеграції (Continuous Integration, CI) наведено у главах 55 і 56.
34.7. Три розібрані випадки
Усі назви компаній, файлів, людей, систем і даних у прикладах нижче вигадані. Це навчальні сценарії, а не твердження про справжню конфігурацію або правила якогось замовника.
Випадок 1. Захист файла політики перед редагуванням
Команда вигаданої платформи «Ліхтар» підтримує файл config/pricing-policy.json. Лише власник продукту має вносити зміни до нього через погоджений review; звичайні текстові файли й компоненти інтерфейсу агенти можуть редагувати в робочій копії. Команді потрібно виявляти саме спробу інструмента Edit або Write змінити захищений шлях.
Проєктний hook під’єднаний до PreToolUse з matcher-ом Edit|Write. Скрипт читає tool_input.file_path, нормалізує шлях і порівнює його з коренем репозиторію та точним шляхом політики. Він не вгадує шлях за назвою, не шукає слово «price» у довільному тексті та не використовує eval. Якщо ціль — config/pricing-policy.json, hook повертає валідний JSON із permissionDecision: deny та короткою причиною. Якщо ціль — наприклад, src/catalog-card.tsx, hook не повертає рішення: звичайний процес дозволів Claude Code залишається чинним. Не потрібно повертати allow для кожного дозволеного файла: такий дозвіл може прибрати очікуване підтвердження і не є нейтральним повідомленням.
Очікуваний результат. Виклик Edit для src/catalog-card.tsx проходить до звичайної перевірки дозволів і редагується лише в межах наданих прав. Виклик Write для config/pricing-policy.json зупиняється до запису; Claude отримує причину, а файл не змінено цим викликом.
Що це не закриває. Hook не є контролем кожної можливої зміни на диску: PreToolUse працює для інструментальних викликів, а не для контексту, доданого через @; команда Bash або сторонній процес може змінити файл іншим маршрутом. Для цих сценаріїв потрібні відповідні дозволи на команди, права файлів, захищена гілка або інша зовнішня межа. Післяфайлова подія FileChanged може зафіксувати зміну, але не здатна заборонити вже виконаний запис. Якщо автор, якого треба контролювати, може редагувати і hook, і файл налаштувань, сам hook не дає незалежного захисту.
Випадок 2. Форматування та валідація після запису
Вигадана команда змінює таблицю регіональних коефіцієнтів у data/regions.json. Hook PostToolUse з matcher-ом Edit|Write запускає два кроки: форматувальник змінює стиль саме цього файла; валідатор перевіряє структуру JSON, обов’язкові ключі та типи значень. Він може переставити поля за однаковим порядком і виправити відступи. Він не редагує package-lock.json, тестові дані чи решту репозиторію, якщо процедура спеціально не націлена на них. Валідатор читає змінений файл і залишає звіт у контексті; форматувальник модифікує його.
Очікуваний результат. Якщо форматування чи схема не проходить, Claude отримує конкретне повідомлення після успішного запису й може виправити файл у наступному виклику. Перший запис однаково вже відбувся: PostToolUse не стає передумовою, а помилка hook-а не означає автоматичного відкату. Якщо форматувальник сам змінює файл, наступний review має прочитати остаточний вміст, а не припускати, що він збігається з тим, що спершу надіслав інструмент.
Чого перевірка не доводить. Валідний JSON і єдиний формат не відповідають на питання, чи правильні ставки для потрібної аудиторії, чи однаково трактуються історичні дані, чи відповідає таблиця вимогам продукту. Для цього потрібні бізнес-правила та докази відповідних тестів. Форматувальник і схема можуть успішно завершитися, коли значення помилкові, але синтаксично допустимі.
Межа події. PostToolUse для Edit|Write спрацьовує після успішного виклику цих інструментів. Він може не запуститися, якщо помилку дав інший інструмент або якщо той самий файл переписала Bash-команда. Для помилки вже розпочатого інструмента існує PostToolUseFailure, але відмови до запуску інструмента мають інші події. Тому цей hook — корисний зворотний зв’язок, а не повний список усіх змін і невдач.
Випадок 3. Перевищено тайм-аут перевірки
Є два гіпотетичні запуски одного зовнішнього сервісу верифікації, який іноді затримує відповідь.
Низький ризик — форматування нотатки. Після редагування вигаданої внутрішньої довідки hook перевіряє Markdown-стиль і очікує не довше п’яти секунд. Якщо перевищено ліміт, поточний файл залишається у своїй останній записаній версії. Команда вирішує не зупиняти подальше редагування лише через недоступність форматувальника: Claude отримує повідомлення, що автоматична перевірка не завершилась, а автор знає, що стиль лишився неперевіреним. Це свідоме fail-open для неважливої форматної якості, а не приховане твердження «все пройшло».
Високий ризик — публікація нового тарифу. Перевірка має підтвердити дозвіл і цільове середовище перед зміною ставки у зовнішній платіжній системі. Якщо сервіс не відповів, команда не має трактувати це як схвалення. Проте один синхронний командний PreToolUse не гарантує такого результату: документація каже, що після його тайм-ауту виклик продовжується через звичайний процес дозволів. Тому fail-closed реалізують у самій контрольній межі: наприклад, облікові дані для публікації доступні тільки окремому брокеру, який вимагає явного рішення; без цього рішення брокер не змінює тариф. Правило Claude Code може додатково попросити людину про підтвердження, але не підміняє перевірку на стороні сервісу. Якщо перевіряльник недоступний, Claude повідомляє, що публікацію не завершено й авторизацію не отримано.
Зіставлення результатів. У першому випадку далі працюють із відомою чернеткою, приймаючи обмежений ризик неперевіреного форматування. У другому зовнішня система не приймає зміну без позитивного дозволу, тому недоступність контролю не перетворюється на можливість публікувати. Fail-open і fail-closed — це обрана реакція всієї системи на відсутність доказу, а не лише назва поля тайм-ауту.
34.8. Як супроводжувати hooks
У кожного hook-а має бути зрозуміла роль, власник і межа застосування. Документуйте для події, фільтра та рішення: яку умову перевіряють; які значення читають; коли невдала перевірка блокує, просить підтвердження чи лише повідомляє; які права має сам скрипт. Ведіть журнал рішення без секретів і зайвих фрагментів аргументів. Якщо декілька hook-ів реагують на той самий виклик, зазначайте їхні незалежні дії та пріоритети.
Після зміни Claude Code, скрипта, залежності або форми параметрів перевіряйте документацію та приклади payload для відповідної події. Matcher може непомітно перестати відповідати інструменту; конфігурація може бути синтаксично неправильною; виконуваний файл може бути відсутній; JSON-вихід може містити службовий текст; код 1 може не блокувати дію. Перевірка того, що налаштування завантажено, ще не доводить, що потрібний обробник запустився й повернув рішення.
Не прив’язуйте повільний зовнішній сервіс до кожного нешкідливого читання чи редагування. Використовуйте matcher лише на потрібних подіях, скорочуйте вхідні дані до необхідного, ставте ліміт часу й продумуйте ізоляцію сервісу. Якщо критичний контроль не спрацював, система має показати це як неперевірений результат, а не як «успіх без помилок». Зберігайте реальні тести на сам hook і на правила доступу в межах процесу команди; цю главу не супроводжує встановлення або запуск hook-ів.
34.9. Головне для роботи
Hook відповідає на питання «яка автоматична дія відбудеться, коли станеться ця подія?». Це корисно для чітких, повторюваних процедур: перевірити виклик до дії, відформатувати файл після запису, додати сигнал про помилку. Але сила рішення залежить від події, вихідного формату, прав процесу та інших рівнів контролю. PreToolUse може відхилити інструментальний виклик; PostToolUse лише працює з тим, що вже сталося. Навіть точний hook не замінює бізнес-перевірку чи права операційного середовища.
Якщо правило важливе, з’ясуйте чотири речі: який саме виклик воно бачить; як саме повертається відмова; що станеться при тайм-ауті або помилці; який нижчий рівень не дасть обійти правило іншим маршрутом. Ці відповіді показують, чи hook справді служить потрібному контролю, чи лише створює відчуття захисту.
Джерела та подальше читання
Довідкові сторінки Claude Code можуть змінюватися. Нижче вказано версію та дату зрізу, до яких прив’язані мінливі факти.
- Anthropic, Claude Code Hooks, поточний довідник подій, полів, рішень і помилок; звірено 10.10.2026.
- Anthropic, Automate actions with hooks, сценарії до й після редагування та приклади використання; звірено 10.10.2026.
- Anthropic, Claude Code Security, дозволи, ізоляція й межа відповідальності користувача; звірено 10.10.2026.
- Anthropic, Settings files and precedence, джерела конфігурації, спільні й локальні налаштування; звірено 10.10.2026.
- Anthropic, Claude Code changelog, найновіший випуск на дату зрізу — версія 2.1.296 від 09.10.2026; перевіряйте окремо версію встановленого клієнта.
- Anthropic, Claude Code v2.1.296 release notes, випуск від 09.10.2026, перевірено 10.10.2026.
- anthropics/claude-code, issue #85250: reported hook timeout/process-startup hang, створено 09.08.2026; має мітку
reproducedBugі лишається відкритим на час перевірки 10.10.2026. Звіт описує версію 2.1.226 у Windows, тому не переноситься на всі версії.