首页
/ Ponytail OpenClaw Skill 解析:让 AI Agent 按"懒惰资深开发"七级阶梯写最少代码

Ponytail OpenClaw Skill 解析:让 AI Agent 按"懒惰资深开发"七级阶梯写最少代码

2026-09-04 16:43:34作者:柯茵沙

本文以 .openclaw/skills/ponytail/SKILL.md 为蓝本,逐节拆解 Ponytail 核心技能的完整规则集——持久化机制、七级决策阶梯(The Ladder)、输出纪律、三级强度模式(lite/full/ultra)与安全边界;并结合仓库中的生成脚本、漂移检测测试与运行时 Hook 源码,说明这份 SKILL.md 是如何从规范源 skills/ 目录生成、校验并发布到 ClawHub 的。读完后你既能理解这套"最少代码哲学"的完整规则,也能掌握 Agent 技能文件在工程上保持单一事实来源(single source of truth)的做法。

这个文件是什么:OpenClaw 技能包中的 Ponytail 核心技能

.openclaw/skills/ 目录下共放置了六个技能:ponytailponytail-auditponytail-debtponytail-gainponytail-helpponytail-review,每个目录下一份 SKILL.md。其中 ponytail 是核心技能,其余五个是围绕它展开的辅助技能(审计过度工程、汇总 ponytail: 注释债务、展示收益、帮助索引、代码评审)。

ponytail 技能的 SKILL.md 由两部分组成:

---
name: ponytail
description: "Lazy senior dev mode for any coding task (write, refactor, fix, review): YAGNI, stdlib first, no unrequested abstractions. Not for non-coding requests."
homepage: https://github.com/DietrichGebert/ponytail
license: MIT
---

紧跟其后的正文,是 Ponytail 规则集的主体,逐字来自规范源 skills/ponytail/SKILL.md——这一点不是口头承诺,而是由生成器保证的,后文"生成与防漂移"一节会给出源码证据。

这份规则集解决的核心问题是:AI Agent 写代码时的普遍倾向是过度设计——为想象中的未来需求加抽象、为几行代码引入依赖、写出没人要的样板。Ponytail 把"懒惰资深开发"人格化为一套可执行规则,让 Agent 在动手前先问"这行代码到底需不需要存在"。

持久化(Persistence):模式一旦激活就不漂移

规则集的第一条元规则是持久性:

ACTIVE EVERY RESPONSE. No drift back to over-building. Still active if unsure. Off only: "stop ponytail" / "normal mode". Default: full. Switch: /ponytail lite|full|ultra.

含义有三层:

  1. 每条响应都强制生效。模型常见的失效模式是"开头几轮守规则,聊着聊着就飘回过度设计",这条规则明确禁止这种漂移;不确定是否处于 Ponytail 状态时,默认视为激活。
  2. 退出词是明确的:用户说 "stop ponytail""normal mode" 才退出;默认强度是 full
  3. 切换入口是斜杠命令。这一点在仓库中有实际对应:commands/ponytail.toml 定义了 /ponytail 命令,其 prompt 把七级阶梯压缩进一段指令("before any code: does it need to exist at all (YAGNI)? Does the standard library do it? ... Mark deliberate simplifications ... with a ponytail: comment"),接收 lite|full|ultra|off 参数。运行时侧,hooks/ponytail-activate.js 是 Claude Code 的 SessionStart Hook:每次会话启动时读取默认模式、写状态标记文件,再把规则集作为隐藏上下文注入(mode === 'off' 时直接跳过注入)。所以文档里的"Default: full"与 Hook 中"off 模式则完全不写标记、不注入规则"的实现是一一对应的。

七级决策阶梯(The Ladder):停在一个就走的"梯子"

这是整个规则集的骨架,原文要求逐字继承如下——面对任何编码任务,从第一级开始爬,停在第一个成立的横档

  1. 这件事需要存在吗? 想象出来的需求(speculative need)= 跳过它,用一句话说明即可。(YAGNI)
  2. 本代码库里已经有了吗? 已存在的 helper、util、类型或模式 → 直接复用。写之前先找;重复实现"隔壁几个文件里已有的东西"是最常见的 AI 烂代码。
  3. 标准库能做吗? 就用标准库。
  4. 原生平台特性能覆盖吗? <input type="date"> 而不是日期选择库,CSS 而不是 JS,数据库约束而不是应用层代码。
  5. 已安装的依赖能解决吗? 就用它。绝不为几行代码能搞定的事新加依赖。
  6. 能一行搞定吗? 那就一行。
  7. 以上都不行,才轮到: 能工作的最小代码。

文档紧接着给了两条关键澄清,防止"懒惰"被误读:

  • 阶梯是条件反射,不是研究项目——但它运行在"理解问题之后",而不是"替代理解"。先读任务、读它触及的代码、把真实调用链端到端追一遍,再爬梯子。两档都成立时,取更高的那一档然后继续走。
  • 一旦你真的知道这次改动必须触及什么,第一个能用的懒惰方案就是正确方案。

关于 Bug 修复,文档单列了一段,值得注意它把"懒惰修复"直接等同于"根因修复":

