AIDive

Пакет к видео

Claude Code Mods: эксперимент fail-open, измерения, чек-лист и источники

10 мин чтения

TL;DR

  • Мод Claude Code состоит из трех файлов: .claude-plugin/plugin.json, hooks/hooks.json с содержимым {"modules":["./index.ts"]} и TypeScript-модуля, который экспортирует register(on). Для загрузки больше ничего не нужно.
  • В сборке 2.1.272 типизированный интерфейс, который создает /plugin-types, занимает 11,783 строки в claude-code.d.ts: 84 имени событий или вызовов в 23 группах. fs.readFile исчез, теперь это fs.read и fs.write.
  • Хук tool.call в 42 строки заставил модель читать API_KEY=[REDACTED] вместо настоящего ключа и в инструменте Read, и в Bash: 27.9 мс на один нормальный переход и около 0 токенов, добавленных в сессию.
  • Хук, который спит дольше бюджета в 10 с или падает с исключением, пропускается, и команда ниже выполняется. В логе это видно, а по факту это обход: охранный Мод открыт при сбое (fail-open).
  • Сгенерированный путь работает: одна фраза дала Мод на 190 строк плюс 53 строки тестов примерно за 4 минуты и $1.23. claude plugin validate прошел без предупреждений, claude plugin test показал 4 pass / 0 fail.
  • Одно не воспроизвелось: Мод загрузился под claude -p, но молчал в интерактивном REPL через pty в двух попытках. Считайте загрузку в REPL непроверенной, пока не проверите в настоящем терминале.

Что показывают измерения

Все ниже запускалось на Claude Code 2.1.272 с установленной CLAUDE_CODE_ENABLE_FUNCTION_HOOKS: на написанном вручную Моде redact-secrets и на трех одноразовых Модах, созданных, чтобы его сломать. Саму функцию отслеживает предложение Function Hooks, которое пока остается самым близким к официальной спецификации s3.

Инструменты появились раньше документации. Сборка 2.1.272 содержит claude plugin validate, test, eval и details; test работает, хотя plugin --help не показывает его в списке команд s3. Запуск /plugin-types внутри сессии записал 11,783 строки в .claude/types/claude-code.d.ts, а также claude-code-mcp.d.ts на 3,438 строк с 150 MCP-инструментами из 7 серверов s3. В сгенерированных типах 84 имени событий или вызовов в 23 группах, и файл переименовывает одну вещь, о которой вы могли читать в сентябрьских постах: fs.readFile больше нет, интерфейс состоит из fs.read и fs.write s9. Те же типы говорят, что хук tool.call возвращает { result, context? } или { deny }; text и ref приходят из ядра и не входят в собственный ответ хука, поэтому переписывать нужно result, а не text s3.

claude plugin validate печатает footprint до первого запуска Мода: ./index.ts hooks: tool.call и ./index.ts calls: $.ui.toast, либо calls: nothing on $, если модуль не обращается к возможностям хоста s4. Эта статическая строка сегодня единственная проверка, которую каталог вроде awesome-claude-code-mods может автоматизировать, и это важно для следующего абзаца.

Редактирование секретов работает в режиме -p. Хук на 42 строки перехватил tool.call, и модель получила API_KEY=[REDACTED] там, где в файле и в выводе оболочки лежало sk-test1234567890abcdef, и для инструмента Read, и для Bash s3. Лог отладки показал для нормального перехода 27.9 мс на полный цикл, включая переход в worker и next() s3. claude plugin details оценил Мод примерно в 0 токенов, добавленных в каждую сессию: Мод это код внутри процесса, а не текст промпта, и это главный аргумент его сторонников против shell-хуков и skills s7.

Охранник открыт при сбое. Мод slow-guard, который спит 15 с, был прерван на бюджете в 10 с с сообщением hook failed: slow-guard: exceeded 10000ms budget (tool.call; skipped; what is below it ran in its place), и echo hi все равно выполнился s3. Мод throw-guard, который бросает исключение, был пропущен так же: hook failed: throw-guard: boom (tool.call; skipped; what is below it ran in its place), время 574.2 мс s3. В логе громко, по факту обход. Любой Мод, чья задача что-то блокировать, нужно читать с этим в голове: ошибка в охраннике это дыра, а не падение.

