JavaRush /Курсы /Claude Code SELF /Само по волшебству: hook

Само по волшебству: hook

Claude Code SELF
8 уровень , 3 лекция
Открыта

1. Как это называется у агента

Тёма сгонял за кофе, сел рядом. В голове уже уложилось: событие, обработчик, стрелочка, готовый список событий. Осталось узнать, как эта штука зовётся у его агента.

— Называется hook, — говорит Лёха. — По-русски считай «авто-действие на событие». Это ровно твоя стрелочка, только внутри сессии с агентом: случилось определённое событие — ты отправил запрос, агент закончил ответ, агент правит файл — и привязанный обработчик выполнился сам. Без напоминаний, без «лишь бы не забыть». Событие случилось — действие сработало, точка.

— Слушай, так это же не «попросить агента сделать», — Тёма медлит. — Это… настроить, чтоб он сам делал.

— Ну вот, дошло, — Лёха доволен. — То самое кресло настройщика, про которое я толковал. Один раз повесил hook — и дальше оно живёт без тебя. Самый частый первый пример — после каждой правки код сам причёсывается, ты пальцем не шевелил. Через час ловишь себя, что вообще перестал про это думать. Оно само.

— Можно подробнее, — Тёма уже примеряет руки. — Где это всё настраивается?

— В файле проекта, .claude/settings.json, — кивает Лёха. — Туда кладётся событие плюс команда, что выполнить. А проверить, что хук встал, — командой /hooks прямо в сессии. Запомни саму суть: hook — это действие, привязанное к событию сессии; срабатывает само — каждый раз, а не «когда вспомнил». Ты впервые настраиваешь поведение агента, а не дёргаешь его за руку по одному действию.

2. Журнал, который пишется сам

— Хватит слов, — говорит Лёха. — И руками в конфиг лезть не будешь — не царское это дело. Просто попроси ИИ-агента словами, ровно как свою спеку проговорил. Скажи ему: повесь хук.

Тёма так и делает — пишет агенту обычной фразой, как привык:

Повесь hook: на каждый мой запрос дописывай его текст со временем в файл requests.log.

Агент не переспрашивает — берётся сам. Кладёт рядом маленький скрипт-обработчик .claude/hooks/log-prompt.sh и прописывает событие в .claude/settings.json — там лежат настройки проекта. Лёха разворачивает на экране то, что агент только что положил, чтоб Тёма увидел свою спеку живьём:

{
  "hooks": {
    "UserPromptSubmit": [
      {
        "hooks": [
          { "type": "command", "command": ".claude/hooks/log-prompt.sh" }
        ]
      }
    ]
  }
}

— Сейчас я все объясню, не пугайся скобок, — Лёха разбирает строку за строкой, не давая Тёме утонуть. — UserPromptSubmit — это событие: «пользователь отправил запрос агенту», ровно тот момент, что ты записал в спеку. Тут даже фильтр не нужен — событие одно, не на что реагировать выборочно. А command — это что выполнить: запустить наш маленький скрипт, который и допишет строку в журнал. Узнаёшь? Это твой HOOK_SPEC, только на языке агента. Событие, действие, куда писать — все три графы тут.

— А почему отдельный скрипт, а не строчка прямо тут?

— Потому что текст твоего запроса агент передаёт хуку не как попало, а пакетом — в формате JSON, с которым мы возились на радаре. Скрипт этот пакет распакует и вытащит сам запрос. Глянь, что агент туда положил, он крошечный.

Лёха открывает файл .claude/hooks/log-prompt.sh, который агент только что завёл сам:

#!/bin/bash
INPUT=$(cat)                                        # пакет с данными приходит сюда
PROMPT=$(echo "$INPUT" | jq -r '.prompt')           # достаём из него текст запроса
echo "[$(date '+%H:%M')] $PROMPT" >> requests.log   # дописываем в журнал

— Три строки: поймать пакет, вытащить из него текст запроса, дописать в requests.log с временем. Та самая стрелочка событие → действие, только живым кодом. Скрипту нужен jq — это стандартный инструмент для разбора JSON, и сам файл должен быть исполняемым, но это агент сделает за тебя.

— Так это ж мои три строки, — Тёма всматривается. Та абстрактная стрелочка из прошлой лекции — событие → действие — лежит теперь перед ним в виде двух файлов: вот событие (UserPromptSubmit), вот действие (command → скрипт), вот файл (requests.log). Не схема на пальцах, а реальная настройка, которая сейчас заработает.

