
这是什么
一套装进编码 agent 的规则,用来改掉 agent 动手之前写下的东西:它先停在七级阶梯上第一个成立的那级——这东西不必存在、代码库里已经有了、标准库能做、平台原生能力能做、已装的依赖能解决、一行能写完——都否,才写刚好能跑的最小实现。它以六个 skill 的形式发布,也给有插件系统的宿主提供插件,档位按会话设为 lite、full、ultra 或 off(默认 full),并同样注入每个 subagent。安装通常是一两条命令:Claude Code 里先 /plugin marketplace add DietrichGebert/ponytail 再 /plugin install ponytail@ponytail;Codex 里是 codex plugin marketplace add DietrichGebert/ponytail 与 codex plugin add ponytail@ponytail;Gemini CLI 用 gemini extensions install https://github.com/DietrichGebert/ponytail;Pi 用 pi install git:github.com/DietrichGebert/ponytail;Cursor 用 node ponytail/scripts/cursor-hooks.js install;OpenClaw 用 clawhub install ponytail;OpenCode 只要在 opencode.json 里加一行。没有插件系统的宿主改为复制一份规则文件。默认档位可以用 PONYTAIL_DEFAULT_MODE 环境变量或 ~/.config/ponytail/config.json 固定下来。
谁做的仓库的 224 次提交里 114 次挂在他的 GitHub 账号下,另有 8 次用的是他另一台机器上的邮箱;其余来自约六十位贡献者,其中一位以 Emeriko 之名提交了 23 次。
它是怎么搭起来的
组成 · 6一份规则文档,按每个宿主读得懂的格式各抄一遍,再加一层很薄的钩子来决定什么时候把它注入。这里没有服务,也不调用任何模型:规则是文本,注入是按宿主写的生命周期钩子,状态是用户主目录下的一个小文件。这个形状解释了树里几乎所有的东西——同一份规则以八份文件入库,六个 skill 写一次再为 OpenClaw 生成第二版,每个宿主一份钩子清单,每个适配器一个测试文件,还有几个只负责让副本保持一致、让版本号互相对齐的脚本。它也解释了这东西会在哪里坏掉:宿主换了插件 API——比如 OpenCode 2——时,没有服务器可以改,只能在每个适配器上各修一遍。
- AGENTS.md 与各宿主的规则副本
- 一套规则,八份入库副本:
.agents/rules/ponytail.md、.clinerules/ponytail.md、.cursor/rules/ponytail.mdc(2,620 字节)、.github/copilot-instructions.md、.kiro/steering/ponytail.md(2,560)、.qoder/rules/ponytail.md、.windsurf/rules/ponytail.md与AGENTS.md(2,593 字节),多数为 2,495 字节;scripts/check-rule-copies.js(2,981 字节)负责在改动后核对它们是否还一致。 - skills/ 与 .openclaw/skills/
- 六个 skill,各一份
SKILL.md:ponytail 6,637 字节,help 2,796,review 2,383,gain 1,973,debt 1,703,audit 1,652;另有一份为 OpenClaw 生成的副本(它的 ponytail 只有 5,957 字节),由scripts/build-openclaw-skills.js(2,873 字节)产出,过期时测试会失败。 - hooks/
- 十二个文件、34 KB:
ponytail-activate.js4,601、ponytail-config.js5,881、ponytail-instructions.js5,487、ponytail-mode-tracker.js6,194、ponytail-runtime.js5,682、ponytail-subagent.js2,683,两个 statusline 脚本(.sh696、.ps1885),以及四份按宿主写的钩子清单。 - .opencode/、commands/ 与 pi-extension/
- 同样六个命令写了两遍:六个
.opencode/command/*.md(510 到 1,141 字节)与六个commands/*.toml(515 到 1,152 字节)。.opencode/plugins/ponytail.mjs(3,773 字节)就是那个 OpenCode 2 拒绝加载的 V1 入口,旁边是ponytail-frontmatter.cjs(1,054);pi-extension/index.js7,171 字节。 - ponytail-mcp/ 与 benchmarks/
- v4.8.0 标题里那个 MCP 服务:
index.js1,922、instructions.js1,181、README.md1,507、package.json365。测量这边是benchmarks/下 17 个文件、benchmarks/results/下 9 个文件,以及benchmarks/agentic/的 5 个文件 103 KB(tasks.py50,646、run.py26,677、judge.py9,987、complete.py7,944)。 - tests/、scripts/ 与 assets/
- 十六个测试文件 84 KB,每个适配器一个——
hooks.test.js21,189、cursor-hooks.test.js15,639、hermes-plugin.test.js9,613、correctness.test.js6,382。scripts/六个文件 20 KB:发布 OpenClaw skill、核对规则副本、核对版本号、装与卸 Cursor 钩子、卸载。assets/14 个文件 1,127 KB,其中logo.png一个就 567,655 字节——正是 #939 从 npm 包里剔掉的那批。
取舍,以及它替代了什么
留住安全底线,不砍校验、错误处理、安全与无障碍 替代 一句“尽量写成一行”的提示词
README 先把规则写死,再用测量背书:“The rule was never ‘fewest tokens.’ It is: write only what the task needs, and never cut validation, error handling, security, or accessibility. The code ends up small because it is necessary, not golfed.” 在基准表里,“YAGNI + one-liners”那一组在对抗性安全档上只有 95%,而它是 100%。
在共享函数上一次性修根因 替代 按报告点名的路径各补一处
这条被写进
AGENTS.md当成规则,而不是留给临场判断:“a report names a symptom. Grep every caller of the function you touch and fix the shared function once — one guard there is a smaller diff than one per caller, and patching only the path the ticket names leaves a sibling caller still broken.” 同一份文件也承认搞错位置的代价:“The smallest change in the wrong place isn’t lazy, it’s a second bug.”砍掉一角,并留下标注天花板的
ponytail:注释 替代 现在就把它做对出自
AGENTS.md:“Mark deliberate simplifications that cut a real corner with a known ceiling (global lock, O(n²) scan, naive heuristic) with aponytail:comment naming the ceiling and upgrade path.” 而ponytail-debt这个 skill 的存在就是为了把这些标记收进台账,“so ‘later’ doesn’t become ‘never’”。Gemini 适配器不带根目录的 hooks/hooks.json 替代 给每个宿主都发同一份生命周期钩子文件
README 把这写成有意为之:“Gemini auto-loads that path, while Ponytail’s lifecycle hooks use Claude/Codex event names.” 这个适配器改用扩展安装,并让 skill 单独随行。
Grok Build 不接生命周期钩子 替代 像别的插件宿主那样接上去
README 给的是机制层面的原因而不是偏好:“Grok lifecycle hooks are not used because their SessionStart output cannot inject instructions.” Grok 用户改为启用插件、按名字调用 skill。
依据AGENTS.md(2,590 字符全文打印;磁盘上 2,593 字节)、README.md(23,529 字符,其中报告打印了前 6,000 字符,其余取自默认分支上的原始文件)、完整的 166 个文件树及其体积、两级的目录汇总、16 个 release 标题,以及三十个 issue 与 pull request 及其评论串。docs/cursor-hooks.md(13,264 字节)、docs/platform-native.md(9,434)与 docs/agent-portability.md(6,878)只在树里给出了名字和体积,内容未读;assets/ 的 1,127 KB 也只按名字与体积记录。
制作过程
6 个阶段- 01
十七天发完十四个版本,然后沉默三十九天
仓库建于 2026-06-12,第一次提交是当天 00:52:37 的
Initial commit;报告里最后一次提交是 2026-09-14T14:34:42Z 的chore: release v4.10.0 (#870)。94 天里一共 224 次提交,而且几乎全堆在前两个月:六月 155 次、七月 51 次、八月 4 次、九月 14 次。16 个 release 的标题比提交数更会讲故事。v1.0.0 — He ships.发于 2026-06-12T02:43:54Z,距第一次提交不到两小时;同一天跟上v4.0.0: production grade, still lazy;2026-06-13 是v4.1.0: three more agents与v4.2.0: lazy in OpenCode now;2026-06-15 一天里发出v4.3.0: more agents, still lazy、v4.4.0: field-tested, still lazy、v4.5.0: lazy in Copilot,四小时后又是v4.6.0: help, reluctantly。2026-06-16 是v4.7.0: lazy in OpenClaw now;2026-06-23 与 06-24 的四个是v4.8.0: comprehension first, now with an MCP server、v4.8.1: consistent versioning、v4.8.2: now on npm、v4.8.3: lazy in subagents too;2026-06-29 的v4.8.4: lazy in Hermes now收尾——16 个 release 里有 14 个挤在十七天内。此后空白三十九天,直到 2026-08-07 的v4.9.0: 53 commits of doing less,标题里数着 53 次提交,而按月表给的是七月 51、八月 4;再往后是 2026-09-14 的v4.10.0,标题只有版本号。周围是 148,962 个星、8,009 个 fork、356 个 watcher、319 个 open issue——对 224 次提交来说,大约每 665 个星对应一次提交——仓库体积 2,666 KB,语言一栏写着 JavaScript。 - 02
整个产品就是一份文档加六个命令
被装进去的东西短到可以直接引用。
AGENTS.md(2,593 字节)开头是:“You are a lazy senior developer. Lazy means efficient, not careless. The best code is the code never written.” 接着是七级阶梯,每一级都是一个问句:这东西需要被造出来吗(YAGNI);代码库里已经有了吗;标准库能做吗;平台原生能力覆盖了吗;已安装的依赖能解决吗;能写成一行吗;都否,才写刚好能跑的最小实现。阶梯是在理解问题之后才爬,而不是用来代替理解。同一份文件还写明什么不许省——信任边界上的输入校验、防止数据丢失的错误处理、安全、无障碍、“the calibration real hardware needs”——并要求非平凡逻辑“leaves ONE runnable check behind”,而“trivial one-liners need no test”。四周是六个 skill:/ponytail把强度设成lite、full、ultra或off,不给参数就报告当前档位;/ponytail-review审当前 diff 的过度设计并交出一份删除清单;/ponytail-audit对整仓库做同一件事;/ponytail-debt把标在刻意妥协上的标记收进一本台账,“so ‘later’ doesn’t become ‘never’”;/ponytail-gain打印实测记分板;/ponytail-help把其余命令列出来。默认档位是full,可以用PONYTAIL_DEFAULT_MODE环境变量或~/.config/ponytail/config.json里的defaultMode改。 - 03
一半的提交把一个模型写成共同作者
224 次提交里有 112 条共同作者尾注,其中最大的几群写的是模型而不是人:Claude Opus 4.8 三十二条、Claude Opus 4.8 (1M context) 三十一条、Claude Fable 5 七条、Claude Opus 5 三条,另有一条只写 Claude。另有四条写的是工具或机器人——Cursor、Copilot、Devin、
google-labs-jules[bot],各一条。人也在这份名单里:Emeriko 七条、Dietrich Gebert 五条、Admin 两条,其后是一长串各一条。其余归属在账号统计里:224 次提交有 215 次能关联到账号,其中 114 次就挂在他自己的账号下,另有 9 次完全没有关联账号。按邮箱看,103 次来自dietrich.gebert@gmail.com,8 次来自dgebert@Dietrichs-MacBook-Pro.local,他自己的两个地址合计 111 次。按作者名统计有 70 个不同名字,其中 Emeriko 的 23 次在按账号的那张表里找不到对应项。贡献者名单列了 50 个人:Lakshya77089 十次,ousamabenyounes 八次,之后是 dhedhialy、hamza-ali-shahjahan、salaamdev 各四次。让这件事不只是花絮的,是AGENTS.md的最后一行——它把这套规则掉转过来对准了这份仓库自己:“(Yes, this file also applies to agents working on the ponytail repo itself. Especially to them.)” - 04
二十个宿主,一套规则,八份副本
README 给了 Claude Code、Codex、GitHub Copilot CLI、Pi agent harness、OpenCode、Gemini CLI、Qoder、Antigravity CLI、Hermes Agent、CodeWhale、Swival、Devin CLI、OpenClaw、Grok Build 和 Cursor 的安装办法,另外还点名了只读规则文件的宿主:Windsurf、Cline、Copilot Chat、Aider、Kiro、Zed。README 顶部一枚徽章写着“works with 20 agents”。文件树能看出这套面积要付什么:同一份规则文本以八种宿主格式各存了一份——
.agents/rules/ponytail.md、.clinerules/ponytail.md、.cursor/rules/ponytail.mdc(2,620 字节)、.github/copilot-instructions.md、.kiro/steering/ponytail.md(2,560)、.qoder/rules/ponytail.md、.windsurf/rules/ponytail.md、AGENTS.md,多数是 2,495 字节——靠scripts/check-rule-copies.js(2,981 字节)和node scripts/check-versions.js让副本与版本号保持一致。有插件系统的宿主拿到的是代码:hooks/有十二个文件、34 KB,包括ponytail-activate.js(4,601)、ponytail-config.js(5,881)、ponytail-instructions.js(5,487)、ponytail-mode-tracker.js(6,194)、ponytail-subagent.js(2,683),每个宿主还有一份钩子清单(claude-codex-hooks.json966、qoder-hooks.json704、copilot-hooks.json539、cursor-hooks.json320)。同样六个命令还写了两遍:六个.opencode/command/*.md(510 到 1,141 字节)与六个commands/*.toml(515 到 1,152 字节)。 - 05
OpenCode 2 的移植,在公开场合定夺
报告里最热闹的一条线不是关于少写代码,而是某个宿主的插件 API 换了形状。2026-09-26 开的 #941 报的是
@dietrichgebert/ponytail@4.10.0在 OpenCode v2 上根本加载不了:“Plugin must export a default definition with an id and an effect or setup function. (cause: SchemaError(Expected object at ["default"]))”。同样的失败在 Windows 11 + Node v24.19.0 的 v2.0.18、Linux x64 + Node v22.23.2、macOS arm64 上都被复现;#930 早先对着 v2.0.15 开过,又被报告者自己以“filed prematurely”关掉。接下来的是一队互相竞争的修法:#928 被当作 #915 与 #907 的重复关掉,然后是 #933、#940、#943。在 #943 里逐条对比时,一位评论者把 #907、#940、#933、#864、#729、#734 都列为备选,并称 #943 最干净;同一条讨论里还报告:在 2.0.20 上,几个补丁都用的{ id, setup, server }双出口会注册 0 个命令、0 个 skill,而从同一个文件里删掉server键就能注册六个——日志里分别是commands: 2, ponytail: 0与commands: 8, ponytail: 6。另一条 #939 走的是体积:npm 包里塞进了assets/和 pi-extension 的测试,而包里没有任何在运行的东西引用它们,砍掉后发布包从 997 kB 降到 49 kB,文件数从 54 降到 38。 - 06
那组数字,以及它自带的更正
README 的招牌说法是“~54% less code (up to 94%) · ~20% cheaper · ~27% faster · 100% safe”,方法是一次无头 Claude Code 会话去改 tiangolo 的 full-stack-fastapi-template——一个真实的 FastAPI + React 仓库——按它留下的
git diff计分:十二个功能工单,同一个 agent 带 skill 与不带 skill 各跑一遍,n=4,模型 Haiku 4.5。表格给出的 ponytail 是代码行数 −54%、token −22%、成本 −20%、时间 −27%,在一个单独的对抗性安全档上是 100%;啰嗦文风对照组 caveman 是 −20% / +7% / +3% / +2%、安全 100%;“YAGNI + one-liners”提示词是 −33% / −14% / −21% / −30%、安全 95%。砍得最狠的地方正是 agent 容易过度建造的地方:日期选择器从 404 行变成 23 行,取色器从 287 行变成 23 行,“because it reaches for a native<input>instead of a component”。这组数字值得记的原因在于 README 会改自己的旧数字:更早的单轮跑分报的是“80-94% less code”,它被留在折叠段落里,并附了一句说明——#126“fairly pointed out that the bare-model baseline pads its answer with prose and options, so that gap is partly a conversational-baseline artifact”;徽章上则写着那个平铺数字是“the per-task ceiling, not the average”。benchmarks/results/下九个结果文件带着日期,从 2026-06-12 到 2026-06-22,最大的一份是 12,226 字节的 agentic 报告。
相关档案
全部档案 →第 061 号
Reticle
一个 MCP 服务器加一个只在开发期生效的 SDK:让编码 agent 从应用内部去读、去操作一个正在运行的 web 或桌面应用,然后给出判词和该改的文件与行号,而不是一张截图。
第 064 号
delegate-skills
一个技能包,给每一种编码 agent CLI 各配一份委派技能:编排方写好自足的任务书,另一条 CLI 去改真实工作树,而审查与提交留给人。
第 067 号
tty7
一个纯 Rust 写的终端:shell 属于后台的服务器而不是窗口,退出应用它们照跑;重启之后面板带着原有布局和最后留在屏幕上的内容回来,四条 CLI 命令能让一个编码 agent 驱动另一个,而远端工作区就是同一个服务器跑在另一台机器上。