高级 📋 7 个步骤 第 442 / 446 篇

别再用「感觉还行」判断插件:用 claude plugin eval 量出 Skill 到底贡献多少

单看装了插件时的得分,你并不知道那是插件的功劳还是模型本来就强。claude plugin eval 会同时跑装插件与不装插件两臂并给出差值 Δ。本教程按目录结构、提示词 frontmatter、四类零成本评分器、结果表与 CI 门禁的顺序,把 Claude Code v2.1.269 起的插件评测流程走通。

2026.09.18· 20 分钟阅读· 约 2638 字· 🧪 插件评测 / 🤖 Claude Code

写 Skill 的人大多经历过同一幕:在对话里试了几次,觉得「效果还行」,于是打包发出去。可到了同事机器上,模型压根不调用它;换一个模型版本,原本会触发的场景又不触发了。问题在于,你手上从来没有一个数字能说明「这个插件究竟贡献了什么」。Claude Code 从 v2.1.269 起补上了这一环:claude plugin eval——把一个插件放进隔离会话里跑一批用例,同时再跑一遍不装插件的对照,最后给出差值 Δ。

🧪 本教程适合:给 Claude Code 写 plugin 或 Skill 的作者,以及要在团队里共享这些扩展的工程同学。需要 Claude Code v2.1.269 或更高版本,并已完成登录。

先把两个命令的分工划清

名字很像,职责完全不同,混着用会白折腾一轮:

命令回答的问题是否调用模型
plugin validate清单结构对不对否,纯静态检查
plugin eval行为有没有按预期走是,每次都产生真实调用

也就是说,validate 管「格式写对没有」,eval 管「活干对没有」。前者免费且瞬时,后者要花钱、要等待,但只有它能回答那个真正要命的问题:把插件拿掉,模型是不是照样做对?如果两者分数一样,那你这份插件对这个用例没有任何可证明的贡献。

Step 1:升级并确认版本达标

1 版本不够,命令根本不存在
# 查看当前版本
claude --version

# 低于 2.1.269 就先升级
claude update

# 确认子命令可用
claude plugin eval --help
claude plugin validate --help

版本是硬门槛。低于 v2.1.269 时该子命令不存在,你会看到「未知命令」而不是「参数错误」——先别怀疑自己参数写错,先核对版本号。

Step 2:认识 evals 目录的排布

2 一个用例一个子目录

评测套件放在插件仓库根目录的 evals/ 下。每个用例是它的一个子目录,里面固定两样东西:一份提示词,和一个放评分器的文件夹。

my-plugin/
├── plugin.json          # 或 .claude-plugin/plugin.json
├── skills/              # 技能目录(可选)
└── evals/
    ├── first-case/
    │   ├── prompt.md    # 这个用例发给模型的提示词
    │   └── graders/     # 一个或多个评分器(markdown 文件)
    └── second-case/
        ├── prompt.md
        └── graders/
            ├── uses-my-skill.md
            └── output-shape.md
📁 目录名字就是用例名字,会直接出现在结果表里。建议用「做什么」而不是「第几个」来命名,例如 weekly-report-format。跑上二十个用例之后,你只会记得语义化的名字。

Step 3:写一份 prompt.md

3 正文原样发送,frontmatter 控节奏

提示词正文会一字不改地发给 Claude,里面的 @路径 提及不会被展开成文件内容——这一点很关键,别指望靠它塞上下文。可调的参数放在 frontmatter 里:

---
max_turns: 10
timeout_seconds: 300
model: ""          # 留空用当前默认模型
tags: ["report", "smoke"]
allowed_tools: []
---

帮我把 src/reports/daily.ts 里的日期格式化逻辑改成 ISO 8601,
改完跑一次相关测试,把命令和实际输出贴给我。
max_turns 默认 10、timeout_seconds 默认 300。真实的多步任务经常需要更多轮次,但你调得越大,单次运行越贵。先按默认跑,看结果里有多少用例是「跑到上限还没收尾」,再决定放宽哪些。

Step 4:写评分器——四类零成本,另有模型判分

4 评分器是 pass/fail 检查

评分器本身也是 markdown 文件,frontmatter 里声明类型,正文放具体的检查规则。四类不产生额外模型调用的评分器最划算,另一类需要判分模型参与:

类型检查什么是否额外计费
regex在回复或产出的文件里匹配正则
tool_used某个工具、技能或 MCP 服务器有没有被调用
tool_order工具调用的先后顺序是否符合预期
file_exists预期文件是否真的被创建出来
模型判分按评分标准让另一个模型给回复打分
---
type: tool_used
tool: weekly-report
weight: 2
---

必须调用 weekly-report 技能,而不是模型自己临时拼一份周报。

具体类型名与字段以官方文档为准。评分器数量和权重会随版本演进,本篇给出的是结构,不是可以直接抄的最终清单。写之前先看一眼插件目录里官方生成的示例文件。

Step 5:让 eval init 先起草一套

5 手写用例最费时间,这一步能省一半

