Codex + Ponytail,代码真的更简洁了?
让 Agent 加个日期选择器,它写了 404 行。 其实,浏览器原生一行就能解决:<input type="date">你大概也遇到过。
你只是想让 AI Agent 加个小功能。它先装了一个组件库,再写一层包装组件,补一套样式,最后还开始跟你讨论时区、主题和浏览器兼容。
你盯着 diff 里几百行新增代码,心里只有一个念头:我就要一个日期选择器啊……
更扎心的是,这些代码大部分还能跑。你连骂它的理由都找不到,只能默默 review、默默删、默默付 Token 的钱。
最近我看到一个很有意思的项目:Ponytail。
它做的事情恰恰相反:让 Agent 在动手之前先停一下,问自己一句:
这段代码,真的有必要存在吗?
https://github.com/dietrichgebert/ponytail
这个今年 6 月开源的项目,到现在已经接近 15 万 stars。

t一、不是不会写,是停不下来

AI Agent 特别擅长把一句话需求,扩展成一个「看起来很完整」的方案:
- 一个小功能,变成一个新组件
- 一段重复逻辑,变成一层抽象
- 标准库就能解决的事,变成一次依赖安装
- 用户没提的功能,也顺手帮你补齐
问题不在于这些代码不能用,而在于:没人证明过它们为什么一定要写。
传统开发里,过度设计可以在 Code Review 时删掉。但 Agent 工作流里,等你发现时,组件已经建好、依赖已经装上、十几个文件已经改完,清理成本早就产生了。
所以更好的时机是:写之前。
Ponytail 做的就是这件事:把资深开发者常说的那句「先看看有没有现成的」「这个真的需要吗」,变成 Agent 每次动手前必须过一遍的规则。
官方 Benchmark 看起来很猛,但我更关心一个实际问题:
放到我平时用的 Codex 上,到底有没有效果?
所以我自己跑了一次。
二、Codex 实测:Todo List
我新开了两个独立会话,都只给 Codex 一句话:
Build a simple todo app I can open in the browser.为了避免 UI 风格差异过大,两边都使用了同一个 frontend-design Skill。
两组的主要区别,就是有没有启用 Ponytail。
最后两个版本都生成了一个可以直接在浏览器打开的 TodoList。

先看最直观的数据:
| 指标 | Codex | Codex + Ponytail | 变化 |
|---|---|---|---|
| 总代码行数 | 586 行 | 393 行 | -193 行 / -32.9% |
| 文件大小 | 19,927 B | 14,288 B | -5,639 B / -28.3% |
| CSS Block | 374 行 | 245 行 | -129 行 / -34.5% |
| JavaScript Block | 141 行 | 99 行 | -42 行 / -29.8% |
| 文件数 | 1 | 1 | 一致 |
也就是说,同一句 Prompt 下:
586 行 → 393 行,少了 193 行,接近三分之一。
截图 左边no ponytail ,右边开启 ponytail(功能界面对比)

代码文件大小对比:20KB vs 14KB

但这里不能简单下结论:
Ponytail 把“同样的代码”压缩了 33%。
我真正关心的是:这 193 行到底少在哪里?
发现1. 浏览器已经有的,就别自己再造
两个版本都要实现一个最基本的能力:
点击 Todo,把任务标记为完成。
没有 Ponytail 的版本自己创建了一个按钮:
const check = document.createElement("button");
check.className = "check";
check.type = "button";
check.setAttribute("aria-pressed", String(todo.done));
check.innerHTML = '<svg ...>...</svg>';然后再手动维护点击状态、SVG 对勾和 aria-pressed。
Ponytail 版本则直接用了浏览器原生能力:
const checkbox = document.createElement('input');
checkbox.className = 'todo-check';
checkbox.type = 'checkbox';
checkbox.checked = todo.done;也就是最普通的:
<input type="checkbox">功能一样,思路却完全不同。
平台已经提供的能力,就不要重新实现一遍。
这正好对应 Ponytail 的一个核心原则:能用 Native Platform Feature,就先别自己造。
发现2. 更大的差异:少做了很多“没人要求的功能”
继续对比,我发现真正拉开代码量的并不只是 Checkbox。
我的 Prompt 只要求做一个能在浏览器打开的简单 Todo app,没有提产品功能。
未启用 Ponytail 的版本却加了今日日期、完成进度环和百分比、All / Open / Done 数量统计,以及更复杂的 Empty State,甚至预设了 Take a short walk、Tidy one small thing、Write down an idea 三条任务。
这些功能并非没用,页面也因此更丰富,只是我没要求它做。Ponytail 版本也不完全局限于 Prompt 的字面要求:它有新增、完成、删除 Todo,All / Active / Done 筛选、清除已完成和 localStorage 本地保存,但没有继续加日期、进度环或推荐任务。
比起“少写了 33%”,我更在意它少做了多少自行扩展的功能。代码少了多少是一回事,少掉的究竟是什么,才值得看。
发现3. 但少,不一定永远更好
这里还有一个很有意思的反例。
没有 Ponytail 的版本读取 localStorage 时,做了完整的异常处理:
function loadTodos() {
try {
const saved = JSON.parse(localStorage.getItem(STORAGE_KEY) || "[]");
returnArray.isArray(saved)
? saved.filter(item =>
item &&
typeof item.text === "string" &&
typeof item.done === "boolean"
)
: [];
} catch {
return [];
}
}Ponytail 版本更直接:
let todos = JSON.parse(localStorage.getItem(storageKey) || '[]');确实短很多,但如果 localStorage 里出现了损坏 JSON,前一个版本明显更稳。
所以这 193 行并不能全部定义成“垃圾代码”。
有一些是过度实现,也有一些是更完整的防御性处理。
这也是为什么我不太想把 Ponytail 简单理解成:“让 Agent 少写代码。”
更准确的说法应该是:让 Agent 重新证明:这些代码为什么有必要存在。
真正的目标不是最少代码,而是最少的、但足够正确的代码。
三、PonyTail的决策梯子

