1. Hooks — окремий шар, а не «ще один tool»
Коли зовнішній tool уже пройшов preflight, а його claims усе одно зводяться до коду, tests і review, виникає наступне питання: що всередині самого Claude Code повторюється так часто, що це вже час автоматизувати? Саме звідси й ростуть hooks.
Коли ви вперше чуєте про hooks, легко сприйняти їх за ще одну інтеграцію, але hook відповідає зовсім на інше питання. Tool, MCP або plugin capability — це про «звідки взяти дані або куди сходити». Hook — про «що автоматично зробити, коли всередині Claude Code відбулося певне подія». MCP — двері назовні: issue tracker, моніторинг, документація, база даних, браузер. Hook — датчик і автоматика всередині дому. Двері не вирішують, коли вмикати світло в коридорі, — це робить датчик руху. Так само hook не потрібен, щоб «отримати дані з Jira». Він потрібен, щоб після редагування файла прогнати форматувач, перед записом у захищений шлях зупинити дію або на початку сесії нагадати правила проєкту.
Через це hooks майже ніколи не стоять у центрі архітектури. Вони не замінюють task spec, human review і tests — прибирають рутинні мікродії, які ви й так робите знову і знову. Намагається «думати замість вас» — тривожний сигнал. Допомагає не забути просту, повторювану, перевірювану дію — це його територія.
У Workflow Kit це особливо добре видно. Файл на кшталт .claude/hooks/format-on-edit.json не знає бізнес-логіки Commerce OS — що таке замовлення, повернення або MRR. Він автоматизує одну звичку: Claude змінив код у потрібній зоні — одразу прогони formatter. Скромно, корисно, без драматургії — найкращий тип автоматизації.
2. Подія → умова → дія
Термін event-driven automation звучить строго, а суть проста: ви не запускаєте команду вручну щоразу, а система сама реагує на подію. Не «я згадав і запустив formatter», а «відбулася подія — formatter викликався сам». Не «крок 1, потім крок 2», а «сталося X — перевір Y і виконай Z».
Найбільш побутова аналогія — датчик руху в коридорі. Рух — це event. Умова «лише вночі» — matcher. Увімкнути лампу — handler. Руху немає — лампа мовчить. Рух удень — фільтр не пропустив, лампа мовчить. Рух уночі — фільтр підійшов, лампа засвітилася. Hook улаштований рівно так само, тільки замість коридору у вас життєвий цикл інструментів, файлів і сесій.
flowchart TD
A[Усередині Claude Code сталася подія] --> B{Matcher підходить?}
B -- Ні --> C[Hook мовчить]
B -- Так --> D[Запускається handler]
D --> E[Корисна дія: форматування, блокування, нагадування]
Із цієї схеми випливає важлива річ: hook не існує сам по собі. Поки подія не сталася, він спить — не «періодично розумує», а чекає моменту. Саме тому hooks і добрі для подієвої механіки навколо workflow: перед інструментом, після редагування, на початку або в кінці сесії. Для довгих міркувань, аналізу кодової бази й складних рішень потрібні інші механізми.
І ще одна корисна думка. Hooks здаються магією рівно до того моменту, поки ви не промовите фразу вголос: «Коли Claude змінив TypeScript-файл у src/, запусти formatter». Усе, лишилася інженерна формула.
Hook = подія + умова + дія.
3. Склад hook: event, matcher, handler
Зараз найважливіше — навчитися читати hook як маленький контракт із трьох частин, а не «JSON, який іноді запускається». Слова англійські, сенс земний: event — подія, matcher — фільтр, handler — обробник. Найзручніше це видно в таблиці:
| Частина | Головне питання | Що означає |
|---|---|---|
|
Коли? | У який момент lifecycle Claude Code взагалі варто реагувати |
|
За якої умови? | Як звузити спрацьовування до потрібних шляхів, інструментів чи ситуацій |
|
Що зробити? | Яку команду або скрипт реально виконати |
Тут корисно не плутати hook з уже знайомими сутностями. Skill ви викликаєте як повторювану процедуру — вручну або через trigger. Agent отримує роль і окремий контекст. Hook нічого не досліджує і не планує — спрацьовує, коли збігся шаблон. У цьому його сила і його межа. Тягне запхати в hook піворкестру складних кроків — інструмент вибрано не той.
Ще один важливий момент: точні назви подій, синтаксис matcher і структура конфига можуть трохи змінюватися між версіями Claude Code. Тримаємося моделі з трьох частин, а не «цей ключ називається тільки так». Актуальний синтаксис звіряєте через /hooks і поточну довідку.
4. Три групи event
Повний список подій конкретної версії дивляться в інструменті, а заучувати його напам’ять — це романтика рівня ручного редагування XML у п’ятницю ввечері. Але одну карту в голові тримати варто: майже всі корисні hooks укладаються в три групи — before tool use, after tool use / file changes і session lifecycle.
| Група подій | Що означає по-людськи | Типові сценарії |
|---|---|---|
| Before tool use | Спрацювати до небезпечної або важливої дії | заблокувати запис у захищений шлях, попросити підтвердження, не дати виконати ризиковану команду |
| After tool use / file changes | Спрацювати після дії або зміни файла | форматування, короткий звіт, запуск локальної перевірки, нагадування |
| Session lifecycle | Спрацювати на етапах життя сесії | показати банер на початку, зберегти стан, надіслати сповіщення, завантажити корисний контекст |
Група before tool use — це ваш «вахтер на вході». Вона особливо корисна там, де важливо не забути про межі. Наприклад, ви не хочете, щоб Claude автоматично редагував .env або щось у payments/. Тоді before-hook може побачити спробу запису й вчасно її зупинити. Це не про зручність, а про захисний контур.
Група after tool use — навпаки, про реакцію після дії. Якщо Claude вже змінив файл, тут доречні форматування, запуск легкої перевірки або зрозуміле коротке повідомлення в лог. Саме сюди зазвичай потрапляє базовий format-on-edit hook. Він нікого не зупиняє і не сперечається з вами про сенс життя. Він просто робить маленьку рутинну річ одразу після правки.
Група session lifecycle часто недооцінена, а дарма. Іноді корисніше не блокувати і не форматувати, а просто на початку сесії нагадати правила проєкту. Наприклад: «Перевірте git status», «Не чіпайте payments/ без окремого плану», «Використовуйте лише approved commands». Це дрібниця, але саме з таких дрібниць потім складається командна дисципліна.
Зверніть увагу: всі ці групи описують внутрішнє життя Claude Code, а не зовнішній світ. Hook не про те, що «в Jira з’явився новий тікет». Hook про те, що «всередині моєї поточної роботи настав момент, на який варто автоматично відреагувати».
5. matcher: точність замість нав’язливості
Якщо event відповідає за момент, то matcher відповідає за точність. І саме тут найчастіше починаються справжні педагогічні пригоди. Новачки люблять написати щось надто широке на кшталт «на всі файли» або «на всі команди», а потім дивуватися, що автоматизація спрацьовує частіше, ніж сповіщення від банківського застосунку. Проблема не в самому hook, а в надто широкому matcher.
Matcher — це фільтр. Він відповідає на питання: за яких саме обставин після події потрібно запускати обробник. Фільтр може дивитися на шлях до файла, тип інструмента, шаблон команди, іноді — на додаткові ознаки контексту. Але важливіше не список можливостей, а принцип: matcher має бути настільки вузьким, наскільки це розумно.
Подивіться на різницю між двома думками. Перша: «Після будь-якої зміни будь-якого файла запускай formatter». Друга: «Після зміни файлів у src/, якщо це ts або tsx, запускай formatter». Друга думка нудніша. А нудні думки в автоматизації, як правило, безпечніші.
Для першого читання нам важлива сама форма hook, а не фінальна конфігурація для проєкту. Тому нижче — схематичний приклад matcher для форматування:
{
"event": "afterFileEdit",
"matcher": { "paths": ["src/**/*.ts", "src/**/*.tsx"] },
"handler": { "command": "prettier --write {{file}}" }
}
Точні шляхи й команда залежать від структури repo та від того, який formatter прийнято в проєкті, але логіка та сама. Hook не чіпає конфіги, markdown, shell-скрипти й чужі директорії. Він реагує тільки на ту зону, заради якої взагалі був задуманий.
Тепер інший сценарій — захист чутливих шляхів. Тут matcher уже не про розширення файла, а про ризиковану ділянку проєкту:
{
"event": "beforeToolUse",
"matcher": { "tool": "Write", "paths": ["**/payments/**", "**/.env*"] },
"handler": { "command": "scripts/block-protected-write.sh" }
}
Такий фільтр уже працює як охоронець на потрібних дверях. Він не заважає редагувати звичайний код, але не дає бездумно лізти в небезпечні зони. І це дуже добра звичка для Workflow Kit: не намагатися поставити одну гігантську пастку на все підряд, а ставити точкові рамки там, де blast radius справді великий.
Якщо вагаєтеся, робіть matcher вужчим, а не ширшим. Шумний hook швидко привчає команду його ігнорувати. А hook, якому перестали довіряти, фактично вже мертвий — просто ще лежить у репозиторії.
6. handler: межа між конфігом і дією
Після event і matcher лишається найприземленіша частина — handler. Він відповідає на питання: що саме виконати, коли все збіглося. І це найкращий момент, щоб остаточно розвіяти магію. Handler — не таємний інтелект, не прихований subagent і не маленький оркестр. Найчастіше це просто команда або скрипт.
Іноді handler зовсім невеликий: викликати formatter для файла. Іноді це shell-скрипт, який друкує нагадування. Іноді — guard-скрипт, який перевіряє шлях і завершує виконання з потрібним статусом. Сенс один: hook знайшов потрібну ситуацію, а handler зробив одну зрозумілу річ.
Наприклад, handler на рівні сесії може бути буквально таким:
#!/usr/bin/env bash
echo "Перевірте git status і scope задачі" # нагадування
echo "Не чіпайте payments/ без окремого плану" # правило проєкту
Так, це вже повноцінний handler. Жодного чаклунства. Просто маленький скрипт, який допомагає не забути контекст на початку роботи.
Корисно тримати в голові дві практичні межі. По-перше, handler має бути передбачуваним. Якщо після одного edit у вас запускається гігантський ланцюжок команд на двадцять секунд, ви доволі швидко зненавидите власну автоматизацію. По-друге, handler має бути вузько корисним. Якщо ви раптом розумієте, що він уже схожий на мініплатформу з п’ятьма гілками поведінки, логами, евристиками й внутрішньою філософією, можливо, це вже не hook-задача, а окремий script/tool/skill.
Так, handler зазвичай отримує частину контексту події: шлях до файла, ім’я інструмента або інший payload. Але глибоко в технічні деталі передавання цих значень сьогодні не заглядаємо. На рівні ментальної моделі достатньо розуміти: hook не лише знає, що сталося, а й може передати обробнику дані, щоб той спрацював не «взагалі», а на конкретному файлі або дії.
7. Перший hook у Workflow Kit
Тепер давайте зберемо все разом на артефакті, який справді живе в нашій проєктній лінії. У Claude Workflow Kit for Team hooks — це не абстрактна теорія, а звичайні файли репозиторію всередині .claude/hooks/. Команда підтримує їх так само, як CLAUDE.md, skills і agents. Тобто hook — це процесний артефакт, а не шматочок «магії всередині Commerce OS».
Нижче — базові, схематичні версії таких hooks. Вони потрібні не для того, щоб копіювати їх як є, а для того, щоб навчитися читати hook як процесний артефакт команди: подія, фільтр, дія. Щойно ви переходите до реального репозиторію, спочатку перевіряються matcher, побічні ефекти й шлях вимкнення.
Перший базовий приклад — наш уже знайомий format-on-edit:
// .claude/hooks/format-on-edit.json
{
"event": "afterFileEdit",
"matcher": { "paths": ["src/**/*.ts", "src/**/*.tsx"] },
"handler": { "command": "prettier --write {{file}}" }
}
Якщо читати цей файл як звичайне речення, виходить дуже наочно: після редагування файла, якщо шлях потрапляє в src/**/*.ts(x), запусти formatter. Жодного «штучного інтелекту всередині hook». Просто добра інженерна дисципліна, упакована в маленький конфіг.
Другий приклад — захист чутливих зон. У Workflow Kit цілком природно тримати окремий hook, який не дає випадково писати в області, де помилки коштують дорого:
// .claude/hooks/block-protected-paths.json
{
"event": "beforeToolUse",
"matcher": { "tool": "Write", "paths": ["**/payments/**", "**/.env*"] },
"handler": { "command": "scripts/block-protected-write.sh" }
}
Тут добре видно різницю ролей. Event — «перед використанням інструмента запису». Matcher — «лише якщо запис іде в payments/ або .env*». Handler — «виклич захисний скрипт». Такий hook не робить проєкт розумнішим. Він робить проєкт спокійнішим.
І, нарешті, мʼякший сценарій — банер на початку сесії. Він узагалі нічого не блокує, зате допомагає швидко заземлитися в правилах поточного репозиторію:
// .claude/hooks/session-banner.json
{
"event": "sessionStart",
"handler": { "command": "scripts/session-banner.sh" }
}
#!/usr/bin/env bash
echo "Перевірте git status і scope задачі" # нагадування
echo "Якщо задача нетривіальна — почніть із плану" # ще одне правило
Зверніть увагу, як акуратно складається загальна картина. Один hook допомагає з чистотою коду. Другий — з безпекою. Третій — з дисципліною початку роботи. Усі три улаштовані однаково. І якщо ви навчилися читати один, ви вже вмієте читати інші.
Тому найкорисніша навичка цієї лекції звучить дуже просто: коли ви відкриваєте hook-конфіг, не дивіться на нього як на «ще один JSON». Читайте його як домовленість команди:
Коли відбулося це, і лише якщо збіглася оця умова, потрібно автоматично зробити ось цю дію.
Прочитали конфіг за цією формулою — і одразу бачите три частини контракту: event відповідає на питання «коли», matcher — «за якої умови», handler — «що зробити». Зібрані разом, вони й дають ваш перший змістовний hook у Workflow Kit. А ось які задачі варто довіряти hook, а які він лише зіпсує, і як розгортати його по кроках — тема наступної лекції.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