#Тестирование и публикация плагина
Продвинутый уровень · Факультатив · около 20 минут плюс время запуска · Нужно: Поделитесь настройкой с командой · Сверено с Claude Code v2.1.285 (stable) 09.10.2026
#Цель
К концу этого факультатива вы сможете проверить файлы плагина через claude plugin validate, измерить, что он меняет, через claude plugin eval и опубликовать его в маркетплейсе, из которого другие люди будут его устанавливать и обновлять.
#Что понадобится
- Структура маркетплейса из урока 6: маркетплейс, который перечисляет плагин по относительному пути.
- Место для практики: новая папка вне других ваших репозиториев, которая станет отдельным приватным репозиторием на GitHub. У факультативов нет проверки в шаблоне.
- bash,
jqи git 2.31 или новее в macOS, Linux или WSL 2. Со старым gitclaude plugin evalостанавливается, не запустив ни одного кейса (Requirements). - GitHub CLI с входом через
gh auth login. Claude Code клонирует приватный маркетплейс с учётными данными git, которые уже есть на вашей машине, — SSH или HTTPS — и никогда их не запрашивает; для HTTPS после входа выполнитеgh auth setup-git, чтобы сохранить учётные данные, которыми он сможет воспользоваться (Grant access to a private marketplace). - Расход лимита: умеренный. Каждый запуск eval — реальный вызов модели на вашем аккаунте (Test plugins with evals). Разбор примера делает один запуск. Полный запуск в задании «Ваша очередь» прогоняет каждый кейс трижды с плагином и трижды без него; его экономный вариант прогоняет каждый кейс один раз.
#Идея
Проверьте плагин двумя способами, прежде чем делиться им. claude plugin validate читает файлы: манифесты и фронтматтер; с --strict запуск проваливается и на предупреждении (Test and debug). claude plugin eval измеряет поведение: каждый кейс — промпт плюс грейдеры (проверки, оценивающие каждый прогон) — выполняется в свежей изолированной сессии только с вашим плагином, по умолчанию трижды (ветка «с плагином»), и столько же раз без плагина (ветка «без плагина»). Разница их оценок, WITH и W/OUT, — это Δ: вклад плагина (How an eval run works).
Грейдеры regex, tool_used, tool_order и file_exists ничего не стоят; llm и baseline вызывают модель-судью. Давайте каждому кейсу один грейдер на результат и один на шаги, например «скилл запустился» (Choose and weight graders).
Публикация — это .claude-plugin/marketplace.json в git-репозитории: как только он запушен, плагин опубликован, никакой формы подачи нет (Publish and distribute a plugin). Если у плагина задан version, пользователь получит ваш следующий релиз только после того, как вы его измените (Release a new version).
Внимание
Прежде чем делать репозиторий маркетплейса публичным, прочитайте в нём каждый файл: публичный репозиторий может прочитать кто угодно (About repositories), а любой, кто может его клонировать, может из него устанавливать (Control who can install). Хук или stdio MCP-сервер, добавленный в следующей версии, выполняется на машине каждого, кто на неё обновится, с его правами (Plugin security and trust).
#Разбор примера
- Создайте репозиторий с одним плагином
commit-helperвplugins/— такую структуру использует Create a marketplace. Его единственный скилл пишет черновики сообщений коммитов. Во всех файлах и командах замените<you>своим именем пользователя GitHub, аYour Name— своим именем:
mkdir -p claude-plugins/.claude-plugin claude-plugins/plugins/commit-helper/{.claude-plugin,skills/commit-message}
cd claude-plugins && git init
mkdir -p .practice && echo '.practice/' >> "$(git rev-parse --git-path info/exclude)"
echo '**/evals/results/' > .gitignore
echo '# commit-helper: drafts commit messages in a short, consistent format.' > plugins/commit-helper/README.md
.practice/ хранит файл, который читает проверка, и игнорируется без коммита, как в уроке 1 Начального уровня. Строка в .gitignore не пускает в git результаты, которые каждый запуск eval пишет в evals/results/ (Write and refine cases), а README требует чек-лист релиза (Prepare your plugin for release). Затем сохраните манифест плагина с полями, которых требует этот чек-лист, как plugins/commit-helper/.claude-plugin/plugin.json:
{
"name": "commit-helper", "version": "1.0.0", "author": { "name": "Your Name" },
"description": "Drafts commit messages in a short, consistent format.",
"homepage": "https://github.com/<you>/claude-plugins", "repository": "https://github.com/<you>/claude-plugins"
}
Скилл — как plugins/commit-helper/skills/commit-message/SKILL.md:
---
name: commit-message
description: Drafts a commit message for a described change. Use when the user asks for a commit message.
---
Write a commit message for the change the user describes: a subject line in the imperative mood, at most 50 characters, with no trailing period; a blank line; then one sentence on why.
И маркетплейс — как .claude-plugin/marketplace.json. Имя записи name должно совпадать с именем в манифесте (Keep the entry name and the manifest name the same):
{
"name": "<you>-plugins", "description": "Plugins from <you>", "owner": { "name": "Your Name" },
"plugins": [{ "name": "commit-helper", "source": "./plugins/commit-helper", "description": "Drafts commit messages." }]
}
- Провалидируйте плагин, затем маркетплейс:
claude plugin validate --strict ./plugins/commit-helper, затемclaude plugin validate --strict .. Каждый запуск заканчивается строкой✔ Validation passed. Валидация маркетплейса проверяет его файл иplugin.jsonкаждого плагина, перечисленного по относительному пути (Problems that validation reports), но не открывает их файлы скиллов, поэтому валидируйте и саму папку плагина (Validate a directory). - Напишите один кейс eval.
claude plugin eval init --bareсоздаёт пустой кейс:prompt.mdи один грейдер-заглушкуgraders/criteria.md, который ждёт критерии для модели-судьи. Он ничего не запускает (Write a case manually). Замените критерии двумя бесплатными грейдерами:
cd plugins/commit-helper
claude plugin eval init --bare names-the-rename
cd evals/names-the-rename && rm graders/criteria.md
printf '%s\n' '---' 'max_turns: 10' 'allowed_tools: [Skill]' '---' '' 'Write me a commit message for this change: I renamed getUser to fetchUser and updated the three call sites.' > prompt.md
printf '%s\n' '---' 'type: tool_used' 'tool: Skill' "input_match: 'commit-message'" '---' > graders/skill-fired.md
printf '%s\n' '---' 'type: regex' "pattern: 'fetchUser'" '---' > graders/mentions-rename.md
cd ../..
Прогон получает только инструменты для чтения, перечисленные в его кейсе, поэтому именно allowed_tools: [Skill] позволяет Claude запустить ваш скилл (prompt.md frontmatter). skill-fired проходит, если Claude вызвал инструмент Skill с commit-message во входных данных, то есть запустил скилл; mentions-rename проверяет ответ (Grader types). Пусть regex ищет факт, который даёт промпт, например fetchUser: ответ пишет Claude, так что формулировки меняются. Теперь в evals/names-the-rename/graders/ лежат mentions-rename.md и skill-fired.md.
4. Прогоните кейс один раз, только с плагином, и оставьте отчёт у себя на машине: claude plugin eval . --runs 1 --ablation none --no-publish (Command options). Если он спросит Trust this plugin directory?, ответьте y; внутри git-репозитория это означает доверие ко всему репозиторию, в том числе для интерактивных сессий (Trust the plugin directory). В итоговой таблице есть столбцы SCORE и PASS%, а строка Report: даёт путь к report.html в evals/results/ (Create your first eval suite). Оценки у вас будут другими.
5. Опубликуйте. Вернувшись в корень репозитория (cd ../..), выполните git add -A && git status --short, прочитайте каждый перечисленный файл, затем:
git commit -m "Publish commit-helper 1.0.0"
gh repo create claude-plugins --private --source . --push
--source . создаёт репозиторий GitHub из этого, а --push пушит ваш коммит (gh repo create). Теперь маркетплейс опубликован для всех, кто может клонировать репозиторий, — пока что для вас. Сделав репозиторий публичным, вы позволите устанавливать его всем.
6. Установите его так, как это сделал бы пользователь, с GitHub:
claude plugin marketplace add <you>/claude-plugins
claude plugin install commit-helper@<you>-plugins
claude plugin details commit-helper
Добавление выводит ✔ Successfully added marketplace: <you>-plugins (declared in user settings), установка — ✔ Successfully installed plugin: commit-helper@<you>-plugins (scope: user), а в Component inventory подробностей значится Skills (1) commit-message (Create a marketplace). Имя маркетплейса берётся из вашего marketplace.json, а не из репозитория (Host your marketplace). Плагин остаётся у вас установленным до конца задания «Ваша очередь».
#Ваша очередь
Задание: выпустите commit-helper 1.0.1, пропустив релиз через его eval, и обновите свою установленную копию.
Критерии приёмки:
- Второй кейс,
ignores-unrelated, имеет тот же фронтматтер, что иnames-the-rename, так что скилл мог бы запуститься, и отправляет запрос, который скилл должен оставить без внимания, напримерExplain what a git rebase does.Грейдерtool_usedнаSkillсmin: 0,max: 0иarm: bothпроверяет, что Claude не запустил скилл.arm: bothнужен потому, что двухветочный запуск иначе исключает из оценки все грейдерыtool_usedнаSkill(Score against the no-plugin baseline). Грейдерregexпроверяет ответ, напримерpattern: 'rebase'сflags: i. - Скилл вносит одно изменение, которое видит грейдер, — например начинает каждую тему с типа вроде
refactor:, — и это проверяет новый грейдерregexвnames-the-rename.versionвplugin.jsonравен1.0.1, а запись маркетплейса не задаёт собственныйversion(Release a new version). - Обе строгие валидации проходят, а один полный запуск
claude plugin eval . --threshold <score> --no-publishиз папки плагина заканчивается тем, что каждый кейс не ниже выбранного вами порога — числа от 0 до 1, например0.8(Command options). Экономный вариант: добавьте--runs 1 --ablation none. evals/закоммичена,evals/results/— нет, и релиз запушен.claude plugin update commit-helper@<you>-pluginsустанавливает 1.0.1 и заканчивается строкойRestart to apply changes.(Plugin loading reference). Если команда говорит, что плагин уже последней версии, новыйversionещё не запушен.
Затем из корня репозитория сохраните список плагинов командой claude plugin list --json > .practice/a-publish-list.json (JSON output) и только после этого выполните claude plugin marketplace remove <you>-plugins --scope user. Удаление маркетплейса из последней области заодно удаляет его плагины (plugin marketplace remove), так что проверка ниже читает именно сохранённый список. Удалять репозиторий не обязательно: gh repo delete <you>/claude-plugins --yes требует права delete_repo, которое добавляет gh auth refresh -s delete_repo (gh repo delete).
#Проверка
Факультатив пройден, когда из корня репозитория выполнено всё это:
-
claude plugin validate --strict ./plugins/commit-helperиclaude plugin validate --strict .заканчиваются строкой✔ Validation passed. -
git ls-files plugins/commit-helper/evalsперечисляет файлы двух кейсов и ничего вresults/. - Новейший результат eval охватывает оба кейса, и каждый кейс пройден (JSON result):
jq '.partial != true and .aggregates.casesTotal == 2 and .aggregates.casesPassed == .aggregates.casesTotal' "$(ls -d plugins/commit-helper/evals/results/*/ | tail -1)aggregate-result.json"выводитtrue. -
jq -r '.[] | select(.id == "commit-helper@<you>-plugins") | .version' .practice/a-publish-list.jsonвыводит1.0.1. - Самопроверка (не тестируется): вы можете сказать, что измеряет
Δи почему двухветочный запуск не оценивает «скилл запустился».
Если валидация не проходит только с --strict, строки над вердиктом называют предупреждение, которое нужно исправить, например отсутствующие description или version (Output and exit codes). Если в списке есть results/, выполните git rm -r --cached plugins/commit-helper/evals/results, проверьте строку в .gitignore и закоммитьте. Если результат выводит false, снова прогоните оба кейса, если в новейшем запуске был только один, или откройте его report.html, чтобы увидеть, какой грейдер не прошёл: без --threshold любой кейс с оценкой ниже идеальной считается непройденным (The run exits 1 but the results look fine). Если проверка версии ничего не выводит или выводит 1.0.0, убедитесь, что <you> заменён, при необходимости запушьте новый version, добавьте маркетплейс, снова установите плагин и сохраните список до удаления маркетплейса.
#Осторожно
claude plugin evalвыполняет скиллы, хуки и агентов плагина на вашей машине от вашего имени, а пройденный набор тестов ничего не говорит о безопасности плагина. Передавайте--allow-tools,--scaffoldили--allow-real-serversтолько для плагина и набора тестов, которые вы прочитали (What a run can access).- Грейдеры-судьи добавляют вызовы модели к каждому прогону, поэтому оставляйте их для того, что не может проверить бесплатный грейдер.
--max-cost-usdограничивает оценку запуска по прейскуранту, а не расход вашего плана, и если посреди набора вы упрётесь в лимит использования, последующие прогоны обычно получают 0, а набор не помечается какpartial(Command options, Troubleshooting). - Считайте
nameплагина постоянным: пользователи устанавливают, включают и настраивают его поname@marketplace, так что переименованный плагин для каждой существующей установки — другой плагин. Для новой подписи меняйтеdisplayName(Prepare your plugin for release). Некоторые имена маркетплейсов зарезервированы, например любые, начинающиеся сclaudeai-; если добавление отклоняет ваше, выберите другое (Reserved names).
#Что дальше
- Run evals in CI:
--trust-plugin, закреплённые модели,--jsonи потолок стоимости — для задания вроде того, что в уроке GitHub Actions. - Submit to Anthropic's directory: разместите плагин в каталоге, который просматривают на claude.ai.
- Host and maintain a marketplace: автообновление, каналы релизов, переименование и удаление плагина.
Источники: Test plugins with evals · Publish and distribute a plugin · Create a Claude Code plugin · Create a marketplace · Host and maintain a marketplace · Plugin commands reference · Plugin loading reference · Marketplace reference · Plugin security and trust · GitHub: About repositories · Руководство GitHub CLI: gh repo create, gh repo delete
Назад к оглавлению Продвинутого уровня · Тема: Плагины · Застряли на уроке?