ponytail 之 /ponytail-review 命令剖析:让 AI Agent 只做"过度工程审查"的删减式 Code Review
本文以 .opencode/command/ponytail-review.md 为主体,完整拆解 ponytail 项目中这个"只找过度工程、不查正确性"审查命令的定义、五类删减标签、输出格式约定,以及它在 OpenCode 中如何从一个带 frontmatter 的 Markdown 文件被加载为斜杠命令的底层机制。读完后你可以理解该命令的每一条规则含义,并能在 OpenCode 等 Agent 宿主中直接复现这套"以净删行数为唯一指标"的审查流程。
命令定位:只审过度工程,不审正确性
.opencode/command/ponytail-review.md 是 ponytail 在 OpenCode 中注册的 /ponytail-review 斜杠命令文件。它在 frontmatter 中声明了唯一的元信息:
---
description: Review changes for over-engineering, what can be deleted
---
frontmatter 之后的正文就是命令的完整 prompt。它的第一句话就划定了审查范围的边界:
Review the current code changes for over-engineering only, not correctness.
也就是说,这个命令刻意把正确性缺陷、安全漏洞、性能问题全部排除在审查范围之外(这些应交给常规 review),它唯一的目标是回答一个问题:这段改动里有什么是可以删掉的。这与 ponytail 项目"最棒的代码是你根本没写出来的代码"(The best code is the code you never wrote)的整体哲学一致——核心规则集定义见 skills/ponytail/SKILL.md,其中"复用优先于新写、标准库优先于自造"的梯子(ladder)原则,正是本命令五类标签的判断依据。
命令本体:五类删减标签与输出格式
.opencode/command/ponytail-review.md 正文全文如下(这是命令的完整 prompt,逐句继承):
Review the current code changes for over-engineering only, not correctness. One line per finding: L
这段 prompt 规定了三件事:逐行输出的格式、五类标签体系、收尾结论。
输出格式:每条发现一行
格式模板为 L<line>: <tag> <what to cut>. <replacement>.,即:行号(L 前缀)+ 标签 + 要删什么 + 用什么替代。这个"一行一条"的强约束让审查结果天然可扫读、可核对,也避免了模型输出长篇分析性散文——这与 ponytail 主技能"解释比代码长就删掉解释"的输出纪律同源。
五类删减标签
| 标签 | 含义(命令原文) | 中文解读 | 替代方案 |
|---|---|---|---|
delete |
dead code/speculative feature | 死代码、投机性功能 | 无,直接删 |
stdlib |
reinvented standard library | 手写了标准库已有的能力 | 标准库函数 |
native |
dependency doing what the platform does | 依赖库干了平台原生就能干的事 | 平台原生特性 |
yagni |
abstraction with one implementation | 只有一个实现的抽象 | 内联 |
shrink |
same logic, fewer lines | 同等逻辑更少的行数 | 更短的写法 |
注意 stdlib 与 native 的区别:前者针对"手写的代码"(本该用标准库),后者针对"引入的依赖"(本该用平台能力,如用 <input type="date"> 而非日期选择库)。五类标签恰好覆盖了 ponytail 梯子(ladder)中最常见的五种"没爬对梯子"的情形。
收尾:净删行数是唯一指标
命令要求以"可净删的行数"(net lines removable)作为结尾。若无可删,输出固定一句话:Lean already. Ship.(已经很精简,直接发版)。这把开放式 review 收敛成一个可量化、可比较的单一指标——diff 最好的结局是变得更短。
完整版:ponytail-review 技能中的示例与边界
OpenCode 命令文件是精简版 prompt,同一命令的完整技能版定义在 skills/ponytail-review/SKILL.md,它补充了三个命令文件未展开的实战细节,可视为对命令 prompt 的"参考手册":
多文件 diff 的定位格式
跨文件改动时格式扩展为 <file>:L<line>: ...,例如 repo.py:L88: yagni: AbstractRepository with one implementation. Inline it until a second one exists.
正反例对比
技能版明确给出"坏输出 vs 好输出"的对照。坏例子是典型的客套式提问:
❌ "This EmailValidator class might be more complex than necessary, have you considered whether all these validation rules are needed at this stage?"
好例子则是格式化的删减清单:
L12-38: stdlib: 27-line validator class. "@" in email, 1 line, real validation is the confirmation mail.
L4: native: moment.js imported for one format call. Intl.DateTimeFormat, 0 deps.
repo.py:L88: yagni: AbstractRepository with one implementation. Inline it until a second one exists.
L52-71: delete: retry wrapper around an idempotent local call. Nothing replaces it.
L30-44: shrink: manual loop builds dict. dict(zip(keys, values)), 1 line.
五条示例正好逐一演示五个标签的写法:stdlib 指名替代函数,native 给出零依赖的原生方案,yagni 说明"等到第二个实现出现再抽",delete 明确"替代方案是:无",shrink 直接展示更短写法。
评分与边界
- 评分:以
net: -<N> lines possible.收尾,N 为可删净行数;无可删则Lean already. Ship.并停止。 - 范围:只审过度工程与复杂度。正确性 bug、安全漏洞、性能问题显式不在范围内,应转交常规 review。
- 豁免项:单个冒烟测试或
assert式自检是 ponytail 的"最小底线"而非膨胀,永远不应被标记删除(对应 ponytail 主技能"非平凡逻辑必须留下一条可运行检查"的规则)。 - 行为约束:该命令只列出删减项,不直接动手改代码;用户说 "stop ponytail-review" 或 "normal mode" 时,回退到冗长式 review 风格。
实现原理:一个 Markdown 如何变成斜杠命令
.opencode/command/ 目录本身只是数据,真正让它生效的是仓库内的 OpenCode 插件。调用链可以从源码完整追踪:
1. 插件注册。 仓库根的 opencode.json 只有一行关键配置:
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["./.opencode/plugins/ponytail.mjs"]
}
若从 npm 安装(包名 @dietrichgebert/ponytail),则把 { "plugin": ["@dietrichgebert/ponytail"] } 写进自己的 opencode.json 即可。
2. 扫描命令目录。 插件 .opencode/plugins/ponytail.mjs 的 config 钩子会读取 .opencode/command/ 下所有 .md 文件,以文件名(去扩展名)为命令名注册——所以 ponytail-review.md 自动成为 /ponytail-review 命令,无需手写注册表。同一钩子还会把 skills/ 目录加入 OpenCode 的技能路径。
3. frontmatter 解析。 解析逻辑在 .opencode/plugins/ponytail-frontmatter.cjs 的 parseCommandFile 中:
const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/);
if (!match) return null;
const description = match[1].match(/description:\s*(.+)/)?.[1]?.trim();
return { description, template: match[2].trim() };
它把文件拆成两部分:frontmatter 中取 description(即命令在斜杠菜单里的说明文案,对应 Review changes for over-engineering, what can be deleted),正文作为 template(即命令执行时注入的 prompt 模板,对应前文那整段审查指令)。正则中的 \r?\n 显式兼容 CRLF——注释说明了原因:Windows 检出(autocrlf)交付 \r\n,而 npm 发布的是 \n。若文件没有 frontmatter,函数返回 null,该文件被静默跳过。
4. 测试印证。 tests/opencode-plugin.test.js 用 node:test 对这条加载链路做了结构性冒烟测试,无需真实 OpenCode 进程:parseCommandFile reads frontmatter description + body, LF and CRLF 用例分别写入 LF 与 CRLF 两个临时文件,断言解析结果都是 { description: 'do a thing', template: 'the template body' };returns null when there is no frontmatter 用例验证无 frontmatter 时返回 null。这证明 ponytail-review.md 这类命令文件被解析为"描述 + 模板"的行为是经过测试保证的。
同一命令在不同宿主的分发
ponytail-review 并非 OpenCode 独有,同一份命令内容以三种形态在仓库中分发,可以对照查看:
| 形态 | 文件 | 说明 |
|---|---|---|
| OpenCode 斜杠命令 | .opencode/command/ponytail-review.md |
frontmatter + prompt 模板,由插件加载 |
| TOML 命令(其他宿主) | commands/ponytail-review.toml | description 与 prompt 两个字段,内容与 OpenCode 版逐字相同 |
| 技能(Skill) | skills/ponytail-review/SKILL.md | 完整版:含多文件格式、正误示例、评分与边界 |
从 docs/agent-portability.md 的分发矩阵看,/ponytail、/ponytail-review、/ponytail-audit、/ponytail-debt、/ponytail-gain、/ponytail-help 六个技能/命令在 Qoder、Hermes、Devin、OpenClaw 等宿主上以不同前缀暴露,例如 Codex 中以 @ponytail-review 触发、OpenClaw 中以 $ponytail-review 触发、Devin 中以 /ponytail:ponytail-review 触发(见 README.md 的跨平台安装说明)。对指令-only 的宿主(Cursor、Windsurf、Cline 等),命令不注册,只加载常驻规则集。
实战使用:在 OpenCode 中运行一次删减审查
适用前提:项目已接入 ponytail 插件(checkout 方式由 opencode.json 指向本地插件;npm 方式配置 @dietrichgebert/ponytail)。操作步骤:
- 让 Agent 完成一次代码改动,使工作区产生待审查的 diff;
- 在 OpenCode 中输入
/ponytail-review,插件会用ponytail-review.md的正文作为 prompt 模板执行审查; - 预期得到一份逐行清单,形如
L12-38: stdlib: 27-line validator class. "@" in email, 1 line.,每条含行号、五类标签之一、删减对象与替代方案; - 结尾读净删行数:有可删项则给出净删行计,没有则返回
Lean already. Ship.; - 审查只列清单不改代码,按清单自行删减;若要退出该模式,说 "stop ponytail-review" 或 "normal mode"。
需要提醒的边界:该命令明确不审正确性、安全与性能,若这些方面需要把关,应走常规 review 流程;一个 assert 式自检不会被误报为"可删"。这条命令的价值正在于它把"这次改动能不能更短"从主观感受变成了一个有标签体系、有固定格式、有净删行指标的可执行审查。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00