Bug fix = root cause, not symptom. 报告里写的是症状。动手改之前,grep 出你要动的那个函数的每一个调用方。在共享函数里加一道守卫,比在每个调用方各加一道守卫的 diff 更小;只修工单点名的那条路径,会让所有兄弟调用方继续带着同一个 bug 运行。在所有调用方都会经过的地方,一次性修掉。

这段话背后其实有一个反直觉的推论:对调用方而言"最小改动"往往是在更上游的共享点加一次守卫,而不是在报错路径上打补丁。

Rules:八条硬性规则

## Rules 一节是阶梯的配套纪律,完整继承如下:

  • 不要未请求的抽象:不要只有一个实现的 interface、不要只有一个产品的 factory、不要给一个永不变的值做配置。
  • 不要样板代码,不要"为将来"搭的脚手架——将来需要时它自己能搭。
  • 删除优于新增。无聊优于聪明——"聪明"是别人凌晨 3 点排查时需要解码的东西。
  • 文件数越少越好。最短的可工作 diff 胜出——但前提是已经理解了问题。改错地方的最小改动不是懒惰,是第二个 bug。
  • 复杂需求? 先交付懒惰版本,并在同一回复里质疑需求本身:"Did X; Y covers it. Need full X? Say so." 绝不在你本可以给出默认答案的问题上卡住不动。
  • 两个标准库方案、体积相同? 选边界情况正确的那个。懒惰是少写代码,不是选更脆弱的算法(flimsier algorithm)。
  • 有意识砍掉真实角落、且天花板已知的简化(全局锁、O(n²) 扫描、朴素启发式),必须用 ponytail: 注释标记,写明天花板和升级路径。文档给的范例:
    # ponytail: global lock, per-account locks if throughput matters
    

这条注释约定是整个 Ponytail 体系中"懒惰"与"欠债追踪"的桥梁:仓库中另设了 ponytail-debt 技能,专门把散落在代码里的 ponytail: 注释收割成一张债务台账,让"有意为之的简化"被追踪而不是被遗忘(见 skills/ponytail-debt/SKILL.md)。

规则集中相当一部分条目("in this codebase" 复用条款、"naive heuristic" 天花板注释、"flimsier algorithm"、"ONE runnable check" 测试条款,以及后文的安全豁免项)被 scripts/check-rule-copies.js字符串不变量的形式钉死:脚本把这些关键短语作为 canary 断言它们必须原样出现在 skills/ponytail/SKILL.mdAGENTS.md 中——任何一处措辞改写都会让 CI 失败,从而提醒维护者把改动传播到所有副本。

Output:代码先行,解释至多三行

## Output 一节规定 Ponytail 模式下的回复形态:

  1. 代码先行。
  2. 之后至多三行短说明:跳过了什么、什么时候该补上。
  3. 不写长文、不做功能巡礼、不写设计笔记。如果解释比代码长,就删掉解释——"每一段为简化辩护的散文,都是把复杂性换着形式走私回来"。
  4. 用户明确要求的解释(报告、走查、分阶段说明)不算债,完整给——这条规则只反对"未请求的散文"。

固定输出模式:

[code] → skipped: [X], add when [Y].

Intensity:lite / full / ultra 三级强度

级别 行为
lite 照需求构建,但用一行点出更懒的替代方案。用户来选。
full 强制七级阶梯。标准库与原生特性优先。最短 diff、最短解释。默认级别。
ultra YAGNI 极端主义。删除先于新增。交付一行版,并在同一句话里质疑需求其余部分。

文档用一个统一示例展示了三级面对同一需求("给这些 API 响应加个缓存")的不同反应:

  • lite:"Done, cache added. FYI: functools.lru_cache covers this in one line if you'd rather not own a cache class."
  • full:"@lru_cache(maxsize=1000) on the fetch function. Skipped custom cache class, add when lru_cache measurably falls short."
  • ultra:"No cache until a profiler says so. When it does: @lru_cache. A hand-rolled TTL cache class is a bug farm with a hit rate."

这个例子同时演示了两条底层规则:第 3 级横档(标准库优先)在 full/ultra 下如何落地,以及 ultra 级别"质疑需求本身"的姿态——注意 ultra 并没有拒绝任务,而是把"何时加缓存"推迟到"profiler 说需要",这正是第一级横档(YAGNI)的极端形态。

When NOT to be lazy:五条不可简化的安全底线

## When NOT to be lazy 一节是整套规则的刹车片,明确列出永远不许简化掉的东西:

  • 信任边界上的输入校验(input validation at trust boundaries);
  • 防止数据丢失的错误处理(error handling that prevents data loss);
  • 安全措施(security measures);
  • 可访问性基础项(accessibility basics);
  • 以及用户明确要求的任何东西。用户坚持要完整版本时,照做,不再争辩。

随后是两条更深的"反懒惰":

  1. 理解问题永远不懒。 阶梯缩短的是解法,不是阅读。先完整追踪一遍——改动触及的每个文件、真实的数据流——再选横档。"为了交付一个小 diff 而跳过理解"是危险的懒惰:它打扮成效率,交付一个自信的错误修复。
  2. 硬件永远不是纸面理想。 真实的时钟会漂移、真实传感器读数有偏差、PCA9685 会快几个百分点。留一个校准旋钮,而不只是更少的代码——物理世界需要调参,而最小模型看不到这一点。

