AIDive

Я собрал неофициальный Mod Claude Code, защита пропускает

AIDive · Опубликовано

Кодинг-агентыБезопасность ИИ

Двенадцать дней от «если вам это нужно» до Tetris

Claude Code Mods — это TypeScript-модули, которые работают внутри движка Claude Code и подключаются к его событиям в виде функций. Boris Cherny, который возглавляет направление Claude Code в Anthropic, анонсировал их пятью словами: «Claude mods are landing now». Пост собрал 2 400 лайков, и кто-то уже успел собрать Tetris прямо в терминале. Tetris, Doom и питомец, который растёт, пока Claude прогоняет ваши тесты, — всё это отрисовывается над полем промпта, без единого токена.

Анонс не ссылается ни на одну страницу документации. Вместо этого — ссылка на issue в GitHub, открытый инженером Anthropic на 12 дней раньше, с одним прописанным в нём условием. Alice Poteat написала, что реакция сообщества, скорее всего, и определит, выйдет ли функция вообще. Спустя 177 комментариев люди уже вовсю тестировали флагованный бинарник, замеряли его тайм-ауты и собирали на нём игры.

Показатель Значение
Лайков под анонсом 2 400
Комментариев в issue на GitHub 177
Типизированная поверхность в сборке этой недели 10 700 строк
Событий на существительных (сборка из issue-треда) 84 на 19
Mod'ов на GitHub за 48 часов 31

На момент написания страница документации отдаёт 404. Эта статья разбирает четыре способа расширить Claude Code, один полезный Mod, который мы собрали и нарочно сломали, и то, что всё ещё нестабильно, прежде чем вы выпустите свой.

Mod — это функция посередине

Дерево исходников определяет это одним предложением: Mod — это плагин Claude Code, поведение которого живёт в hooks-модуле. Одна запись регистрации подключает события движка в виде функций. На диске это папка плагина, hooks manifest, называющий ровно один модуль, и сам модуль.

Каждый хук — это функция от трёх вещей: $, двери, через которую проходит любой побочный эффект; события; и продолжения — остальной части цепочки под вами. Хуки вложены друг в друга, как middleware. Тот, что зарегистрирован первым, владеет событием, и ничто дальше по цепочке не может его подавить. Этот порядок задаётся конфигурацией, а не установкой. Как говорит Alice Poteat, порядок определяется конфигурацией, а не тем, когда вы установили хук.

Никакого фонового доступа нет. Всё, что делает Mod, проходит через $, поэтому администратор может аудировать, разрешать, запрещать или логировать любое событие. Один из комментаторов сформулировал это так: то, что сделал плагин, — это в точности те вызовы, которые он совершил. Один хук на * видит все события, так что журнал аудита — это одна функция. Mod умеет рисовать, потому что интерфейс — это React. Он работает в том же процессе, на Bun, за 50 микросекунд на 99-м перцентиле. Включается одной переменной окружения. То, что именно будет жить в $, всё ещё дорабатывается вместе с партнёрами раннего доступа.

Четыре способа расширить Claude Code — и когда какой нужен

Shell hook — это скрипт, который движок вызывает в фиксированный момент. Он получает JSON на стандартном вводе и отвечает кодом выхода. У ответа есть потолок: 8 000 символов контекста обратно, а для некоторых хуков — 2 000. По словам Pratham, на Windows они часто ломаются самым странным образом.

Плагин — это коробка. Один манифест объединяет скиллы, агенты, хуки и MCP-серверы. Он устанавливается из marketplace или загружается прямо из папки на диске, и одна команда проверяет коробку прежде, чем что-либо запустится.

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

Mod — это та же коробка плюс ещё один файл: hooks manifest, называющий модуль, а сам модуль — это TypeScript, типизированный, работающий в том же процессе, на каждом событии движка. В этом всё отличие.

Механизм Что это Работает Потолок
Shell hook Скрипт, вызываемый в фиксированный момент Отдельный процесс, код выхода 8 000 символов обратно (2 000 для некоторых хуков)
Плагин Набор скиллов, агентов, хуков, MCP-серверов Устанавливается или загружается с диска Проверяется перед запуском
Скилл Текст, загружаемый по подходящему промпту В контексте модели Самое дешёвое изменение
Mod Плагин плюс TypeScript hooks-модуль В том же процессе, на каждом событии Типизированный, ранний доступ

Типы приходят из одной slash-команды, которая записывает прямо в ваш проект полный список того, что предлагает $. Старые shell hooks не выведены из обращения, а обёрнуты. На ранней сборке Spencer Morley наблюдал, как обёртка не загрузилась, но осталась объявленной. Правило простое: чтобы изменить то, что знает Claude, — пишите скилл; чтобы запустить скрипт в определённый момент — shell hook; чтобы выпустить набор — плагин; чтобы встроиться внутрь движка — Mod. Shell hook по-прежнему работает везде, где флаг выключен.