在插件目录里执行初始化,它会读你的插件结构,问你「什么算好、什么算坏」,然后把用例和评分器草拟出来,先做一次试跑,最后给你一个全量运行的成本估计:

# 切到插件根目录(有 plugin.json 的那一层)
cd ~/work/my-plugin

# 交互式起草评测套件
claude plugin eval init

# 草稿会落到 evals/ 下,草稿不满意就直接改文件
✍️ 起草时最有价值的输入不是「我想要什么结果」,而是「什么样的输出算失败」。把两个反例讲清楚(比如「只描述改动但没有实际执行」「引用了不存在的文件」),生成的评分器才拦得住东西。

Step 6:跑一遍,把表读明白

6 关键是 Δ 这一列
# 先便宜地试跑一次
claude plugin eval --runs 1

# 正式跑(默认每个用例跑 3 次取均值)
claude plugin eval

# 收紧通过门槛(默认 1.0,即评分器全过)
claude plugin eval --threshold 0.8

结果是一张表,字段含义如下:

含义
CASE用例名(取自目录名)
WITH装了插件的分数
W/OUT不装插件的对照分数
Δ两者之差,也就是插件的实际贡献
RUNS实际执行次数(含对照臂)
COST本次开销(按标价估算)

只看 WITH 会骗自己。WITH 满分、Δ 为零,说明模型不靠你的插件也能做对——这份能力要么已经被基座模型内化,要么你测的是一个太简单的任务。表里真正需要行动的是「WITH 高但 Δ 低」和「WITH 低」两种行。

Step 7:把门槛接进 CI

7 用退出码挡住回归

命令行按门槛返回非零退出码,所以可以直接放进流水线。报告除了终端汇总,还会生成一份自包含的 HTML 详情页:

# 流水线里做无交互运行 + 门槛判定
claude plugin eval --runs 1 --threshold 0.8
# 退出码非 0 -> 阻断合并

# 生成的报告
#   report.html   完整逐用例明细,可直接下载翻阅
# 账号支持时也会发布为私有制品
🔁 这条流水线最值得长期跑的时机有两个:改插件本身之后,以及基座模型发新版本之后。模型换代最容易让「原本会触发的 Skill」不再触发,而这类回归在你手工试用时几乎发现不了。

Δ 接近零的时候,先动 description

官方文档提到出现频率最高的初期结果,就是一个 Δ 接近零、同时 tool_used 评分器失败的行。它翻译成人话是:模型压根没选择你的技能。多数人此时的直觉反应是回技能正文里加约束、加例子,但方向往往错了——决定「要不要用它」的是技能的描述字段,不是正文。描述写清楚「什么情况下该用、什么情况下不该用」,比在正文里堆十条禁令有效得多。改完描述再跑一次,把两个 Δ 摆在一起对比,你才真正知道改动有没有用。

一条不能省的安全边界

评测跑起来的时候,插件的 hooks 与 MCP 服务器是以你自己的身份和权限执行的。隔离会话隔离的是对话上下文,不是权限边界。因此:只对你信任的插件跑 eval;拿到别人的插件想先看看效果时,别在自己的主力机器上直接跑。官方也明确提示了这一点。

成本与方差怎么控

两件必须接受的事:一是评测调用的是真实模型,费用计入你的订阅或 API 账户,判分模型还会额外加一笔;二是因为 Agent 执行存在抖动,同一用例每次结果并不完全一致,所以默认每个用例跑 3 次取均值。实操上的顺序建议是:先用 --runs 1 把套件本身调通(此时重点看「用例是否被正确理解」而不是分数),再全量跑一轮建立基线;此后只有在改动插件或模型换代时才重跑。把「每次提交都全量跑」当成目标,账单会难看,而且大部分变化其实无关紧要。

常见问题速查

现象常见原因处理
提示命令不存在Claude Code 版本低于 v2.1.269执行 claude update 后重试
用例全部满分且 Δ 为零任务太简单,模型不靠插件也能做对换更贴近真实难度的提示词
Δ 接近零且 tool_used 失败技能描述没写清适用场景先重写 description,再重跑对比
多次运行分数跳动Agent 执行本身有方差提高运行次数取均值,别用单次结论
开销超出预期用例轮次上限高 + 判分模型参与先用 --runs 1 试跑并看成本估计
同事机器结果不一致模型版本或插件版本不同把版本号与套件一起记录在评测结果旁

结语

这一步的价值不在于多了一个命令,而在于它把「我的 Skill 有用」从一句主观判断变成了一组可比的数字。它的设计里最聪明的部分是对照臂:单看装插件时的得分,你永远不知道那是插件的功劳还是模型本来就强;只有把不装插件的成绩摆在同一张表上,Δ 才有意义。

也正因为如此,首轮跑出来的结果大概率不好看——有些用例 Δ 为零,有些用例模型压根没选中你的技能。这不是坏事,那正是你要处理的问题清单。按描述、用例难度、评分器三个方向逐个改,再跑一轮,把两轮的 Δ 摆在一起,你才建立了真正的迭代循环。

← 返回教程中心