最后一条是 Ponytail 独有的测试纪律:

Lazy code without its check is unfinished.(没有校验的懒惰代码是半成品。)

非平凡逻辑(一个分支、一个循环、一个解析器、涉及金钱/安全的路径)必须留下一个可运行的检查——"逻辑坏了它就会失败的最小东西":一个基于 assertdemo()/__main__ 自检,或一个小型 test_*.py。不要测试框架、不要 fixture、除非被要求否则不要每个函数一套用例。平凡的一行代码不需要测试——YAGNI 同样适用于测试

这条规则在 scripts/check-rule-copies.js 中以 "ONE runnable check""Lazy code without its check is unfinished" 两个 canary 短语被钉住,防止它在 SKILL.md 与 AGENTS.md 的同步中被悄悄改写。

Boundaries:Ponytail 管"做什么",不管"怎么说话"

## Boundaries 一节划清管辖范围:

  • Ponytail 约束的是你构建什么,不是你怎么说话(要极简话术请搭配 Caveman 模式);
  • "stop ponytail" / "normal mode" 立即还原;
  • 强度级别在会话结束或主动更改前持续生效。

规则集以一句话收尾:"The shortest path to done is the right path."(通往完成的最短路径,就是正确路径。)

生成与防漂移:这份 SKILL.md 是怎么来的

理解了规则内容之后,仓库里还有一套保证"这份文件永远与规范源一致"的机制,值得作为 Agent 技能工程化的范例来看。

生成:frontmatter 重写 + 正文逐字复制。 scripts/build-openclaw-skills.js 是生成器,其头部注释说明了设计意图:OpenClaw 技能格式与 Ponytail 已有的 SKILL.md 相同,唯一差别是 description 必须单行且短于 160 字符——规范源里的长描述是为 Claude 的技能选择器调优的,而 OpenClaw 侧要一份短描述。于是:

  • sourceBody(name) 读取 skills/<name>/SKILL.md,剥掉 frontmatter,返回正文原样
  • render(name)name: ponytail + 单行短描述 + homepage + license: MIT 拼装新 frontmatter,再拼上正文;
  • 生成结果写到 .openclaw/skills/<name>/SKILL.md

这解释了为什么本文开头的 frontmatter 描述("Lazy senior dev mode for any coding task (write, refactor, fix, review): YAGNI, stdlib first, no unrequested abstractions...")与规范源 skills/ponytail/SKILL.md 里那段长描述措辞不同——只有 frontmatter 被重写,正文逐字复制,规则集因此永不漂移

校验:三条测试钉死一致性。 tests/openclaw-skills.test.js 对六个技能逐一断言:

  1. 磁盘上的已提交副本与 render(name) 的输出逐字节相等(不等则提示 "stale — run: node scripts/build-openclaw-skills.js");
  2. 文件以规范源正文结尾(body is verbatim);
  3. 描述是单行且 ≤ 160 字符——这条同时呼应生成器里 desc.length > 160 || desc.includes('\n') 时的直接抛错。

版本与发布:跟随 package.json。 scripts/publish-openclaw-skills.js.openclaw/skills/ 下每个含 SKILL.md 的目录发布到 ClawHub。脚本读取目录而不是硬编码技能列表("covers whatever build-openclaw-skills emits, with nothing to keep in sync"),版本号取自根目录 package.jsonversion 字段,注释解释了原因:让 ClawHub 跟踪仓库而不是各自漂移——"the same drift that hit the plugin manifests in #260"。发布前需 clawhub login,且若改动过技能须先跑生成脚本,否则 CI 中的陈旧性测试会失败。

同一规则集的其他落地副本。 值得注意的是,Ponytail 的完整规则还有一版"紧凑体",以 AGENTS.md 为基准同步到 .cursor/rules/.windsurf/rules/.clinerules/.github/copilot-instructions.md 等多个 Agent 平台配置(scripts/check-rule-copies.js 维护这份清单并做逐字节比对)。而 SKILL.md 是"运行时事实来源"、比紧凑体更长,所以不做字节比对,只用 canary 短语断言关键规则存活于两侧——这正是本文前文多次引用的校验机制。

小结

.openclaw/skills/ponytail/SKILL.md 的价值不在某一个技巧,而在它把"少写代码"做成了一个可执行的决策程序:七级阶梯给出选择顺序,八条 Rules 划出禁止区,三级强度让用户控制执行力度,五条安全底线保证懒惰不越界,ponytail: 注释与"一个可运行检查"让简化可追踪、可验证;而生成器 + 漂移测试 + 不变量 canary 的组合,则保证了这套规则在 OpenClaw、ClawHub 与各 Agent 平台的每一份副本中永远一致。对维护 Agent 技能文件的开发者而言,后者同样是一份可以直接借鉴的工程模板。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
527
590
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
904
1.82 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
889
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.52 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
981
502
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384