Три собственных Mod'а Anthropic — по исходному коду

Три Mod'а поставляются прямо внутри бинарника, и их исходники лежат на GitHub: security-дефолт, панель diff и телеметрия.

Security-дефолт стоит снаружи всех остальных. На машине с managed settings или в организации уровня Team или Enterprise ничто из того, что устанавливает пользователь, не оказывается выше него. Он подключается к 12 событиям, и каждый хук делает одно из трёх: пропускает дальше пользовательский уровень, отклоняет вызывающего с пользовательского уровня по имени или пропускает без изменений. Он падает в закрытое состояние (fails closed), и комментарий в коде говорит об этом двумя словами. Именно это волновало тред: администратор убирает возможность из $, и ничто зарегистрированное ниже не может её вызвать. По словам одного из комментаторов, это принципиально отличается от просьбы к плагину чего-то не делать.

Diff — это панель рядом с транскриптом, показывающая незакоммиченные изменения сессии файл за файлом, обновляющаяся по мере того, как Claude редактирует. Она регистрируется при старте сессии и занимает 27 вспомогательных файлов — не игрушка.

Телеметрия добавляет существительное в $ прямо изнутри создания движка. Она дожидается того, что находится ниже, и возвращает это плюс саму себя. Работает только во внутренних сборках.

В README сказано запускать один из исходников и тестировать один из исходников. Help в сегодняшней сборке перечисляет validate, eval и details. В списке нет test, хотя help для test всё ещё отвечает. Встроенный уровень также отклоняет вашу копию: выпустите плагин с одним из этих имён — и бинарник загрузит свой собственный.

Сорок две строки: Mod, который прячет секреты от модели

Slash-команда, которая записывает типы, на этой сборке выдаёт 11 700 строк: 84 события на 23 существительных. Хук вызова инструмента отвечает результатом или отказом, но никогда текстом. Это задано ядром (core).

Mod состоит из трёх файлов: манифеста плагина, hooks manifest с его единственной строкой и самого модуля. Модуль — это 42 строки. Он дожидается того, что находится ниже, вычищает результат и возвращает его обратно. Четыре паттерна покрывают два формата ключей вендоров, GitHub-токен и всё, что присвоено переменной с именем key, secret или token.

Validate читает исходник до запуска. Он называет событие, к которому подключается модуль, и единственную вещь, которую тот вызывает на $. Единственное предупреждение — отсутствующий author. При загрузке с диска с включённым флагом тестовый файл содержит два ключа, оба заведомо фальшивые, и модель читает «redacted». Своими словами: значения вернулись как redacted, так что она не может увидеть, что в них.

Показатель Значение
Длина модуля 42 строки
Задержка на переход, с учётом воркера 28 мс
Токенов добавлено в сессию 0

Движок логирует переход как resolved (разрешённый) hooks-модулем. В инвентаре нет ни скиллов, ни агентов — ничего, что работало бы постоянно. Остаётся одно ограничение: скрытое от модели не скрыто от экрана. Транскрипт по-прежнему показывает то, что вывел инструмент. Это уже другой Mod, как в одной строке заметил Max из Ship Notes.

Ломаем: медленная защита — это обойдённая защита

Тот же Mod, одна добавленная строка: sleep на 15 секунд перед вызовом того, что находится ниже. Через десять секунд движок сдаётся, сообщает, что хук превысил свой бюджет и был пропущен (skipped), и вместо него выполняется то, что находится ниже. Команда всё равно выполняется и печатает «hi».

Заменяем sleep на throw: 574 миллисекунды, тот же вердикт — skipped, и команда выполняется.

Случай Время Вердикт
Здоровый хук 28 мс Resolved
Throw 574 мс Skipped, команда выполнена
Зависание более 10 с Skipped, команда выполнена

Оба сбоя заканчиваются одним и тем же словом: skipped. Тред измерил эту асимметрию неделей раньше. Возможность, отсутствующая при загрузке, падает в закрытое состояние (fails closed). Хук, превысивший бюджет, падает в открытое состояние (fails open): громко, но в обход, по словам Spencer Morley. Блокировка без причины просто отправляет модель к другому инструменту. Pratham наблюдал, как она выбрала другой инструмент и всё равно записала файл.

Ответ, который лежит на столе, — это catch. Alice Poteat предлагает catch на возврате хука, который срабатывает, если вы работаете слишком долго или бросаете исключение. Переписанная запись всё равно требует пометки для модели: она видит то, что попросила записать — по соображениям кеширования, — поэтому вы дописываете строку контекста. Бюджет — это ещё и изоляция. Hooks worker работает отдельно, и когда он падает, движок пересоздаёт его и выключает хуки для этой сессии. Решение — не более длинный бюджет, а объявленный catch.

