教程Claude Code系列第 10 / 11 篇

Claude Code 插件进阶(下):给插件写评测,看它占多少上下文,管好依赖、版本和市场

插件给团队用起来之后,改一句 skill 的描述都可能让它不再被触发。本站实测了 claude plugin eval:给示例插件写两个用例,带插件和不带插件各跑三遍,12 次运行 27 秒、0.28 美元,直接看出插件贡献了多少。后半篇整理怎么看插件占多少上下文、怎么声明依赖、怎么发版本和托管自己的市场。

发布 · 约 12 分钟读完 · 经人工审核()· 本站的内容怎么来的

本站已实测,测试日期:2026-10-12。

本页目录(8 节)
  1. 一、给插件写评测
  2. 二、它占多少上下文,有没有人在用
  3. 三、依赖和版本(整理自文档,没有实测)
  4. 四、发版本和托管市场(整理自文档,没有实测)
  5. 另外两页
  6. 通过中转站用,有什么不一样
  7. 这一趟花了多少
  8. 这次实测没有覆盖到的

这篇教程解决一个问题:插件做出来、团队也用上了,然后呢?改了一句 skill 的描述,它还会不会被触发?它到底有没有让结果变好?它给每个会话加了多少负担?新版本怎么发,才不会把别人弄坏?

上一篇站在用插件的人这边,这一篇站在维护插件的人这边。用的还是做一个插件分享给团队里那个示例插件 express-kit:一个写提交说明的 skill,一个评审测试的子代理,一个记改动的 hook。

评测那一节是本站实测的。后面三节(上下文占用里的用量部分、依赖、托管市场)整理自官方文档,没有实测,每节会再标一次。

实测环境
日期 2026-10-12
版本 Claude Code 2.1.296
系统 Ubuntu 24.04
模型 Sonnet 5.5
连接方式 通过酷站AI 中转站,不是直连官方

一、给插件写评测

评测是什么

claude plugin eval 是终端里的一条命令。它拿一组用例去跑你的插件,然后打分。

  • 一个用例 = 一句用户可能会说的话,加上一个或几个评分器。
  • 评分器是对结果的一项通过或不通过的检查:回答里有没有匹配某个正则、某个工具有没有被调用、另一个模型按你写的标准判它合不合格。
  • 每个用例默认跑三遍。 模型的输出不稳定,跑一遍说明不了什么。
  • 每个用例还会在不加载插件的情况下再跑三遍。 两边的得分分别叫 WITH 和 W/OUT,差值 Δ 就是插件的贡献。

最后这一条是关键。得分高不代表插件有用,Claude 不靠它可能也做得一样好。有了对照才知道。

每次运行都是一个全新的、隔离的非交互会话,只加载被测的插件,工作目录是空的。

写用例:两种办法

让 Claude 写。 在插件根目录运行 claude plugin eval init,它会打开一个会话,读你的插件,问你什么算好结果,提出该触发和不该触发的提示,设计评分器,试跑一遍,然后把文件写好。文档推荐这种。本站没有试。

自己写。 本站走的是这条,为了看清楚文件里到底有什么。先要一个空白模板:

claude plugin eval init --bare commit-format
Created evals/commit-format/prompt.md and evals/commit-format/graders/criteria.md

模板里是两个待填的文件。prompt.md 上半是运行的限制,下半是发给 Claude 的话:

---
max_turns: 10
allowed_tools: [Read, Glob, Grep, Skill]
---

TODO: describe what the agent should do

本站写的两个用例

用例一:该触发的。 示例插件的 skill 要求提交说明是英文的一行、以 fix:、docs:、test:、refactor: 之一开头、不带解释。

evals/commit-format/prompt.md:

---
max_turns: 6
allowed_tools: [Skill]
---
帮我写一条提交说明:我把 getUser 改名成了 fetchUser,三处调用的地方也一起改了。

提示要像用户会说的话,不要点 skill 的名字。点了名就测不出“它会不会自己被选中”。

三个评分器,每个一个文件,放在 graders/ 下。

prefix.md,检查开头的类型:

---
type: regex
pattern: '^(fix|docs|test|refactor): [A-Za-z]'
---

one-line.md,检查只有一行(不能出现第二个非空行):

---
type: regex
pattern: '\n\s*\S'
match: not_contains
---

