
Claude Code
Claude Code 插件评测与输出样式切换:claude plugin eval 与 /output-style 使用指南
面向自建 Claude Code 插件与技能的开发者,介绍如何用 claude plugin eval 对插件评测套件进行自动打分,以及如何在无头会话中用 /output-style 列出并切换输出样式。内容涵盖评测目录结构、case.yaml 与 prompt.md/graders 两种写法、with-without 消融机制、常用参数与成本控制、结果 JSON 字段解读,以及输出样式的持久化位置与自动化调用方式。
如果你在自建 Claude Code 的插件或技能,迟早会遇到一个问题:改了提示词或工具声明之后,怎么知道这次改动是变好了还是变坏了。靠人工反复对话既慢又不可复现。Claude Code 提供的 claude plugin eval 就是为这件事准备的——它把插件放进一个受控的评测环境里跑一遍,输出可复现的评分结果,并同时给出 JSON 与 HTML 报告。与之配套的 /output-style 则解决另一个场景:在无头(headless)会话里也能列出和切换输出样式,让自动化流程拿到风格一致的回复。本文面向已经写过插件或技能、想给它们加上自动评分环节的开发者,把这两项能力的目录约定、参数、成本结构和常见坑讲清楚。涉及版本号、价格、配额等易变信息时,请以官网当前信息为准。
准备工作
在动手之前,先确认下面几件事。
- 可用的 Claude Code 环境。评测既可以在本地终端跑,也可以在云端会话(Linux)里跑,两者行为一致。用
claude --version确认当前版本,因为claude plugin eval与/output-style是较新版本才加入的能力,旧版本上执行会直接报未知命令。 - 一个待评测的插件目录。最小情况下只需要在该目录下放
.claude-plugin/plugin.json,里面写name和version两个字段即可。评测对象可以是路径、插件名,也可以是plugin@marketplace形式的 ID;已安装的插件和skills目录下的插件都能被解析到。 - 评测用例目录。默认位置是插件根目录下的
evals/,每个用例是一个子目录。子目录里要么放一个case.yaml,要么放prompt.md加graders/*.md的组合。没有这个目录,评测会直接告诉你找不到用例。 - 成本预算意识。评测会真实调用模型,产生费用。建议第一次就跑最小用例,并始终带上成本上限参数。
- 非交互环境的信任处理。在没有交互终端、或者使用
--json的场景下,Claude Code 不会弹出信任确认提示,而是直接失败。CI 里需要显式跳过这一步。
操作步骤
第一步:确认评测命令的解析规则
先看帮助信息,了解评测对象是怎么被解析的。
claude plugin eval --help
帮助信息会说明:评测目标可以是路径、插件名或 plugin@marketplace ID;当插件被成功解析出来时,系统会自动追加一条「不加载插件」的基线臂(baseline arm)。这一点是理解后续成本与结果结构的关键。
第二步:在未准备的目录上跑一次,看清报错
在一个还没有评测用例的仓库里直接执行,会先卡在信任确认上:
claude plugin eval .
Error: /home/user/your-repo is not a trusted plugin directory, and this run cannot stop to ask you about it (no interactive terminal, or --json / CI).
非交互会话不会弹出确认提示,而是直接失败。加上 --trust-plugin 再跑,报错内容就变成了缺少用例:
claude plugin eval . --trust-plugin
No eval cases found under /home/user/your-repo.
Cases are expected in a evals/ directory under /home/user/your-repo (the default), each case a directory containing case.yaml or prompt.md.
Run `claude plugin eval init` for a guided interview, or `claude plugin eval init --bare <name>` to scaffold a blank case.
报错信息里直接给出了下一步该敲的命令,所以在这里基本不会卡住。
第三步:生成用例雏形
用 --bare 生成一个空白用例,比走交互式访谈快得多,适合先摸清结构:
claude plugin eval init --bare demo-case
Created evals/demo-case/prompt.md and evals/demo-case/graders/criteria.md
生成的两个文件都是带 frontmatter 和 TODO 行的空模板。prompt.md 长这样:
---
max_turns: 10
allowed_tools: [Read, Glob, Grep, Skill]
---
TODO: describe what the agent should do
graders/criteria.md 长这样:
---
type: llm
weight: 1
---
TODO: describe what a successful response looks like
如果希望被引导着一步步配置,也可以直接运行 claude plugin eval init,它会以访谈形式提问。
第四步:填好 TODO 并执行
为了把成本看得更清楚,先用一个极小的用例:提示词只问「1+1 等于几,只回答数字」,评分标准只判断「回复里是否包含数字 2」。把 allowed_tools 留空,max_turns 设为 3。
然后带上成本上限执行:
claude plugin eval . --trust-plugin --runs 1 --max-cost-usd 0.2 \
--no-publish --judge-model haiku --json eval-result.json
输出开头会有一段关于消融(ablation)的说明,这是理解整个机制最有价值的一行信息:
Ablation: defaulting to with-without — a plugin resolved from this path, so each case also runs a no-plugin baseline arm (2× runs) and reports Δ; ...
Wrote /tmp/.../eval-result.json
Report: .../evals/results/2026-09-14T07-16-55-894Z/report.html
意思是:因为从这个路径成功解析出了插件,每个用例都会额外跑一条不加载插件的基线臂,也就是实际执行次数翻倍,并报告两者的差值 Δ。
第五步:读懂结果 JSON
输出的 JSON 里,几个关键字段如下:
| 字段 | 含义 |
|---|---|
claudeVersion | 执行评测的 Claude Code 版本 |
durationSeconds | 整体耗时 |
costUsd | 总花费 |
with 臂的 costUsd | 加载插件那一臂的花费 |
without 臂的 costUsd | 不加载插件那一臂的花费 |
judgeVotes | 评分模型的投票结果数组 |
turns | 各臂的对话轮数 |
同时,HTML 报告会写到 evals/results/<时间戳>/report.html,可以直接打开查看。
第六步:在无头会话中列出输出样式
/output-style 是斜杠命令,但可以直接作为 claude -p 的提示词字符串传入:
claude -p "/output-style" --output-format json
不带参数时,它会返回当前样式和可用样式列表,形如:
Output style: default
Available styles:
- default (current)
- Proactive: Claude executes immediately, minimizes interruptions, and prefers action over planning
- Concise: Claude responds tersely, leading with results and skipping preamble and narration
- Explanatory: Claude explains its implementation choices and codebase patterns
- Learning: Claude pauses and asks you to write small pieces of code for hands-on practice
Usage: /output-style <style>
值得注意的是,current 会随执行位置变化。在没有项目配置的目录里,当前样式是 default,列表里只有内置的几种;而在 .claude/settings.json 里声明了 outputStyle 的仓库根目录下,当前样式会变成声明的那一个,并且 .claude/output-styles/*.md 里的自定义样式也会出现在列表中,连 Markdown frontmatter 里写的说明文字都会一并展示。因此这个命令也可以当作「查看本仓库定义了哪些输出样式」的手段。
第七步:切换并确认持久化位置
带上参数即可切换:
claude -p "/output-style Concise" --output-format json
# result: "Output style set to Concise"
cat .claude/settings.local.json
{ "outputStyle": "Concise" }
切换不是一次性的,结果会写入 .claude/settings.local.json 并持久化。也就是说,如果不想让自动化流程改动本地配置,需要提前考虑这一点。
一个完整示例
下面把流程串起来,从零开始跑通一个最小评测。
1. 准备插件目录。在工作目录下创建 .claude-plugin/plugin.json:
{
"name": "demo-plugin",
"version": "0.1.0"
}
2. 生成用例雏形。
claude plugin eval init --bare demo-case
3. 填写提示词。编辑 evals/demo-case/prompt.md:
---
max_turns: 3
allowed_tools: []
---
1+1 等于几?只回答数字。
4. 填写评分标准。编辑 evals/demo-case/graders/criteria.md:
---
type: llm
weight: 1
---
如果回复中包含数字 2,则判定为成功。
5. 执行评测。
claude plugin eval . --trust-plugin --runs 1 --max-cost-usd 0.2 \
--no-publish --judge-model haiku --json eval-result.json
6. 查看结果。打开 eval-result.json 检查 costUsd、durationSeconds 与各臂花费,再打开 evals/results/<时间戳>/report.html 看可视化报告。
7. 切换输出样式。
claude -p "/output-style Concise" --output-format json
cat .claude/settings.local.json
到这里,一条「改插件 → 跑评测 → 看差值」的闭环就搭起来了。
注意事项
关于消融与执行次数
--runs 1 并不等于「总共只跑一次」。只要默认的 --ablation with-without 生效,加载插件的 with 臂和不加载插件的 without 臂都会跑,成本大致翻倍。如果确实只需要单臂,必须显式指定 --ablation none。反过来说,默认值让每次评测都能测出「插件到底带来了多少改变」,作为评测工具的默认行为是合理的。
结果 JSON 里的 runsPerCase 不可尽信
用 --runs 1 执行时,JSON 中记录的 runsPerCase 可能仍是默认值 3,而各臂的实际执行结果只有一条。如果 CI 里靠这个字段判断「跑了几次」,就会与实际不符。更稳妥的做法是读取 arms 数组的元素个数。
成本控制要一开始就做
即便只是问一句「1+1」,一次评测也会产生真实费用。总成本大致按「用例数 × 执行次数 × 2 条臂」增长,用例一多、次数一调,量级变化很快。--max-cost-usd 在超限时不会中断正在进行的 run,而是让已开始的 run 跑完,然后以退出码 2 结束。因此建议从第一次试跑就带上这个参数,而不是等接入 CI 时再加。
评分器分免费与付费两类
评分器共有六种。regex、tool_used、tool_order、file_exists 从转录记录或文件系统做机械判定,不产生额外费用;llm 和 baseline 需要调用判定模型,会产生费用。想压低评分开销,优先考虑用机械判定类评分器表达验收条件。例如用 tool_used 判断「预期中的技能是否被调用」,就能在零成本的前提下发现回归。
判定模型可以覆盖
--judge-model 的默认值是一个小型快速模型,具体名称未公开。需要指定时用该参数覆盖。
发布行为要留意
不加 --no-publish 时,评测会涉及向 claude.ai 发布。评测内部插件时,建议始终带上这个参数,避免把不该外发的内容推出去。
输出样式没有对应的 CLI 子命令
在 claude --help 的范围内,找不到名为 output-style 的顶层子命令,也没有对应的 config 子命令。它是斜杠命令,非交互场景下有两种等价做法:用 claude -p "/output-style <name>" 传入,或者直接改写 .claude/settings.json 或 .claude/settings.local.json 里的 outputStyle 键。两者写入的是同一个文件,效果一致。
其他常用参数
| 参数 | 默认值 | 作用 |
|---|---|---|
--ablation <mode> | with-without | 设为 none 时退化为单臂执行 |
--runs <n> | 用例的 runs 字段,或 3 | 每个用例的执行次数 |
--max-cost-usd <usd> | 无 | 超出上限后不再启动新 run,已开始的跑完后以退出码 2 结束 |
--judge-model <model> | 小型快速模型 | 覆盖判定所用模型 |
--json [path] | 无 | 带路径则写入文件,不带则输出到标准输出 |
--trust-plugin | 无 | 跳过首次信任提示,供 CI 使用 |
把机械判定类评分器作为起点,先覆盖「该调用的技能有没有被调用」这类可自动验证的断言,再逐步引入需要模型判定的评分项,是控制评测成本同时保持回归检测能力的务实路径。