Сорок восемь часов Mod'ов — и что покупает одно предложение

Через два дня: Tetris над полем промпта и ещё семь игр, в которые можно играть, пока работает Claude, — и всё это без единого токена. Doom, оригинал 1993 года, работает в собственном процессе; Mod обращается к нему по локальному HTTP и перерисовывает картинку 10 раз в секунду. Есть дышащий пейсер в спиннере и модель для генерации историй на 260 000 параметров, работающая прямо внутри hooks worker, без единого API-токена.

Реестр просканировал 31 Mod через validate. 14 из них умеют запускать процессы на хосте. 13 видят каждый вызов инструмента.

Демо №8 из треда сообщества обещало, что одно предложение напишет плагин, который прячет секреты до того, как их прочитает модель. Мы попросили такой.

Показатель Значение
Время 4 мин
Ходов (turns) 34
Стоимость $1.23
Строк (плюс тестовый файл) 190, против наших 42
Тесты 4 проходят за треть секунды

Он помечает то, что скрывает, по типу, проходит validate без замечаний и не требует ни API-ключа, ни вызова модели. Один из ответов в треде сформулировал так: allowlists — это продукт, Tetris — это демо.

Вывод: собирайте сейчас, выпускайте позже

Собственные цифры реестра — уже предупреждение. 14 из 31 Mod'а умеют запускать процессы на хосте, и единственная проверка — это статический footprint. Help для eval сам об этом говорит: прошедший набор тестов — это не проверка безопасности.

Сигнал Значение
Событий 8-го числа 20
Событий 15-го числа 84
Версий CLI за две недели 14
Баллов на Hacker News 2
Ответов на вопрос о совместимости 0

10-секундный бюджет живёт в рантайме, а не в типах, как заметил Marat. Нет ни строки в changelog, ни страницы документации, ни поста о запуске. Конкурент утверждает, что Anthropic скопировала идею: Ahmad Awais указывает на mods в Command Code — и он же пишет их пример-mod, так что учитывайте это. Пост «ранний доступ, API может измениться» набрал 357 лайков.

Собирайте свой Mod прямо сейчас, если вы уже пишете хуки и хотите получить аудит, редактирование (redaction) или панель. Подождите, если планируете выпустить его для команды, — пока контракт не зафиксирован. Именно эта открытость и позволила пользователям за считаные дни найти и бюджет, который падает в открытое состояние, и несовпадение типов в вызове MCP, и сбой обёртки.

Источники

Частые вопросы

Что такое Claude Code Mod?
Mod — это плагин Claude Code, поведение которого живёт в TypeScript hooks-модуле. Модуль регистрирует функции на события движка и работает в том же процессе, на Bun, а каждый побочный эффект проходит через объект `$`.
В чём разница между хуками, плагинами, скиллами и Mods в Claude Code?
Shell hook — это скрипт, который вызывается в фиксированный момент и отвечает кодом выхода. Плагин — это набор скиллов, агентов, хуков и MCP-серверов. Скилл — это текст, который модель загружает по подходящему промпту. Mod — это плагин с одним дополнительным файлом: типизированным TypeScript-модулем, который подключается к каждому событию движка в том же процессе.
Может ли Claude Code Mod скрывать секреты от модели?
Да. Mod на 42 строки, который дожидается результата инструмента, вычищает паттерны key, secret и token и возвращает редактированный текст, добавляет 28 мс на переход и не тратит ни одного токена. Он не скрывает значения из транскрипта на экране — для этого нужен другой Mod.
Почему медленный Claude Code Mod падает в открытое состояние?
Hooks worker выделяет каждому хуку бюджет в 10 секунд. Хук, который его превышает или бросает исключение, помечается как skipped, и вместо него выполняется цепочка ниже, так что защищённая команда всё равно выполняется. Предложенное Anthropic решение — declared catch на возврате хука.
Безопасно ли устанавливать Claude Code Mods?
Пока нет, по умолчанию — нет. Из 31 Mod'а, проиндексированного за первые 48 часов, 14 умеют запускать процессы на хосте, а 13 видят каждый вызов инструмента, и единственная проверка — статический footprint. Managed settings ставят security-дефолт Anthropic выше всего, что устанавливает пользователь.
Стоит ли собирать Claude Code Mod прямо сейчас?
Собирайте сейчас, если вы уже пишете хуки и хотите получить журнал аудита, redaction или панель diff. Подождите с выпуском для команды: функция в раннем доступе, API изменился с 20 до 84 событий за неделю, а страницы документации или строки в changelog пока нет.

Похожие видео