看完刚才这个 TodoList,再看 Ponytail 的设计就很好理解了。
Ponytail 不是格式化工具,也不是代码高尔夫。它只改变一件事:
Agent 选择方案的顺序。
每次动手前,Agent 要从上往下逐级问:
- 这件事真的需要存在吗?(先做 YAGNI 判断)
- 代码库里是不是已经有了?(复用,不重写)
- 标准库能解决吗?
- HTML、CSS、浏览器 API、数据库约束能解决吗?
- 已安装的依赖能解决吗?(不新增依赖)
- 能不能一行搞定?
- 以上都不成立,才写最小可用实现。
回到官方日期选择器的例子:浏览器原生的 <input type="date"> 早就做完了。
类似的还有:
- 颜色选择 →
<input type="color"> - 文件选择 →
<input type="file"> - 折叠内容 →
<details> - 简单弹窗 →
<dialog> - 查询参数 →
URLSearchParams - 深拷贝 →
structuredClone
Ponytail 不是「永远不用库」,而是把「装库」从默认动作,降级成需要被证明的选择。
它「懒」,但不糊弄
这里最容易误会:第六级「能否一行」,不是让 Agent 玩代码高尔夫。
Ponytail 明确要求:梯子必须建立在理解问题之后。Agent 依然要先读代码、追调用链、搞清约束。
一句话概括:
它懒得写多余的代码,但不懒得理解代码。
而且有些东西不能为了「少写」而删:
- 信任边界上的输入校验
- 防止数据丢失的错误处理
- 安全与权限措施
- 无障碍基础
- 非平凡逻辑的最小检查
这也解释了为什么刚才 TodoList 的 localStorage 例子值得单独拿出来说。
少写本身不是目的,判断哪些不能少才是关键。
真正的最小实现,不是把护栏拆掉,而是把护栏之外的装饰拆掉。
四、Codex 里如何装
Ponytail 支持 Claude Code、Codex、Cursor、OpenCode、Gemini CLI 等一大票 Agent,核心规则只有一份,各平台做对应适配。
以 Codex 为例,官方 README 给的安装方式是两行:
codex plugin marketplace add DietrichGebert/ponytail
codex plugin add ponytail@ponytail安装后运行 codex,打开 /hooks,检查并信任它的两个生命周期 Hook,然后重新开一个 Thread。
如果是 Codex Desktop,安装完成后重启应用即可。
Ponytail 本身提供几档工作强度:
- lite:正常开发,但更积极提醒简单方案
- full:默认思路,完整执行决策梯子
- ultra:面对明显过度设计的代码库,更激进地质疑复杂度
- off:关闭
另外还有 review、audit、debt、gain 等能力,用来检查当前改动、扫描代码库和查看 Benchmark。
这里我建议不要死记命令。
Ponytail 对不同 Agent 的调用方式并不完全一样,安装后直接看当前版本帮助最稳。
还有一个容易忽略的点:主 Agent 创建子 Agent 时,Ponytail 会把同一套规则继续注入。
否则很容易出现这种情况:
主 Agent 知道复用已有工具,子 Agent 一接手,又重新造轮子。
写在最后
Ponytail 最值得借鉴的,不是把 Agent 变得「更懒」,而是让它在写代码之前,多问一次:
这段代码,真的有必要存在吗?
对人类开发者,这是一种工程习惯;
对 AI Agent,它得被写成规则、注入上下文,还要在主子 Agent 之间传下去。
代码的最小单位不是一行,而是一个被证明有必要存在的行为。
如果这篇对你有一点点用,麻烦点个赞
再转给那个天天帮 Agent 擦屁股的同事,让他的代码也更精简(不要像裹脚布)
参考
[1] Ponytail 官方 GitHub 仓库:https://github.com/DietrichGebert/ponytail
[2] Ponytail README:https://github.com/DietrichGebert/ponytail/blob/main/README.md
[3] Benchmark:https://github.com/DietrichGebert/ponytail/blob/main/benchmarks/results/2026-06-18-agentic.md
[4] Agent portability:https://github.com/DietrichGebert/ponytail/blob/main/docs/agent-portability.md