skill-fired.md,检查答案确实是这个 skill 产生的:

---
type: tool_used
tool: Skill
input_match: '"skill"\s*:\s*"(?:[\w-]+:)?commit-message"'
---

用例二:不该触发的。 一个和提交说明毫无关系的问题,确认插件不会乱插手。

evals/ignores-unrelated/prompt.md 的正文是“用一句话解释 HTTP 状态码 404 是什么意思。”,两个评分器:一个正则检查回答里说到了“找不到”,一个 tool_used 把 min 和 max 都设成 0,要求 skill 一次都没被调用。

跑起来

claude plugin eval . --trust-plugin --no-publish --model sonnet -j 3
  • . 是插件目录。
  • --trust-plugin:第一次对一个目录运行时它会问你是否信任,这个参数替你回答,给脚本和 CI 用的。
  • --no-publish:报告只留在本地。默认情况下,账号支持的话它会把报告发布到 claude.ai。
  • --model sonnet:被测的会话用哪个模型。
  • -j 3:同时跑三个。

每跑完一次打一行,带着每个评分器的结论。不带插件的那几次是这样的:

    ✗ one-line (weight 1): pattern found (expected absent)
    ✗ prefix (weight 1): pattern not found in last_message

最后是汇总表:

CASE               WITH  W/OUT Δ      RUNS COST    NOTES
commit-format      1.00  0.00  +1.00  6    $0.15
ignores-unrelated  1.00  1.00  0.00   6    $0.13
2 case(s) · mean Δ +0.50 · 27s · $0.28
Report: …/express-kit/evals/results/2026-10-12T15-33-15-933Z/report.html

怎么读这张表

commit-format:带插件 1.00,不带 0.00,Δ +1.00。 三遍带插件的运行全部符合格式;三遍不带的全部不符合,Claude 写了好几行,也没有类型前缀。这个 skill 的作用是实打实的。

ignores-unrelated:两边都是 1.00,Δ 是 0。 这正是想要的结果。这个用例测的不是“插件有帮助”,而是“插件没添乱”:带着插件,Claude 照样正常回答了无关的问题。

再看每次运行的明细,有一行值得解释:

    ✓ skill-not-fired [with-only, not scored]: Skill called 0x (expected 0..0)

“skill 有没有被调用”这类检查不计入得分。 文档的解释:这种检查在不带插件时永远不可能通过,算进去会把对照那一边的分数压低,Δ 就虚高了。所以它在两边都不计分,只在带插件那边当一个指示灯。

指示灯的用处在排查。文档说最常见的第一个发现是:Δ 接近 0,同时 tool_used: Skill 那个评分器不通过。意思是 Claude 在自然的说法下根本没选你的 skill。这时该改的是 skill 的 description。

六种评分器

类型 通过的条件 要不要花钱
regex 正则在目标里找到了(或者用 match: not_contains 要求找不到) 不要
tool_used 某个工具被调用的次数在 min 和 max 之间 不要
tool_order 两个工具都被调用了,并且先后顺序对 不要
file_exists Claude 创建了匹配某个路径的文件 不要
llm 一个评审模型按你写的标准投票,三票里至少两票通过 要,每次三个短的评审调用
baseline 评审认为这次的结果不比一份参考记录差 要

没有“自己写代码来评分”这一种。

正则默认看的是 Claude 最后一条回答。也可以看整个会话的记录、Claude 创建了哪些文件、某一个文件的内容。

文档给的几条经验:

  • 长的输出用正则评。 评审模型读的东西越长,前后两次的结论越容易不一样。llm 评分器留给短的输出,标准写成明确的“什么情况通过、什么情况不通过”。
  • 每个用例配两个评分器:一个看结果,一个看过程。 合起来才知道答案对不对、是不是你的插件做出来的。
  • skill 被调用了但 Δ 是负的,先怀疑评审。 默认的评审模型是 Haiku,它可能因为格式和你描述的不一样就判错。换成 --judge-model sonnet 再跑,并把标准写得不依赖格式。

常用的几个参数

