Claude Code 插件评测实测:过期答案拿了 1.00 满分
Δ 是对照你自己写的评分器得出的分差。最顺手的评分器往往只检查回答里有没有出现技能中写的那个值,分不出技能有用还是已经过期。我们的评分器给一个四个月前的答案打了 1.00 满分,裸模型拒绝猜测却得了 0.00。汇总表既不提示内容过期,也不告诉你为加载技能多花了多少钱。
30 秒看懂结论
9 月 11 日,Anthropic 为 Claude Code 加入了 claude plugin eval。skill-creator 插件早就有自己的评测格式;这次新增的是官方直接提供的命令,并且内置了无插件基线组。它的做法是把同一个用例放进两组:带插件组加载待测插件,无插件组什么也不加载,默认每组各运行三次。最醒目的指标是 Δ,也就是两组得分之差。
我们用 Stripe 官方公开发布、仍在持续维护的 stripe-best-practices 做了实测,测试对象是 2026-05-16 安装后一直未更新的本地副本。这也是许多已安装技能的实际状态;我们没有测 Stripe 当前发布的最新版。三个用例在 Claude Opus 5 上共运行 18 次,耗时 237 秒,花费 $1.79。
结果看起来很好:每个用例都是 1.00 满分,平均 Δ 为 +0.33。逐条翻看运行记录后,结论却变了:
- 全部分差都来自同一个用例。它拿到 1.00 的答案,已经过期四个月;上游在 7 月和 8 月各更新过一次那个版本号。
- 另外两个用例中,技能的建议仍然适用,Δ 却都是 0.00。两组都通过了评分检查,技能并不是通过的原因。
- 这两个用例加载技能后,平均每次运行分别贵了 56% 和 84%,原本一个轮次就能完成,也变成了四到五个轮次。
Δ 是对照你自己写的评分器得出的分差。最顺手的写法,是检查回答里有没有出现技能中写的那个值;这样的评分器分不出技能有用还是已经悄悄过期。它甚至可能更偏向过期的技能,因为基线组恰好没有给出那个过期值。
命令是怎么跑的
一个用例对应一个目录。prompt.md 放 Claude 要接收的提示词,graders/ 目录中的每个文件则定义一项通过或失败的检查,也就是一个评分器。
评分器一共有六种。regex、tool_used、tool_order、file_exists 这四种直接检查会话记录,不产生额外费用;llm 和 baseline 会调用裁判模型,因此另行计费。
每次运行都会在空目录中启动一个全新的无界面会话,只加载待测插件。环境中没有 CLAUDE.md,没有用户设置或其他技能。每次运行默认带一组只读工具;额外工具和插件的 MCP 服务器要为该次运行显式启用。我们的用例只额外启用了 Skill,两组都没有能联网的工具。后面的结果必须放在这个隔离条件下理解。
默认每个用例在带插件组和无插件组各运行三次,合计六次。每次运行的得分,是通过的评分器占全部计分评分器的比例;用例得分再取各次运行的平均值。
有一条计分规则很容易漏看:无插件组根本不可能通过「调用了技能」这项检查。如果把它算进分数,就会凭空压低基线、抬高 Δ。因此,Claude Code 在两组中都不把 tool_used: Skill 计入得分,只在带插件组把它作为通过或失败的指示项。这也解释了为什么技能每次都触发,Δ 仍然可能是 0.00。
测试设计:一个真实技能,三个问题
测试使用的是本机已安装的 stripe-best-practices:2026-05-16 安装后没有改写,也没有更新,已落后上游四个月。它由 Stripe 官方发布并持续维护,适合做这次实验:这不是演示用的玩具技能,而且同时包含两类内容,一类是通用的集成建议,另一类是当前 API 版本号这样的具体事实。以下结果都来自这份旧副本在 Claude Opus 5 上的运行,测的不是 Stripe 当前发布的版本;我们没有测最新版。
我们按用户平时提问的方式写了三个用例,提示词都没有点名技能:
| 用例 | 提示词概要 | 评分器(免费、结果确定) | 预期 |
|---|---|---|---|
api-version-pin | 应该固定使用哪个确切的 Stripe API 版本号? | 回答包含技能中写明的版本号 | 技能应当占优:模型不太会断言这个带日期的版本号 |
routing-one-time-payments | 用 Node 收取一次性银行卡付款,该选哪个 Stripe API? | 回答包含「Checkout Session」 | 难说谁会占优:属于常识 |
which-key-type | 后端应该使用哪类 API 密钥? | 回答包含受限密钥(原文:“restricted key”)或 rk_ | 两边都有可能,稍看好技能 |
所有计分评分器都用 regex 检查最终回答,结果不受裁判模型判断波动的影响。每个用例还配了一个 tool_used: Skill,用来指示插件中的技能是否触发。每个用例的 allowed_tools: [Skill] 都是在默认的只读工具基础上加上 Skill,所以 Read 和 Grep 仍然可用,但两组都没有任何能联网的工具。因此,我们测的是这两种配置各自知道什么,而不是它们能查到什么。
api-version-pin 这个用例一共就三个文件,想自己跑一遍可以直接照抄:
evals/api-version-pin/
├── prompt.md
└── graders/
├── names-current-version.md
└── skill-fired.md
<!-- prompt.md -->
---
max_turns: 6
timeout_seconds: 180
allowed_tools: [Skill]
---
I'm starting a fresh Stripe integration today and I want to pin the API
version explicitly. Which exact version string should I pin to?
<!-- graders/names-current-version.md -->
---
type: regex
pattern: "2026-04-22\\.dahlia"
---
然后在上一级目录执行 claude plugin eval <your-plugin>。
实测结果
| 用例 | WITH | W/OUT | Δ | 运行次数 | 费用 |
|---|---|---|---|---|---|
api-version-pin | 1.00 | 0.00 | +1.00 | 6 | $0.63 |
routing-one-time-payments | 1.00 | 1.00 | 0.00 | 6 | $0.59 |
which-key-type | 1.00 | 1.00 | 0.00 | 6 | $0.57 |
三个用例全部通过,总分 1.00,平均 Δ 为 +0.33。共运行 18 次,耗时 237 秒,费用 $1.79。带插件组的九次运行全部触发了技能。
只看工具展示的这些数字,用例集没有问题,技能也确实起了作用。但要判断这是不是好事,还得看它到底回答了什么。
拿到 1.00 满分的答案,已经过期四个月
api-version-pin 拿到满分 +1.00,原因只有一个:带插件组给出了技能里写着的版本号,裸模型一次也没有给出这个字符串。运行记录中的原文写道(以下译为中文):
请固定使用:
2026-04-22.dahlia这是最新的 Stripe API 版本。
这个版本并不是最新的。本机安装的副本停留在 5 月 16 日,此后上游至少已经改过两次:
| 来源 | 其中写明的版本号 |
|---|---|
| 本机安装的副本(5 月 16 日) | 2026-04-22.dahlia |
| 上游,8 月 5 日 | 2026-07-29.dahlia |
| 上游,8 月 28 日至今 | 2026-08-26.dahlia |
这不能归咎于 Stripe 疏于维护。自本机安装那份副本以来,这个文件在上游已有十九次提交,仅 8 月 5 日到 9 月 11 日就有八次提交。上游一直在更新,只是本机安装的副本停住了。任何安装后不再同步的副本都会这样,而评测完全没有发现。
再看另一组的回答,问题就更清楚了。
裸模型答得更好,却得了零分
无插件组在这个用例上得了 0.00。它没有答错,而是意识到自己无法可靠作答,拒绝猜测。原文写道(以下译为中文):
我无法在这里给出一个可信的确切版本号。这类问题猜错还不如不猜。[…] 我的知识截止于 2026 年 5 月,而今天是 2026-09-13。Stripe 会定期发布带日期的新 API 版本,大约每隔几个月一次。所以我记得的任何版本号,往好了说已经过期,往坏了说可能是编造的。
随后,它告诉用户去哪里查权威答案:在控制台进入「开发者」,再查看「API 版本」。基线组的另一次运行还指出,沙箱不能联网,也没有 Stripe 代码可读,无从据此推断版本号。
于是,同一道题出现了这样的评分结果:
- 模型知道自己的信息可能过期,谨慎拒答,并引导用户去权威来源核实:0.00。
- 模型把四个月前的版本号当成最新版本,给出肯定回答:1.00。
最终 Δ 为 +1.00。这不是指标算错了:它按我们写的评分器比较两组得分。评分器检查的是回答里有没有出现技能中的版本号,插件正好让这项检查从失败变成了通过。
同一份回答,两个评分器,结论相反
为了看清这 +1.00 有多少是评分器带来的,我们重跑了这个用例。原来的评分器保留,再加一个评分器,检查回答是否包含真正的当前版本号 2026-08-26.dahlia。两个评分器都会用于每次运行,因此同一份会话记录会得到两项判定。
| 评分器 | 带插件组 | 无插件组 |
|---|---|---|
| 回答包含技能里写明的版本号 | 通过,2 次中有 2 次 | 失败,2 次中有 0 次 |
| 回答包含真正的当前版本号 | 失败,2 次中有 0 次 | 失败,2 次中有 0 次 |
用例得分:WITH 0.50,W/OUT 0.00,Δ +0.50。四次运行共花费 $0.42。
同一份会话记录,交给两个评分器,却得出相反结论。评分器拿技能文件里的值当标准,测到的是回答有没有照着技能写;拿自己核实过的值当标准,测到的才是答案对不对。评测框架允许你测其中任何一个,结果都放在同一列,用同样的格式展示,读者看不出你选了哪种标准。
只看检查正确性的那一行,两组都是 0.00,Δ 也应当是 0.00。技能没有提高答案的准确性。最初用例集中那个 +1.00,全部来自检查回答有没有照着技能写的评分器。
Δ 0.00,钱可没少花
剩下两个用例看似打平,实际却多花了钱。aggregate-result.json 记录了两组各自的费用和轮次,汇总表没有展示这些明细:
| 用例 | Δ | 带插件组:每次费用 | 无插件组:每次费用 | 费用变化 | 带插件组:轮次 | 无插件组:轮次 |
|---|---|---|---|---|---|---|
api-version-pin | +1.00 | $0.089 | $0.120 | −25% | 3 | 3 |
routing-one-time-payments | 0.00 | $0.128 | $0.070 | +84% | 5 | 1 |
which-key-type | 0.00 | $0.115 | $0.074 | +56% | 4.3 | 1 |
两个 Δ 0.00 的用例,裸模型平均都只用一个轮次就给出了答案。加载技能后,同样的答案却用了四到五个轮次,平均每次运行费用增加 56%–84%。我们保留了一次运行记录,可以看清多出的轮次用在了哪里:Claude 先调用技能,再用 Read 读取技能里的 references/payments.md,接着用 Grep 搜索同一个文件,最后才给出裸模型一个轮次就能给出的答案。表中的百分比按未四舍五入的每次运行费用计算;用表内已四舍五入的金额重算,会相差一两个百分点。
唯一省了钱的用例,恰好是技能提供了具体版本号的那一个,尽管那个版本号已经过期。基线组为了判断能否可靠作答,三次运行合计花了 84 秒,带插件组合计只用了 19 秒。
在这次测试中,技能只有在给出模型不愿自行断言的内容时,才省下了钱,另外两个用例都增加了开销。但评测汇总把两个多花钱却没有改善结果的用例都标为 Δ 0.00,每用例费用也只给出两组费用的合计,掩盖了组间差异。三个用例就这样全部通过了 1.0 的阈值。
运行前 要注意的五件事
命令存在,不代表已经开放。 在 Claude Code 2.1.266 中,这个命令能显示完整帮助,真正执行时却报 plugin eval is currently in early access,提示当前仍处于早期开放阶段。升级到 2.1.270 后就能用了。遇到命令有帮助却不能运行的情况,先升级,再排查其他原因。
不同版本支持的参数也有变化。 持续集成示例依赖的 --trust-plugin,在 2.1.266 的 --help 中找不到,到了 2.1.270 才出现。因此,持续集成环境除了固定模型,也要固定 Claude Code 版本。
插件名要放在参数前面。 --json、--tag 和 --allow-tools 都接收参数值。如果写成 claude plugin eval --json my-plugin,插件名会被当作输出路径。应当写成 claude plugin eval my-plugin --json。
由代理发起的评测,默认不发布报告。 Claude Code 会识别评测是否从另一个 Claude Code 会话内部启动。如果是,HTML 报告只保存在本地,并附上说明。要让这类运行也发布报告,需要加 --publish-report。否则输出里不会出现你期待的 Published:。
省钱模式的计分口径不一样。 启用 --ablation none 后,tool_used: Skill 会计入得分,不再只是指示项。我们检查时两个评分器都通过了,所以分数碰巧没变。但如果技能没有触发,同一套用例在省钱模式下的得分就会比完整评测更低。这两种模式的得分不能放在同一张趋势图里比较。
这些结果该怎么用
这个工具确实能解决一个实际问题:用户按日常说法提问,技能却不再触发。这类缺陷常见,代价也不小。claude plugin validate 只检查插件清单的语法,看不到实际行为上的退化。skill-creator 插件其实早就有自己的 evals/evals.json 格式;这次新增的是官方直接提供的命令,并且内置了无插件基线组。把 Δ 和技能触发指示项放在一起,就能准确发现技能不再触发的问题。
但不能因此把 Δ 当成质量分。它是两组在你编写的评分器上得出的分差。根据这次实测,我们建议这样做:
- 先核实标准答案,再写评分器。 版本号、价格、限制、接口地址都可能变化。如果技能把这些值写死了,就要手动核实当前正确值,再写进评分器,并注明核实来源。这样技能一过期,检查就会失败。直接照抄技能文件作为标准答案,只会让错误一直通过。评分器里的值也会过期,因此还要注明核实日期、定期复查。上面这个用例应该查 Stripe 的 API 版本管理文档,而不是另一份相同技能。
- 看到 Δ 0.00,先看两组得分,再查账单。 两组都为 1.00,说明裸模型自己就能通过;两组都为 0.00,说明两边都失败了,用例并没有测出东西。它们在 Δ 那一列看起来完全一样,所以要先读 WITH 和 W/OUT。确认两组都通过后,再打开
aggregate-result.json,比较两组的costUsd和turns,判断这段内容值不值得加载。 - 持续集成要同时检查得分和触发指示项。 在两组对照模式下,
tool_used: Skill不计入得分,因此技能不再触发,也不一定会让用例跌破阈值。我们那两个裸模型也能通过的用例,即使技能完全没触发,仍可能拿到 WITH 1.00。要在持续集成中单独检查技能触发指示项,不能指望--threshold覆盖。同时固定--model和--judge-model,确保下个月测出的分数仍能与今天比较。 - 整套用例都只有 Δ 0.00,也可能是有效结论。 但要先确认:评分器太宽松、提示词太简单、覆盖不全,也会测不出收益。只有两组在贴近实际使用的用例上都能通过,才有依据判断模型原本就会做;删除技能内容前也要先完成这一步。
这次数据能支持的结论其实更窄:Δ 是对照你选定的评分器得出的分差。最顺手的评分器往往只检查回答有没有复述技能里的值;在这样的检查下,过期的技能和有用的技能一样能得高分。
延伸阅读
- Anthropic 删掉 80% 的提示词,对你的 CLAUDE.md 有什么启发:从另一个方向得出同样的结论,你写下的大部分要求,模型本来就会做。
- CLAUDE.md 写到多大会开始拖慢性能?:还没开始测效果,加载指令的成本就已经发生了。
- 复现 Spotify 的词元用量下降 90%:本系列的上一次实测,同样提醒我们不能只看最醒目的数字。
- CLAUDE.md 里白耗词元的写法:哪些内容花了钱,却没有带来收益。
- Claude Code 生态还有哪些缺口:插件工具还有哪些地方没有补齐。
来源
- Anthropic:用评测测试插件。用例目录结构、六类评分器、带插件组与无插件组的对照方式、
tool_used: Skill不计分规则、持续集成示例及退出码的官方依据。 - Anthropic:Claude Code 更新日志。2026 年 9 月 11 日发布的 2.1.269 版本新增了
claude plugin eval。 - Stripe:stripe-best-practices 技能,位于
stripe/ai仓库。这是本次测试的技能;文中的版本号变更日期也根据其提交历史核实。 - Stripe:代理技能。技能的安装方法和预期用途。
- Anthropic:代理技能文档。说明了如何通过前置元数据中的
description决定技能是否触发。 - Anthropic:Claude Code 费用说明。评测报告中按标价估算费用的计算依据。
本文实测环境为 macOS 上的 Claude Code 2.1.270,本次运行的默认模型为 Claude Opus 5(claude-opus-5),使用 2026-05-16 安装后一直未更新的 stripe-best-practices。主用例集包含三个用例,每组按默认设置各运行三次,只用免费的 regex 和 tool_used 评分器。allowed_tools: [Skill] 在默认的只读工具基础上加上 Skill,两组都没有能联网的工具。主用例集合计运行 18 次,耗时 237 秒,费用 $1.79;另有一次四次运行的补充实验,费用 $0.42。两组各自的费用和轮次均取自 aggregate-result.json。
FAQ
claude plugin eval 是什么,它衡量什么? 这是 Claude Code 在 2026 年 9 月 11 日发布的 2.1.269 版本中新增的命令。每个用例包含提示词和评分器,带插件运行三次,无插件再运行三次。输出中的 WITH 和 W/OUT 是两组得分,Δ 是两者之差,反映插件在你编写的评分器上带来的得分变化。除非有评分器检查正确性,否则评测框架不会替你核实答案。
评测得分高,就说明技能好吗? 不能只凭这一点判断。Δ 高,说明技能让回答通过了裸模型未通过的评分检查。如果评分器只找技能里写着的字符串,过期的值和有用的值一样能拿到高分。我们的用例在一个已被上游更新过两次的版本号上拿到了 +1.00,裸模型拒绝猜测,却得了 0.00。
Δ 0.00 到底意味着什么? 先看 WITH 和 W/OUT,再解读分差。两组都为 1.00,说明裸模型自己就能通过评分检查;两组都为 0.00,说明两边都失败了,用例并没有测出东西。我们的两个用例属于前一种,但加载技能后,平均每次运行仍分别贵了 56% 和 84%,原本一个轮次就能完成,也变成了四到五个轮次。汇总表却把这笔额外开销显示成了平局。
运行评测要花多少钱? 我们的三个用例共运行 18 次,耗时 237 秒,按标价计算为 $1.79,约合每个用例 $0.60、每次运行 $0.10,而且只用了免费的评分器。每增加一个 llm 或 baseline 评分器,每次运行还要额外调用裁判模型三次。运行次数按「用例数 × 每组运行次数 × 2」计算。--ablation none 会让运行次数减半,但两组单次运行费用不同,总费用不一定减半。--max-cost-usd 在达到设定金额后不再启动新的运行,进行中的那次仍会跑完,总额可能略超。
应该用评测得分把关持续集成吗? 可以,但要单独检查技能触发指示项。在两组对照模式下,tool_used: Skill 不计入得分,因此技能不再触发时,用例也未必会跌破阈值,不能指望 --threshold 覆盖。得分阈值也发现不了内容过期:如果评分器照抄技能里的值,过期可能让 Δ 升高。需要补一个评分器,检查经人工核实的当前正确值,并固定 --model 和 --judge-model。
一个用例应该测什么? 找一个需要技能补充信息的用例:这些信息,模型独自回答时不会给出。再按核实过的值编写评分器,不能照抄技能文件里的说法。如果找不到这样的用例,接近零的 Δ 可能是在说明技能本身的问题。但要先确认两组在贴近实际使用的用例上都能通过,因为评分器过于宽松也会测不出收益。
这篇对你有帮助吗?