— Хорошо, что мы сказали агенту создать этот хук. Не хотел бы я сам такое писать, — Тёму аж передергивает. — Хорошо, что теперь такие вещи ИИ пишет. Брр.

Лёха проверяет, что хук на месте, и предлагает работать как обычно:

/hooks       # показывает настроенные хуки — наш UserPromptSubmit должен быть тут
Поправь функцию счёта в Тетрисе.

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

Тёма отправляет запрос. И сама собой в requests.log появляется строка: время и текст того, что он только что попросил. Он её не дописывал. Отправляет следующий — ещё строка.

— Я ж пальцем не шевельнул, — он смотрит на файл, который пополняется без единого его движения. Под этим что-то сдвинулось: он больше не ведёт записи руками каждый раз, он настроил поведение один раз. Через час тут будет готовый журнал всех его запросов, который он не вёл ни секунды.

3. Бонус: пусть скажет «Готово» вслух

— Раз уж можно вешать действия на события, — Лёха хмыкает, — повесим что-нибудь весёлое. Хочешь, агент будет говорить вслух, когда закончил? Это тоже hook, только на другое событие — Stop, то есть «агент завершил ответ». И вешаешь так же — словами, не руками.

Тёма уже без подсказки кидает агенту фразу:

Повесь ещё hook: когда закончишь ответ, проговаривай «Готово» вслух.

Агент добавляет в settings.json ещё один хук — на этот раз на событие Stop:

{
  "hooks": {
    "Stop": [
      { "hooks": [ { "type": "command", "command": "say 'Готово, сэр'" } ] }
    ]
  }
}

say — это команда твоей операционной системы, она произносит текст голосом, — поясняет Лёха. — На маке есть из коробки, на других системах свои аналоги. Как только агент закончит задачу, комп скажет «Готово».

— Опа, заговорил! — Тёма аж подскакивает: машина отозвалась голосом. — Дворецкий, блин! У меня теперь комп-дворецкий: я лежу — он докладывает «всё готово, сэр». Как я без этого жил?!

— Вот тут запомни, это важно, — Лёха сразу ставит границу. — Это не «агент заговорил». Никто не ожил. Это твой хук дёрнул системную команду озвучки — ту же say, ну или другую под твою ОС. Ты сам повесил хук «закончил работу → произнеси слово». Магия не в ИИ, а в том, что ты привязал действие к событию. Так на него и смотри: то же авто-действие, что и в случае с журналом, только этот вслух. Но, прикольно — да.

— Да понял-понял, — Тёма кивает, а сам нет-нет да ухмыльнётся: говорящий комп ему всё равно страшно нравится.

4. Жёсткая граница: след, а не память

И тут Тёма выдаёт:

— Так получается, я сделал журнал — значит, теперь агент всё помнит! У него типа память появилась, да?

Нет, — Лёха обрывает жёстко, без улыбки. — Вот это самое важное предупреждение за весь день, не пропусти. requests.log — это внешний след, файл-журнал снаружи. Это не память агента и не «база знаний, из которой он что-то узнаёт». Журнал нужен тебе — заглянуть, что и когда делалось. Агент от наличия этого файла умнее не стал и ничего нового не запомнил.

— А в чём тогда разница? — Тёма хмурится, не сразу видит. — Файл же есть, в нём всё записано.

— В том, кому он служит, — Лёха разводит две вещи. — Смотри: hook — это внешний журнал плюс авто-реакция на событие. То, что мы сейчас сделали. А вот память агента — чтоб он сам помнил контекст между сессиями, узнавал твой проект назавтра — это совсем другая вещь, отдельная тема, до неё ещё доберёмся. Не путай их. Сегодня мы не «починили память Claude». Мы завели внешний журнал, который пишется сам. Но это тоже круто, согласен.

— А, точно, — Тёма прокручивает в голове и ловит. Утром он же сам поставил диагноз: проблема не в памяти агента, а в том, что нет журнала снаружи. Журнал он и сделал. Память тут вообще ни при чём.

— Понял, — говорит. — Журнал для меня, не для него. Я себе блокнот завёл, а не агенту мозги пересадил.

— Вот теперь правильно, — кивает Лёха.

1
Задача
Claude code, 8 уровень, 3 лекция
Недоступна
Исправление hallucinated onboarding draft
Исправление hallucinated onboarding draft
1
Задача
Claude code, 8 уровень, 3 лекция
Недоступна
Черновик onboarding-документа через Claude CLI
Черновик onboarding-документа через Claude CLI
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