参数 用途
--case <名字> 只跑名字匹配的用例
--runs 1 --ablation none 只跑一遍、不跑对照。调评分器的时候用,省钱。一遍的结果有噪声,定稿前要用默认的三遍确认
--threshold 0.8 有用例得分低于这个值,命令的退出码是 1。默认是 1.0。放进 CI 就靠它
--max-cost-usd 2 花费到了就中止,给出部分结果
--json 文件 把每次运行的完整结果写成 JSON

每次运行的结果写在 evals/results/<时间>/ 下,里面有 report.html 和 aggregate-result.json。把 evals/results/ 加进 .gitignore。

两点提醒

  • 评测会真的运行插件里的代码,用的是你的身份。 命令的帮助里写着:只评测你信任的插件;它的隔离限制了恶意插件能够到的范围,但不是保证。
  • 每次运行都是真的模型调用。 文档的算法:一个评测集大约是“用例数 × 运行次数”次带插件的运行,对照再来同样多次,每个 llm 评分器每次运行再加三个评审调用。

二、它占多少上下文,有没有人在用

占多少(实测)

上一篇用过的命令,对还没安装的插件也能用:

$ claude --plugin-dir ./express-kit plugin details express-kit
Projected token cost
  Always-on:   ~134 tok   added to every session

Per-component (rounded)
  component       always-on  on-invoke
  commit-message        ~70       ~270
  test-reviewer         ~60       ~160
  • Always-on 是每个启用了这个插件的会话都要背的:各个 skill、子代理、命令的名字和描述。不管用没用到都在。这是最该压的数字。
  • on-invoke 是某个组件真的被用到时才加载的正文。
  • hook 不占上下文。MCP 服务器的工具说明不在这个估算里,要在会话里用 /context 看。

压低 Always-on 的办法只有两个:把描述写短,或者把大插件拆开让人按需安装。

这里有一个和评测直接相关的风险,文档特意提了:skill 的描述同时也是 Claude 判断“该不该用它”的依据,写得太短它可能就不触发了。 所以改完描述,跑一遍上面那个 skill-fired 评分器。这两节是配着用的。

有没有人在用(整理自文档,没有实测)

Claude Code 不会把插件的使用情况回报给作者。用量只记在每个安装者自己的机器上。你能做的是请同事在自己的会话里看:

  • /plugin 的 Installed 页签:一个插件连续 14 天、10 个会话没被用到,会被归到“Not used recently”下面,详情里有 Last used 一行。
  • /skill-doctor:看每个 skill 占多少上下文、用得多不多。
  • /doctor 和 /usage 里也各有一处。

/skill-doctor 本站在讲 advisor 的那篇里试过:用令牌接中转站时它是“未知命令”,和 advisor 用不了是同一个原因。

三、依赖和版本(整理自文档,没有实测)

声明依赖

写在插件的 .claude-plugin/plugin.json 里:

{
  "name": "deploy-kit",
  "version": "3.1.0",
  "dependencies": [
    "audit-logger",
    { "name": "secrets-vault", "version": "~2.1.0" }
  ]
}

两种写法:

  • 只写名字:依赖跟着它所在的市场走,市场发了新版本,用户下次更新就换上。那个版本要是改了你用到的东西,你的插件就对所有更新了的人坏掉。
  • 带版本范围:~2.1.0、^2.0、>=1.4 这样的语义化版本范围。用户会一直收到范围内的补丁,不会越界。它是按依赖的 git 标签来解析的,所以依赖的维护者要给发布打标签。

用依赖做“全家桶”

一个插件的清单只要有 name 就合法。所以可以发一个只有名字和依赖列表的插件,装它就等于装了一组:

{
  "name": "backend-standard",
  "version": "1.0.0",
  "description": "后端工程师的标准插件组合",
  "dependencies": ["secrets-vault", "deploy-kit", { "name": "db-migrate", "version": "^3.0" }]
}

新同事一条命令装齐。

跨市场的依赖默认不装

依赖在另一个市场里时,Claude Code 默认不会替用户装它,除非用户已经装了。这是为了防止一个市场悄悄从用户没看过的来源装东西。要放行,在你自己市场的 marketplace.json 里用 allowCrossMarketplaceDependenciesOn 列出允许的市场名。

四、发版本和托管市场(整理自文档,没有实测)

市场放在哪

