- Попросите Claude написать его: опишите, что вы хотите в сеансе Claude Code
- Напишите его сами: следуйте руководству, чтобы узнать, как работает код мода. Вам не нужны Node.js, бандлер или этап сборки, потому что Claude Code загружает файлы
.jsи.tsнапрямую.
Моды требуют Claude Code v2.1.287 или позже. В вашей оболочке выполните
claude --version, чтобы проверить. Чтобы узнать, могут ли моды загружаться для вас, см. Проверка возможности загрузки модов.Попросите Claude написать мод
Опишите нужный вам мод в интерактивном сеансе Claude Code, и Claude напишет его. Claude работает из встроенного skill с именемplugin-authoring, который сообщает ему, где написать мод, какие события и методы есть в вашей версии, и как загружается мод. Claude может загрузить skill, когда вы попросите мод, или вы можете загрузить его сами, выполнив /plugin-authoring в приглашении Claude Code.
Мод запускается после того, как вы его одобрите, кроме сеансов, где мод, написанный Claude, не может загрузиться.
1
Опишите мод
Попросите мод своими словами, например
make a mod that shows the current git branch above the prompt. Claude пишет мод в отдельном каталоге в папке модов сеанса, которая находится в ~/.claude/dev-mods/, за которой следует ID сеанса. Полный путь мода выглядит как ~/.claude/dev-mods/3f2a9c1e-5b7d-4e8a-9c21-6d0f4b8a7e13/git-branch/.В режимах разрешений
default и acceptEdits permission modes Claude Code спрашивает перед тем, как Claude создаст каждый из файлов мода, потому что ~/.claude — это защищённый путь. Одобрите каждый файл по мере его появления.2
Одобрите мод
Когда Claude сохраняет первый файл, Claude Code спрашивает, следует ли включить горячую перезагрузку для сеанса. Горячая перезагрузка запускает моды, написанные Claude в этом сеансе, и подхватывает каждое последующее изменение.Выберите один из этих ответов:
- Enable for this session: моды в папке модов сеанса загружаются при завершении хода и перезагружаются в конце каждого хода, который их изменяет. Ваш ответ действует для сеанса, включая после его возобновления.
- Not now: ничего не загружается пока. Файлы остаются там, где их написал Claude, и моды загружаются при следующем запуске этого сеанса. Чтобы мод никогда не загружался, удалите его каталог.
3
Проверьте, что мод загрузился
Выполните
/plugin в приглашении Claude Code и нажимайте Tab, пока не будет выбрана вкладка Installed. Она перечисляет мод, и вы можете отключить его там.4
Попробуйте мод
Используйте то, что вы просили. Для примера приглашения текущее имя ветки появляется над полем приглашения. Если мод не делает то, что вы хотели, скажите Claude, что изменить. Мод перезагружается в конце каждого хода, который изменяет его файлы, поэтому вы можете попробовать изменение сразу после завершения Claude.
Используйте мод в других сеансах
Мод, написанный Claude, загружается только в сеансе, который его создал, и Claude Code удаляет папку модов этого сеанса после того, как она старшеcleanupPeriodDays. Чтобы сохранить мод, скопируйте его каталог из папки модов в место по вашему выбору, например ~/mods/git-branch. Затем выберите, как его загружать:
- В сеансе, который вы запускаете: в вашей оболочке выполните
claude --plugin-dir ~/mods/git-branch - Для других людей: добавьте его на маркетплейс, чтобы они могли его установить
Сеансы, где мод, написанный Claude, не может загрузиться
Мод, написанный Claude, загружается только после того, как вы его одобрите, в доверенной рабочей области, где разрешено запускать моды. В этих сеансах он не загружается:- Никого нет, чтобы одобрить: сеанс не может показать вам приглашение, как в запуске
claude -pили в режимеdontAsk - Рабочая область не доверена: вы не приняли приглашение доверия для каталога
- Моды остановлены: вы запустили с
--safe-modeили--bare, вы установилиdisableAllHooks, или управляемые параметры вашей организации это блокируют
Напишите мод сами
В этом руководстве вы создаёте мод с именемfirst-mod, который подсчитывает вызовы инструментов, которые делает Claude, показывает счётчик рядом со спиннером во время работы Claude и добавляет команду /tally, которая его выводит. Затем вы читаете объявления типов, которые Claude Code пишет рядом с вашим модом, и выполняете claude plugin validate. Вместе они показывают вам события и методы, которые предлагает ваша версия, и что Claude Code читает из вашего кода.
Эта запись показывает готовый мод. Спиннер подсчитывает вызовы инструментов, /tally выводит счётчик, и редактирование кода вступает в силу во время работы сеанса:
plugin.json: манифест плагинаhooks.json: указывает на ваш файл кодаregister.js: ваш код, называемый модулем hooks
1
Создайте каталог плагина
Создайте два каталога, которые содержат файлы:
- Bash или Zsh
- PowerShell
2
Напишите манифест
Мод — это плагин, и моду нужен манифест. Манифест этого мода не имеет специальных полей. Сохраните это как
first-mod/.claude-plugin/plugin.json:first-mod/.claude-plugin/plugin.json
3
Скажите Claude Code, где находится ваш код
Когда Claude Code загружает плагин, он читает
hooks/hooks.json плагина. Ключ modules в этом файле указывает путь к вашему коду, и его наличие делает плагин модом. Перечислите один путь, относительный к hooks.json. Здесь он указывает на register.js, который вы напишете на следующем шаге.Сохраните это как first-mod/hooks/hooks.json:first-mod/hooks/hooks.json
4
Напишите код
Этот файл — это код мода, называемый модулем hooks. Когда мод загружается, Claude Code вызывает функцию Файл хранит счётчик в
register, которую экспортирует файл, и передаёт ей функцию с именем on. Каждый вызов on регистрирует обработчик события, называемый hook, для события, которое он называет.Сохраните это как first-mod/hooks/register.js:first-mod/hooks/register.js
calls и регистрирует четыре hook:session.startзапускается при запуске сеанса, перед вашим первым приглашением, и снова каждый раз, когда мод перезагружается. Он добавляет команду/tallyв Claude Code.tool.callзапускается каждый раз, когда Claude собирается использовать инструмент. Он добавляет один кcallsи просит Claude Code нарисовать интерфейс снова.command.runзапускается, когда вы вводите/tally. Он возвращает текст для вывода.ui.renderзапускается каждый раз, когда Claude Code рисует спиннер. Он добавляет счётчик после слова спиннера.
5
Загрузите мод
Запустите Claude Code с флагом
--plugin-dir, который загружает каталог плагина для одного сеанса без его установки:6
Попробуйте мод
Попросите Claude сделать что-то, что требует нескольких вызовов инструментов, например Если
list the files here and read the README. Пока Claude работает, слово спиннера сопровождается счётчиком, который растёт, как в Thinking · tool calls: 2…. Когда Claude закончит, введите /tally и нажмите Enter. Транскрипт показывает first-mod: Claude has made 2 tool calls since this mod loaded с вашим собственным счётчиком. Claude Code ставит имя плагина перед текстом команды.Чтобы проверить команду без интерактивного сеанса, выполните её в неинтерактивном режиме:/tally не в списке команд, модуль не загрузился. См. Узнайте, почему мод ничего не делает.7
Измените код во время работы сеанса
Оставьте сеанс открытым. В Строка в транскрипте говорит, что
register.js измените ' · tool calls: ' на ' · tools used: ' в hook ui.render и сохраните. Выделенная строка — это та, которая изменяется:first-mod/hooks/register.js
first-mod перезагрузился и перечисляет его hooks, и следующий спиннер использует новый текст, как в Thinking · tools used: 1….Как работает пример мода
Каждая функция, которую вы передаётеon, — это hook, который является обработчиком события. Claude Code передаёт каждому hook одни и те же три аргумента:
- API модов, названный
$: каждый метод, который мод может вызвать, чтобы выйти за пределы себя, в пространствах имён таких как$.uiи$.command - Событие, названное
e: входные данные события как простые данные, такие как имя и аргументы вызова инструмента - Следующий обработчик, названный
next: функция, которая передаёт событие другим модам, а затем собственному поведению Claude Code, и возвращает результат
first-mod обрабатывают свои события тремя способами, которыми может обрабатывать hook:
- Observe: hook
session.startрегистрирует команду, и hooktool.callподсчитывает вызов и просит перерисовку. Оба возвращаютnext(e), поэтому сеанс запускается и инструмент работает как обычно. - Answer: hook
command.runвозвращает свой собственный результат и никогда не вызываетnext. Второй аргументon,{ command: 'tally' }, — это фильтр, называемый matcher, поэтому hook запускается только для/tally. - Rewrite: hook
ui.renderвызываетnextс копиейe, чейsuffixсодержит счётчик, поэтому Claude Code рисует свой обычный спиннер с вашим текстом после слова
--plugin-dir, и горячо перезагружает модуль hooks при изменении файла в нём. Каждая перезагрузка запускает register снова, поэтому calls возвращается к 0 и /tally начинает считать снова. Чтобы сохранить значение между перезагрузками, см. Сохранение состояния.
Продолжайте работать над модом
После загрузки мода вы можете попросить Claude изменить его, проверить ваш код против определений типов для вашей версии, перечислить события и вызовы, которые Claude Code находит в нём, и протестировать его.Измените мод с помощью Claude
Чтобы изменить мод, который у вас уже есть, запустите сеанс с--plugin-dir, указывающим на каталог мода, чтобы то, что пишет Claude, загружалось в том же сеансе:
add a /tally-reset command to this mod that sets the tally back to zero. Claude редактирует модуль hooks, выполняет claude plugin validate и исправляет то, что он сообщает. Каталог, который вы загружаете с --plugin-dir, — это защищённый путь, поэтому в режимах default и acceptEdits вас просят одобрить каждое редактирование Claude мода. Таблица защищённых путей даёт результат для других режимов разрешений.
Файлы, которые Claude сохраняет во время его хода, перезагружаются при завершении хода, поэтому вы можете попробовать /tally-reset сразу после завершения Claude.
Получите определения типов для вашей версии
Каждый раз, когда Claude Code загружает или перезагружает мод из каталога, который вы передаёте--plugin-dir, или мод Claude написал для вас, он пишет файлы объявлений TypeScript, заканчивающиеся на .d.ts, в .claude-plugin/types/ внутри каталога мода. Они описывают точные события, методы API модов и элементы в версии Claude Code, которую вы запускаете, поэтому ваш редактор может автодополнять и проверять типы ваших hooks. Чтобы просмотреть объявления в Интернете, прочитайте mods/types/claude-code.d.ts в репозитории Claude Code, первая строка которого называет версию, которая его написала. Каталог содержит эти файлы:
Если ваш мод не имеет собственного
tsconfig.json, Claude Code добавляет один в корень мода, который расширяет сгенерированный, поэтому ваш редактор и tsc -p ./first-mod проверяют тип мода без дополнительной настройки.
События и методы могут изменяться между выпусками, поэтому доверяйте этим файлам больше, чем любой странице, включая эту, когда они не согласны.
claude-code/index.d.ts — это самый полный справочник для вашей сборки, с комментарием и примером для каждого метода API модов. Чтобы что-то найти, поищите в файле его имя, например 'tool.call'.
Проверьте, что Claude Code читает из вашего мода
Чтобы увидеть ваш мод так, как Claude Code его видит, без запуска вашего кода или запуска сеанса, используйтеclaude plugin validate. Он проверяет манифест и выполняет тот же статический анализ на исходном коде модуля hooks, который Claude Code выполняет при загрузке мода. В вашей оболочке выполните его на каталоге мода:
first-mod вывод включает эти строки.
hooks: перечисляет события, которые ваш модуль hook, каждое с его фильтром в скобках. Строка calls: перечисляет каждый метод API модов, который он вызывает. Модуль, который читает или устанавливает переменные окружения, также получает строки env reads: и env writes:, и тот, который использует $.state, получает state reads: и state writes:.
Если событие, которое вы хотели hook, отсутствует в первой строке, Claude Code не будет вызывать этот hook либо. Обычная причина — неправильное написание имени события, которое команда сообщает как ошибку, такую как "tool.calls" is not an event.
Следуйте этим правилам, чтобы статический анализ мог найти каждый hook и вызов:
- Напишите каждый вызов API модов полностью:
$, пространство имён, затем метод, как в$.store.get('notes'). Вы можете передать$функции, объявленной на верхнем уровне того же файла, и для функции вашей с именемloadNotesстрокаcalls:затем читает$.store.get (via loadNotes). Передача$методу, функции, определённой внутри hook, или функции, которую вы импортируете из другого из ваших файлов, не проходит валидацию. Функцииreadиupdate, которые использует$.state, — это импорты, которые могут её принять. Не присваивайте$или одно из его пространств имён переменной, не деструктурируйте его и не индексируйте его с вычисленным именем.const ui = $.uiне проходит с$.ui is used as a value. - Напишите имя события в каждом вызове
onкак строковый литерал, например'tool.call'. Переменная или цикл по списку имён не проходит сthe event name passed to on() is not a string literal. - Внутри
registerне объявляйте вторую переменную или параметр с именемon. Валидация не проходит с"on" is declared again (shadowed). - Импортируйте только из файлов внутри каталога плагина, по относительному пути. Единственный разрешённый голый импорт — это
claude-code, для типов и нескольких помощников. - Используйте объявления
importв верхней части файла, как вimport { name } from './file.js'. Динамическийimport()не проходит сa dynamic import(); a hooks module imports its own files with an import declaration. - Напишите каждый файл как модуль ES, с
import, а неrequire. Справочник перечисляет расширения файлов, которые загружает Claude Code.
Протестируйте мод
Вы можете написать автоматизированные тесты для мода и запустить их из вашей оболочки сclaude plugin test, без сеанса, входа или сети. Тест вызывает события, которые обрабатывают ваши hooks, и проверяет, что сделали hooks.
Этот тест вызывает два вызова инструментов, запускает /tally и проверяет, что ответ считает оба. Сохраните это как first-mod/tests/first-mod.test.ts:
first-mod/tests/first-mod.test.ts
first-mod:
Поделитесь своим модом
Мод — это плагин, поэтому вы версионируете его в манифесте, и люди устанавливают и обновляют его с помощью команд/plugin. Чтобы дать его другим людям, добавьте его на маркетплейс.
Перед этим проверьте name плагина: claude plugin validate не проходит имя, которое выглядит как одно из собственных Anthropic, например то, которое начинается с claude-. События и методы могут изменяться между выпусками, поэтому ваш README — это место, где нужно сказать, какую версию Claude Code вы тестировали.
Продолжайте разработку против каталога с --plugin-dir, а не против установленной копии. Claude Code кэширует установленный плагин по версии, поэтому ваши редактирования не достигают установленной копии, пока вы не повысите версию и не установите снова.
Следующие шаги
- Рисуйте в интерфейсе: откройте панель, рисуйте над приглашением и добавляйте кнопки и текстовые поля
- Реагируйте на события: hook вызовы инструментов, приглашения и ходы
- Используйте API модов: добавляйте команды и инструменты, вызывайте модель и запускайте работу по таймеру
- Протестируйте мод: заглушка того, что Claude Code ответит, и тестирование таймеров и рисунков
- Устраняйте неполадки мода: причины, по которым мод ничего не делает, и журнал отладки
- Прочитайте исходный код встроенных модов: полные плагины, каждый со своим модулем hooks и тестами