JavaRush /Курсы /Claude code /Hooks: event,

Hooks: event, matcher и handler

Claude code
14 уровень , 2 лекция
Открыта

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 устроен ровно так, только вместо коридора у вас lifecycle инструментов, файлов и сессий.

flowchart TD
    A[Внутри Claude Code произошло событие] --> B{Matcher подходит?}
    B -- Нет --> C[Hook молчит]
    B -- Да --> D[Запускается handler]
    D --> E[Полезное действие: форматирование, блокировка, напоминание]

Из этой схемы следует важная вещь: hook не существует сам по себе. Пока событие не случилось, он спит — не «периодически умничает», а ждёт момента. Потому hooks и хороши для событийной механики вокруг workflow: перед инструментом, после редактирования, в начале или конце сессии. Для длинных рассуждений, анализа кодовой базы и сложных решений нужны другие механизмы.

И ещё одна полезная мысль. Hooks кажутся магией ровно до того момента, пока вы не проговорите фразу вслух: «Когда Claude изменил TypeScript-файл в src/, запусти форматтер». Всё, осталась инженерная формула.

Hook = событие + условие + действие.

3. Состав hook: event, matcher, handler

Сейчас самое важное — научиться читать hook как маленький контракт из трёх частей, а не «JSON, который иногда запускается». Слова английские, смысл земной: event — событие, matcher — фильтр, handler — обработчик. Удобнее всего в таблице:

Часть Главный вопрос Что означает
event
Когда? В какой момент lifecycle Claude Code вообще стоит реагировать
matcher
При каком условии? Как сузить срабатывание до нужных путей, инструментов или ситуаций
handler
Что сделать? Какую команду или скрипт реально выполнить

Здесь полезно не путать 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, а какие он только испортит, и как раскатывать его по шагам — тема следующей лекции.

1
Задача
Claude code, 14 уровень, 2 лекция
Недоступна
Создание базового after-edit hook
Создание базового after-edit hook
1
Задача
Claude code, 14 уровень, 2 лекция
Недоступна
Мини-сценарий для before-tool guard hook
Мини-сценарий для before-tool guard hook
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