放在哪 用户怎么添加 用户要有什么
GitHub /plugin marketplace add your-org/your-marketplace git;私有仓库要有访问权限
别的 git 托管(GitLab 等) 给完整的地址,/plugin marketplace add https://…/plugins.git git,能访问那台主机
一个放着 marketplace.json 的网址 /plugin marketplace add https://…/marketplace.json 能访问那个地址
共享盘上的目录 /plugin marketplace add /Volumes/shared/claude-plugins 能读那个路径

想让一个仓库里的所有人都自动有这个市场:在仓库里运行一次 claude plugin marketplace add your-org/your-marketplace --scope project,把它写出来的 .claude/settings.json 提交。

私有市场靠的是机器上已有的凭据

Claude Code 自己没有 git 令牌,marketplace.json 里也没有放令牌的地方。它在用户机器上运行 git,关掉了交互提示,能不能拉下来全看那台机器上已经有的凭据。

  • 走 SSH:密钥要能不输密码就用(比如已经加进 ssh-agent),主机要已经在 known_hosts 里。
  • 走 HTTPS:凭据助手里已经存着的能用,需要现场问的不行。

同事说“添加市场失败”,多半是这里。让他先在终端里手动 git clone 一次那个仓库。

用户什么时候拿到新版本

两条规则,都容易踩:

一、你的市场默认不自动更新。 marketplace.json 里没有开关,要每个用户自己在 /plugin 的 Marketplaces 里打开,或者由管理员统一设置。没开的话,用户要手动 /plugin marketplace update <名字> 才会看到新东西。

二、只有版本号变了,用户才会拿到新的一份。

你的做法 结果
每次发布都改 version 用户在版本号变化时更新
写了 "version": "1.0.0",之后只推提交、不改这个字符串 用户收不到你的改动,一直用缓存的那份
不写 version 用户跟着你的提交走
plugin.json 和市场条目里都写了 version 以 plugin.json 为准,没有警告。claude plugin validate 会报两边不一致

第二行是最常见的“我明明推了,他们怎么没变”。

稳定版和尝鲜版

Claude Code 没有发布通道的概念,一个市场里一个插件同一时间只有一个版本。要分两条线,就开两个名字不同的市场,条目分别指向同一个插件仓库的不同分支,让用户自己选加哪个。

另外两页

这两页本站没有展开,放个指引:

  • 让你的命令行工具推荐你的插件。 如果你维护一个 CLI,它可以在检测到自己运行在 Claude Code 里的时候,往标准错误输出写一行 <claude-code-hint /> 标签,Claude Code 会给用户弹一次安装提示。只对列在官方市场里的插件有效。
  • 给 mod 写测试、mod 不工作怎么查。 mod 有自己的两页文档。写第一个 mod那篇讲了怎么做,测试和排错这两页还没有写到。

通过中转站用,有什么不一样

评测通过中转站正常跑完了。它用的就是你平时的认证和模型,没有额外的要求。

有两处和接入方式有关:

  • 报告发布不了。 默认它会把报告发布到 claude.ai,这要 claude.ai 的账号。本站带了 --no-publish,报告留在本地。
  • /skill-doctor 用不了,见上文。

这一趟花了多少

评测跑了两遍,每遍 12 次运行、约半分钟,分别是 0.31 和 0.28 美元,合计约 0.59 美元。每次运行 0.01 到 0.03 美元,用的是 Sonnet 5.5,没有用到要花钱的评审类评分器。这是 Claude Code 按官方价格估算的数字,不是中转站实际扣的金额。

这次实测没有覆盖到的

  • claude plugin eval init 的访谈式流程没有试。
  • llm 和 baseline 两种要评审模型的评分器没有试,“评审不稳定”是文档的说法。
  • 没有接进 CI。 --threshold 的退出码、--max-cost-usd 的中止都没有验证。
  • 用例里没有用到文件、脚本和 MCP 的模拟。 示例插件的 skill 只输出一行文字,用不上。
  • 子代理和 hook 没有写用例,只测了 skill。
  • 依赖、托管市场、版本更新三节全部是文档的内容,没有搭一个真的市场来验证。
  • 只跑了两遍。 这两个用例很简单,两遍的分数完全一样;复杂的用例波动有多大,没有数据。

来源

通过 API 中转站使用这些模型?到 Veridrop 免费检测中转站给你的是不是它声称的模型,或者看看中转站排行榜前 100 名。

相关文章