TL;DR :Ponytail 把"写简洁代码"从一句模糊建议变成了一个 7 级 yes/no 决策梯子。实测砍 54% 代码、省 20% 成本、安全满分。它跟加记忆类项目有本质区别------一个是减法规则(失败了你一眼能看出来),一个是加法规则(失败了你也发现不了)。这篇文章拆它的架构、三个值得偷的设计、以及哪些场景下不该用。
入口
给 Agent 加记忆的项目有一个共同问题:记忆会腐烂。你说过喜欢 React Query,三个月后换了团队用 tRPC,Agent 还照着旧偏好写代码------你花了半小时才发现它在做一个你早就不做的决策。
这个疑虑适用于所有往 Agent 系统提示里塞东西的项目。Ponytail 也在这个范畴里------它往系统提示里注入一份反过度工程化规则。第一眼不是"牛逼",而是"又来一个"。
但翻完代码之后,我的判断是:Ponytail 跟加记忆类项目是两种东西。 加记忆是加你不知道什么时候会过时的信息,Ponytail 加的是一个不会过时的决策偏置。但这不代表它可以无脑全局开启。
核心机制:7 级梯子
Ponytail 的核心不是一个 prompt,是一个决策树。Agent 写任何代码之前,必须从第一级开始爬,哪一级站住了就停:
markdown
1. 这东西真的需要做吗? → 不需要:跳过(YAGNI)
2. 代码库里已经有了? → 复用,别重写
3. 标准库能做? → 用标准库
4. 原生平台能力能覆盖? → 用平台能力(<input type="date"> 而不用 datepicker 库)
5. 已安装的依赖能解决? → 用现有依赖,别加新的
6. 能一行搞定? → 一行
7. 实在不行:写最少能工作的代码
每一级的判断标准极其具体------"标准库有没有?"是 grep 一下就能回答的问题。"原生 <input> 能不能用?"是查 MDN 就能回答的问题。Agent 不需要"品味",只需要逐步排除。
梯子跑在理解之后,不是代替理解。 SKILL.md 里明确写了:Agent 必须先读完所有相关代码、追踪真实调用链,然后才爬梯子。懒的是解法,不是阅读。
三档强度
不是"开/关",是渐进式:
| 等级 | 行为 | 什么时候用 |
|---|---|---|
| lite | 正常写代码,顺嘴提一句"其实有个更懒的写法" | 日常开发,不想冒险 |
| full(默认) | 严格爬梯子,输出最短解法 | 代码开始膨胀 |
| ultra | YAGNI 极端主义,连需求本身都质疑 | 重构前的"核威慑" |
less
# 同一个需求 "加个缓存",三种等级的输出:
# lite: "Done, cache added. FYI: lru_cache covers this in one line."
# full: "@lru_cache(maxsize=1000) on the fetch. Skipped custom cache class."
# ultra: "No cache until a profiler says so. When it does: @lru_cache."
架构:一份规则,16 种适配器
先看文件结构------整个项目 80 个文件,核心只有两条线:
bash
ponytail/
├── AGENTS.md ← 核心规则(所有 Agent 都能读的静态版)
├── skills/ponytail/SKILL.md ← 完整版规则(带 lite/full/ultra 三档)
├── hooks/
│ ├── ponytail-instructions.js ← 指令构建器(唯一的事实来源)
│ ├── ponytail-config.js ← 配置解析(env > config.json > default)
│ ├── ponytail-runtime.js ← 模式状态读写(flag file + 输出协议)
│ ├── ponytail-activate.js ← SessionStart hook:注入规则 + 状态栏
│ ├── ponytail-subagent.js ← SubagentStart hook:子 Agent 也注入
│ └── ponytail-mode-tracker.js ← UserPromptSubmit hook:追踪 /ponytail 命令
├── skills/ ← 6 个 skill(ponytail / review / audit / debt / gain / help)
├── .cursor/rules/ ← 静态规则文件(Cursor / Windsurf / Cline / Kiro / Copilot)
├── .opencode/plugins/ ← OpenCode 插件
├── pi-extension/ ← Pi 扩展
├── ponytail-mcp/ ← MCP 服务器
├── gemini-extension.json ← Gemini CLI 扩展
├── plugin.yaml ← Hermes Agent 插件
└── __init__.py ← Hermes Python 插件实现