Генерация дешевая. По одной фразе модель написала рабочий Мод на 190 строк плюс 53 строки тестов примерно за 4 минуты, 34 хода и $1.23 (19,053 выходных токена, 497,282 прочитанных из кеша, 8,357 токенов рассуждения) s3. Этот Мод прошел claude plugin validate без предупреждений и claude plugin test с результатом 4 pass / 0 fail за 0.31 с и скрывал ключи вживую s3. На написанном вручную Моде claude plugin test отработал без API-ключа и без вызова модели: 1 pass за 0.25 с s3. Skill, который учит агентов писать Моды, уже существует, если хотите повторить опыт по шаблону s12.

Что не воспроизвелось: $.ui.toast ни разу не отобразился, потому что Мод не загрузился в REPL через pty в 2 попытках; в -p аналог проявился только строкой в отладочном логе. Наблюдалось обратное утверждению "только в REPL", которое ходит по X, а первопричину выделить не удалось s8. Heartbeat зависшего worker на 5 с тоже не проверялся; измерены только бюджет ожидания в 10 с и путь с исключением.

Измерения

Случай Что делает Мод Результат Время
redact-secrets, инструмент Read Переписывает result в tool.call Модель видит API_KEY=[REDACTED] 27.9 мс на переход
redact-secrets, инструмент Bash Тот же хук, вывод оболочки Модель видит API_KEY=[REDACTED] 27.9 мс на переход
slow-guard Спит 15 с внутри tool.call Пропущен, echo hi выполнился прерван на 10000 мс
throw-guard Бросает boom внутри tool.call Пропущен, команда выполнилась 574.2 мс
сгенерированный Мод 190 строк + 53 строки тестов из одной фразы validate: без предупреждений; test: 4 pass / 0 fail ~4 мин, 34 хода, $1.23
claude plugin test на redact-secrets Без API-ключа, без вызова модели 1 pass 0.25 с
claude plugin details Стоимость Мода в сессии ~0 добавленных токенов n/a

Протокол: Claude Code 2.1.272, function hooks включены переменной окружения. Каждый Мод это каталог плагина с plugin.json, hooks/hooks.json и одним index.ts. Запуски шли через claude -p с включенным логом отладки; подготовленный файл и команда оболочки содержали sk-test1234567890abcdef. Случаи fail-open запускались Модом, который спит 15 с, и Модом, который бросает исключение, с echo hi в качестве охраняемой команды. Интерактивный REPL запускался через pty и не загрузил Мод в двух попытках.

Что сделать в понедельник

  • Запустите /plugin-types в сессии и откройте .claude/types/claude-code.d.ts: найдите fs.read и tool.call, прежде чем доверять любому сниппету из сентябрьского поста.
  • Напишите скелет Мода из трех файлов (plugin.json, hooks/hooks.json с {"modules":["./index.ts"]}, index.ts, экспортирующий register(on)) и запустите на нем claude plugin validate: прочитайте строки footprint hooks: и calls:.
  • Перенесите самый используемый shell-хук в обработчик tool.call, который переписывает result, и сравните время перехода в логе отладки с shell-версией.
  • Добавьте файл claude plugin test рядом с Модом, чтобы охранник запускался в CI без API-ключа.
  • Оберните каждый обработчик-охранник в try/catch, который при сбое возвращает { deny }: в этой сборке исключение или зависание на 10 с пропускает вас и пропускает команду.
  • Проверяйте Мод под claude -p и в своем настоящем интерактивном терминале по отдельности и записывайте, где он загрузился.
  • Перед установкой стороннего Мода запустите на нем claude plugin validate и отклоняйте все, у кого в строке calls: указаны возможности хоста, не нужные Моду по смыслу.

Читать дальше

  • Прочитайте issue с предложением целиком, включая PDF с архитектурой в комментариях: это единственный письменный контракт для register(on), бюджетов и перехода в worker s3.
  • Сравните с дизайном Command Code Mods, который запускает TypeScript против ModApi в процессе хоста: у систем общая форма и закрытый ранний доступ s2.
  • Превью claudefa.st написано, когда функция еще была предложением: полезно увидеть, что изменилось между текстом от 3 сентября и бинарником 2.1.272 s9.
  • Заметка Prathkum это самое ясное короткое объяснение, почему хуки в процессе выигрывают у shell-хуков по токенам и задержке s7.
  • cc-mod-waitwhat хороший первый Мод для чтения: UI над промптом, ничего не пишется в транскрипт s11.
  • cc-arcade показывает, как далеко достает $.ui: игры, нарисованные над промптом из Мода s5.
  • Справочник по хукам все еще описывает shell-модель; держите его открытым, чтобы сопоставить каждое старое событие с новым именем noun.event s1.
  • Скептики на X утверждают, что плагины уже все это покрывают, а интерфейс будет ломаться в каждом релизе; переименованная группа fs это один аргумент в их пользу s23.

Источники

  • Function Hooks proposal (issue #91870), GitHub, anthropics/claude-code. Почему читать: единственный текст, похожий на спецификацию Модов, с PDF об архитектуре и историей выпуска в комментариях.
  • Hooks reference, Claude Code docs. Почему читать: shell-модель хуков, с которой вы мигрируете, событие за событием.
  • Command Code Mods documentation, Command Code. Почему читать: прототип с той же формой TypeScript внутри процесса, помогает увидеть, что Anthropic скопировала или обошла.
  • awesome-claude-code-mods, GitHub, karanb192. Почему читать: автоматически сканируемый каталог публичных Модов, где footprint из validate это единственная проверка.
  • cc-arcade, GitHub, sezaakgun. Почему читать: демо, которое сделало функцию заметной, и обзор $.ui.
  • Boris Cherny announcement tweet, X, Boris Cherny. Почему читать: заявление о запуске от инженера Anthropic, так как блог-поста нет.
  • Prathkum: Function Hooks explained, X, Prathkum. Почему читать: лучшее короткое объяснение хуков против Модов для тех, кто уже пишет shell-хуки.
  • shipnotesai reaction thread, X, shipnotesai. Почему читать: где ходило утверждение "только в REPL", которое наш запуск опроверг.
  • Claude Code Function Hooks: Preview Behind a Flag, claudefa.st. Почему читать: объяснение до релиза, удобно сверять предложение с бинарником.
  • cc-mod-waitwhat, GitHub, GGGODLIN. Почему читать: небольшой читаемый Мод, который пишет в UI, а не в транскрипт.
  • claude-mods-skill, GitHub, BeLazy167. Почему читать: skill для генерации Модов, если хотите повторить опыт с одной фразой.
  • AxialisSoftware reaction, X, AxialisSoftware. Почему читать: скептическая позиция в одном твите.

FAQ

Заменяет ли Мод мои shell-хуки уже сегодня?

Пока нет, если что-то должно блокироваться. В 2.1.272 хук, который бросает исключение или стоит дольше 10 с, пропускается, и команда выполняется. Shell-хуки продолжают работать, поэтому блокирующие оставьте там, пока не появится объявленный catch или опция fail-closed.

Зачем нужен validate, если Мод и так работает?

Потому что его строки hooks: и calls: это единственный статический взгляд на то, чего Мод касается в $. Для вашего Мода это подтверждение footprint; для стороннего Мода это весь обзор, который вы получаете до запуска кода в вашем процессе.

Сколько стоит Мод за сессию?

claude plugin details показал около 0 добавленных токенов. Мод это код, работающий в движке, а не текст в промпте, и в этом его главное преимущество перед skill или правилом в CLAUDE.md.

Почему Мод загрузился в -p, но не в REPL?

Неизвестно. Две попытки через pty молчали, пока claude -p загружал и применял хук. Вероятная причина в окружении pty, а не в самой функции, поэтому проверьте на своем терминале, прежде чем полагаться на любую из сторон.