指令构建器:唯一的事实来源
ponytail-instructions.js 读 SKILL.md(6400 字符),按当前模式过滤掉不相关的规则行,输出统一格式的注入文本。Claude Code 的 hooks 调它,Pi 的 extension 调它,OpenCode 的 plugin 调它,MCP server 也调它。改了 SKILL.md 里的一句话,所有 16 种 Agent 下次启动自动生效。
CI 里 check-rule-copies.js 检查所有静态副本(.cursor/rules/、.clinerules/、.github/copilot-instructions.md)是否跟 AGENTS.md 保持同步。不是"给每个 Agent 写一份规则",而是"一份规则,多种注入方式"。
Hooks 管线
有 hook 能力的 Agent(Claude Code、Codex)在三个生命周期节点注入:
bash
用户启动会话 ──→ SessionStart hook ──→ 写 flag file(.ponytail-active)
├─ 注入规则到系统提示
└─ 检测状态栏,没配就提示
用户发消息 ────→ UserPromptSubmit hook ──→ 检测 /ponytail lite|full|ultra|off
└─ 更新 flag file
Agent 创建子任务 ──→ SubagentStart hook ──→ 读 flag file,注入规则给子 Agent
SubagentStart 是容易被忽略但关键的一环。 没有它,主线程有规则,子 Agent 没有------子 Agent 按默认行为写代码,不受梯子约束。issue #252 专门记录了这个问题。
模式状态机
bash
┌──────────┐ /ponytail lite ┌──────────┐
│ off │ ────────────────→ │ lite │
│ (无注入) │ ←──────────────── │ (提醒) │
└──────────┘ stop ponytail └────┬─────┘
│ /ponytail full
▼
┌──────────┐ /ponytail ultra ┌──────────┐
│ full │ ────────────────→ │ ultra │
│ (默认) │ ←──────────────── │ (极端) │
└──────────┘ /ponytail lite └──────────┘
状态持久化在 ~/.claude/.ponytail-active(一个 flag file),所有 hook 节点共享。PONYTAIL_DEFAULT_MODE 环境变量或 ~/.config/ponytail/config.json 控制新会话默认模式。
Skills 体系
5 个辅助 skill,每个都是"只读不写":
| Skill | 做什么 |
|---|---|
/ponytail-review |
审查 diff 里的过度工程化,一行一个发现 |
/ponytail-audit |
全仓库扫描,排出最该删的东西 |
/ponytail-debt |
grep 所有 ponytail: 注释,生成技术债账本 |
/ponytail-gain |
展示 benchmark 效果数据 |
/ponytail-help |
命令速查 |
ponytail-review 的输出格式特别值得学------一行一个发现,每个发现只包含位置、标签、替换方案:
vbnet
L12-38: stdlib: 27-line validator class. "@" in email, 1 line.
L4: native: moment.js for one format call. Intl.DateTimeFormat, 0 deps.
L52-71: delete: retry wrapper around idempotent call. Nothing replaces it.
net: -43 lines possible.
没有"This class might be more complex than necessary"这种废话。每个 finding 直接告诉你砍什么、用什么替。
适配器全景
| 适配层 | 注入方式 | 模式切换 | 覆盖的 Agent |
|---|---|---|---|
| 生命周期 Hooks | SessionStart + SubagentStart + UserPromptSubmit | /ponytail 命令 |
Claude Code, Codex, Copilot CLI |
| 系统提示注入 | 每轮 system.transform 追加 |
同上 | OpenCode, Pi |
| MCP 协议 | ponytail_instructions tool + prompt |
调用时传 mode | 任何支持 MCP 的 Agent |
| 静态规则文件 | 复制 .cursor/rules/ 等 |
无 | Cursor, Windsurf, Cline, Kiro, CodeWhale |
| Hermes 插件 | pre_llm_call + gateway rewrite |
同 Hooks | Hermes Agent |
效果数据
在真实项目上(FastAPI + React 模板,Haiku 4.5,12 个 feature 任务,每个跑 4 次取平均):
| 指标 | vs 无 skill 基线 |
|---|---|
| 代码行数 | -54% |
| Token 消耗 | -22% |
| 成本 | -20% |
| 时间 | -27% |
| 安全性 | 100% |
对比其他方案:caveman(极简表达)砍了 20% 代码但 token 和成本反而上升------说得少不等于想得少;"YAGNI + one-liners"这句 prompt 砍了 33% 但安全性掉到 95%。Ponytail 是唯一在所有指标上同时正向的。
Benchmark 的诚实度
Ponytail 的 benchmark 里有一段话值得关注:
我们早期的 agentic benchmark 跑出来 Ponytail 只有 ~4% 的差距,差点就发布了。后来发现是 bug------Ponytail 的 SessionStart hook 在每一个 arm 上都触发了,包括 baseline。所以 baseline 实际上是偷偷跑着 Ponytail 的。修掉之后才看到真实的 -54%。
而且作者本人承认旧 benchmark 有偏------旧版是 single-shot(一个 prompt 一个 completion),baseline 会输出一堆选项和解释,"行数"里混了 prose。新版换成真实 Claude Code session 在真实 repo 上跑,行数从 git diff 里数。这种"自己推翻自己旧数据"的诚实度,在开源项目里不常见。 (Colin Eberhardt 在 issue #126 里指出了旧 benchmark 的偏误,Ponytail 作者接受批评后重做了整版。)
三个值得偷的设计

1. 梯子模型:把品味问题变成决策流程
大多数写简洁代码的 prompt 是模糊的------"write clean code"、"keep it simple"。Agent 不知道什么叫简洁。
Ponytail 的解法是:不给定义,给决策树。 每一级判断标准极其具体------"标准库有没有?"是 grep 就能回答的问题。"原生 <input> 能不能用?"是查 MDN 就能回答的问题。Agent 不需要品味,只需要逐步排除。
这个思路可以迁移到任何你想约束 Agent 行为的场景。不要告诉 Agent"要安全",告诉它"每个用户输入先过白名单校验,然后参数化 SQL,最后设置 CSP header"。不要告诉 Agent"要可测试",告诉它"每个非平凡函数留一个 assert 式 self-check,有输入就写一个正常 case + 一个边界 case"。
关键不是"给指令",是"给判断流程"。 好的 Agent 规则不是一条条 do/don't,而是一个能让 Agent 在每一步做 yes/no 判断的决策树。
2. ponytail: 注释:给简化留审计线索
bash
# ponytail: global lock, per-account locks if throughput matters
注释必须包含两个信息:当前简化的上限 + 什么时候该升级。三个月后看到这行注释,你知道为什么这里只有全局锁,也知道什么信号出现时该换成更细粒度的锁。
这个约定的关键是"升级触发条件"------不是为了现在写更多代码,是为了让未来的人知道"这个简化不是 bug,是决策,决策条件是 X"。没有注释的简化是欠债,有注释的简化是存在于这个约束下的正确决策。
Ponytail 还配了一个 /ponytail-debt skill,grep 全仓库的 ponytail: 注释,生成技术债账本。标注了no-trigger 的注释------即只写了简化但没写升级路径的------是腐烂风险最高的。
3. 不懒清单:砍和保的边界
梯子爬得再高,这几样绝对不能砍:trust boundary 的输入校验、防数据丢失的错误处理、安全措施、可访问性、硬件校准。
清单的价值不是"列了哪些东西不能砍",而是把砍和保的边界从凭感觉变成了按类别。 Agent 不需要判断"这个校验重不重要",它只需要检查------这是 trust boundary 的输入校验吗?是,那就不能砍。
这个清单可以按项目类型定制。做支付系统的,加上"幂等性检查"和"审计日志"。做数据迁移的,加上"回滚路径"和"数据校验"。做前端组件的,加上"键盘导航"和"屏幕阅读器标签"。清单越长,Agent 在"不能砍"的边界上越可靠。
反模式
| 用法 | 后果 |
|---|---|
| 不管什么项目,装了就开 full | 支付/安全场景下可能漏掉必要检查 |
| 以为跟 Prettier 一样只影响格式 | 它影响的是架构决策,不是缩进宽度 |
| 把"能一行就一行"当"可以吞错误" | try { ... } catch {} 也是一行 |
简化了但不留 ponytail: 注释 |
三个月后同事看到全局锁,以为是你没想到 |
| 跟项目 CLAUDE.md 冲突时不处理 | Agent 随机选一条,你永远不知道下次选哪条 |
它跟加记忆类项目的本质区别
CloudMem 这类项目是加法规则 ------给 Agent 加记忆、加偏好、加历史。这些"加法"如果过时了,Agent 基于错误前提写代码,你很难发现------行为看起来"有道理",只是基于你已经忘掉的旧偏好。
Ponytail 是减法规则------告诉 Agent 少写代码。减法规则的副作用是"代码不够"------代码跑不起来,功能不完整,一眼就能看出来。说"加上 X",Agent 就补上。
加法规则的失败是隐性的,减法规则的失败是显性的。 这是根本区别。
实践建议
哪些场景下不该用
错误处理场景下,"能一行就一行"可能变成"能吞就吞"。 fetch().catch(() => null) 也是一行。Ponytail 的不懒清单写了"错误处理不能砍",但 Agent 在具体场景下可能判断失误------写支付回调时觉得"这个 API 很少失败",把重试逻辑压缩成一行。
跟项目规则冲突时,Agent 随机选一边。 你的 CLAUDE.md 写"所有公开函数必须 docstring + 单元测试",Ponytail 说"不需要框架,一个 assert 就够了"。两条矛盾指令同时存在,Agent 自己判断优先级------有时候选对,有时候不。
每轮注入占上下文。 模式过滤后的注入文本约 1500 tokens。在 200K 上下文里不算什么,但在 Haiku 或小型模型里,每轮被抽走上下文空间去读规则。
安全/支付场景不适合。 Benchmark 在 6 个安全 task 上满分,但那是精心设计的 task,不是真实生产环境。
不用装也能搬走的 5 个设计
- 梯子模型:在 AGENTS.md 里加"写代码前先问:这东西真的需要吗?标准库有吗?能一行吗?"------3 级就够用。
- 简化标记约定 :
// lean: <上限>, <升级路径>------任何简化必须带注释。 - 不懒清单:项目规则里明确写"以下东西绝对不能简化:输入校验、错误处理、安全、可访问性"。
- 多档强度:给 Agent 的规则不要只有"开/关",至少加一档"提醒但不强制"。
- 输出格式:代码先,然后最多三行"跳过了什么、什么时候加回来"。解释比代码长就删掉解释。
Ponytail 是一个好工具,但它是刹车,不是方向盘。
如果你决定装,从 lite 开始。加记忆类项目的教训------任何往 Agent 系统提示里塞东西的操作,都应该带着"我什么时候会关掉它"的预案。
但 Ponytail 真正值得去想的问题,不是"该不该装",而是它提示了一个更底层的设计原则:在 Agent 工具设计里,减法比加法更安全。 加记忆、加偏好、加规则------这些"加法"的失败成本是隐性的,你发现不了。减代码、减决策空间、减可选路径------这些"减法"的失败是一眼可见的。这不是说减法没有风险,是说减法的风险落在明处,你修得快。
以后你再往 Agent 的系统提示里塞东西的时候,先问自己:这是加法还是减法?失败了我是马上能发现,还是三个月后才发现?
项目地址:github.com/DietrichGeb...
题外话
写完 Ponytail,顺便提三个我在做的项目,跟这篇文章的主题有关------都是让 Agent 工作得更好的工具。
Archify --- 在聊天里生成架构图、流程图、时序图。说一句话,出一个可切换暗色/亮色主题、可导出 PNG/SVG 的 HTML 文件。不需要设计能力,不需要拖拽工具。
Hive --- 浏览器里的多 Agent 协作工作台。一条 prompt 调度多个 Agent,带持久化身份、共享任务图、一键重启全队。MCO 的后续项目。
MCO --- AI Coding Agent 编排工具。一条 prompt 同时调度 Claude Code、Codex、Gemini CLI、OpenCode、Qwen 等多个 Agent 并行工作。核心理念跟 Ponytail 一样------让 Agent 做它擅长的事,框架做剩下的。