同名不同物:pi、ECC、superpowers 三个项目对技能机制的三种设计取向

2026-07-29

本文基于三个仓库的以下版本梳理:pi commit 027a584、ECC commit 591ab5c、superpowers commit 44c9b2d(均为 2026-07 下旬)。三个项目都在持续迭代,具体行为以各自仓库最新代码与文档为准。

你在三个项目的文档里看到的「技能」,是三个不同层次的东西:pi 谈的是加载器该从哪些路径发现文件、什么时候把内容塞进上下文;ECC 谈的是怎么把领域知识切成够窄的模块以便命中;superpowers 谈的是怎么写一段让模型在压力下也不敢绕过去的文字。 这三件事互不替代。你如果拿 ECC 的写法去满足 superpowers 的目标,会得到一篇模型读完照样不执行的漂亮文档;反过来拿 superpowers 的强度去写两百多个领域知识模块,写不动也没必要。

站内已有的 Claude Code Skills 是什么MCP 扩展框架怎么选 讲的是这类机制的通用方法论——一个技能应该长什么样、扩展该走哪条协议。本篇不重复那层,只做一件事:把三个真实开源仓库摊开,看它们各自把这套方法论落到了什么具体形态上,路径、字段、约束都可以当场打开核对。

一、三个项目各自在回答哪个问题

先给全貌,再逐个展开。

对照维度piECCsuperpowers依据文件
技能的定位按需加载的自包含能力包,含工作流、安装说明、辅助脚本、参考文档知识模块,被动的领域知识,Claude Code 按上下文引用已验证技法的参考指南,明确不是「我某次怎么解决问题」的叙事三份主文档开头的定义段
数量级文档不预设数量,靠外部技能仓库补skills/ 下 281 个技能目录skills/ 下 14 个技能目录各仓库 skills/ 目录清点
发现来源全局目录、项目目录、npm 包、settings、CLI 参数五类安装器把技能拷进运行时的技能目录按各 harness 的插件/同步方式安装pi docs/skills.md 的 Locations 一节
进上下文的时机启动只注入 name 与 description,正文靠模型自己 read上下文匹配时自动激活入口技能强制要求「有 1% 可能相关就必须调用」superpowers skills/using-superpowers/SKILL.md
frontmatter 必填namedescriptionnamedescriptionnamedescription三份文档的字段表
特有字段allowed-toolsdisable-model-invocationcompatibilitylicensemetadataorigintagsversion只用两个必填字段,其余按规范pi 文档 Frontmatter 表 / ECC 指南 YAML 表
篇幅取向未规定,结构自由典型 200-500 行,上限 800 行常规技能瞄准 500 词以内,高频加载的 200 词以内ECC 指南 Content Guidelines / superpowers SDO 第 4 节
质量把关方式加载期校验,多数问题只告警提交前的检查清单加代码示例编译验证用压力场景跑基线,写完再跑一遍看是否合规ECC 指南 Testing / superpowers RED-GREEN-REFACTOR

这张表里每一行的分歧,都能追到各自项目要解决的那个具体麻烦。下面拆开讲。

二、pi:技能首先是一个加载器问题

pi 的这份文档花了大量篇幅在「文件从哪儿来」。它列出的加载来源有五类:全局的 ~/.pi/agent/skills/~/.agents/skills/;项目级的 .pi/skills/.agents/skills/(后者会沿 cwd 往上一直找到 git 仓库根,不在仓库里则到文件系统根);npm 包里的 skills/ 目录或 package.json 中的 pi.skills 条目;settings 里的 skills 数组;以及命令行的 --skill <path>

有两个细节值得你留意。项目级的那两个位置,文档写明只在项目被信任之后才加载——这不是随口一提,源码里 packages/coding-agent/src/core/ 下就有 project-trust.tstrust-manager.ts 与之对应。文档同一节还挂了一条安全提示:技能可以指示模型执行任何动作,也可能包含模型会去调用的可执行代码,用之前先审内容。这个提醒是有分量的,因为技能目录来自 npm 包这条路径意味着你 npm install 一个依赖,就可能顺带引入一段会进系统提示的文字。

另一个细节是 --skill 的行为:文档说它可重复,并且「即使配了 --no-skills 也仍然叠加」。也就是关闭自动发现之后,显式指定的技能照样加载。这个设计对排错很实用——怀疑某个技能在捣乱时,可以一把关掉发现、只留下你要验证的那一个。

发现规则本身也有不对称之处:在 ~/.pi/agent/skills/.pi/skills/ 里,直接放在根下的 .md 单文件会被当成独立技能;而在 ~/.agents/skills/ 和项目的 .agents/skills/ 里,根下的 .md 文件会被忽略。所有位置里,含 SKILL.md 的目录都会被递归发现。这个区分不是随意的:.agents/skills/ 是跨运行时共享的约定位置,pi 不去认领别人目录里的散装文件。

跨 harness 复用这件事,pi 给的是一段配置:

{
  "skills": [
    "~/.claude/skills",
    "~/.codex/skills"
  ]
}

相应地,它在规范符合度上主动放宽了一条。文档明说 pi 实现的是 Agent Skills 标准,但允许技能的 name 与所在父目录不同名,理由写得很直白:标准里那条「必须同名」的要求,对被多个 agent 运行环境共用的技能目录来说是不合适的。校验策略也偏宽松——名称超长、含非法字符、首尾或连续连字符、描述超长,这些都只产生告警但技能照样加载;唯一的硬性例外是缺 description 的技能不加载。同名冲突则告警并保留先发现的那一个。

至于正文什么时候进上下文,pi 的说法是分级披露:启动时扫描各位置,只抽出名称和描述放进系统提示,完整的 SKILL.md 要靠模型在任务匹配时自己用 read 去读。文档还老实交代了这套机制的软肋——「模型不总是会这么做」,所以提供了 /skill:name 这种斜杠命令来强制加载,命令后面跟的参数会以 User: <args> 的形式追加到技能内容后面。这条自陈很关键,它正好是下一节 superpowers 那套强硬措辞想要解决的问题。

三、ECC:技能是一座要靠命中率吃饭的工作流库

ECC 的这份指南开篇就把技能和别的东西划清了:技能是知识模块,是被动知识,靠上下文自动激活;agent 是任务执行器,靠显式委派;命令是用户动作,靠 /command 触发;钩子靠事件触发;规则一直生效。这五分法在仓库结构上是能对上的——顶层同时存在 agents/commands/hooks/rules/skills/ 五个目录,其中 agents/ 下有 67 个 markdown 文件,skills/ 下有 281 个技能目录,rules/ 下则分成 22 个子目录,除公共的 commonweb 外,其余按语言和框架各占一格(pythonrustgolangreactvue 之类)。

规模一上来,问题就从「怎么写」变成「怎么让对的那个被选中」。指南给出的第一条建议是把焦点收窄,并且直接列了对照:react-hook-patterns 是好焦点,react 太宽;postgresql-indexing 好过 databasespytest-fixtures 好过 python-testingnextjs-app-router 好过 nextjs。这不是命名洁癖,是在 281 个候选里做区分度设计。

配套的是模板里那个被标为「关键」的段落——## When to Activate。指南要求它写得具体,给的示例是列出「创建新 React 组件 / 重构既有组件 / 调试 React 状态问题 / 按最佳实践评审 React 代码」这类具体场景,而不是抽象描述。除此之外,模板还固定了 Core Concepts、Code Examples、Anti-Patterns、Best Practices、Related Skills 几段。

内容写法上,指南反复强调「展示而非陈述」:不要写「异步函数里要正确处理错误」,要直接给出带 try/catch、检查 response.ok、再抛出友好错误的完整代码,后面附「关键点」小结。它同样要求写反模式,用直接改对象属性对比展开出新对象的写法说明什么不该做。还有检查清单和决策树两种形态,都是为了让模型读完能立刻照做。

篇幅上 ECC 给了明确区间:典型 200 到 500 行,最多 800 行。代码块要带语言标识,标题用 ##### 分层,对照信息用表格。

验证环节偏工程化。指南要求本地把技能拷到运行时的技能目录里实测激活,然后走一份检查清单:YAML 无语法错误、名称是小写连字符、描述说清何时使用、示例代码能编译能跑、关联技能的链接有效、不含 API key 与令牌之类的敏感数据。示例代码的验证给了具体命令,TypeScript 用 npx tsc --noEmit,Python 用 python -m py_compile,Go 用 go build

这里有个你抄的时候一定会碰上的偏差:指南的 YAML 字段表把 origin 写成顶层字段,但仓库里 281 个技能中,把 origin: ECC 放在 metadata: 下面的有 201 个,把 origin 写成顶层字段的只有 7 个。比如 skills/security-review/SKILL.md 的头部是这样:

---
name: security-review
description: Use this skill when adding authentication, handling user input, working with secrets, creating API endpoints, or implementing payment/sensitive features. Provides comprehensive security checklist and patterns.
metadata:
  origin: ECC
---

另外还有 3 个技能用了指南里完全没提的 argument-hint 字段,skills/tdd-workflow/SKILL.md 就是其中之一。以仓库里的实际文件为准,比以文档为准更保险。

顺带一提,tdd-workflow 那篇里有一段值得单独看:它要求把用户给的 *.plan.md 当作不可信的输入来读,计划文件的内容是数据不是指令,里面出现「忽略先前规则」「跳过校验」这类文字要作为计划内容记录下来而不是照做,嵌在计划里的命令在经过清洗与用户批准之前不得执行。这属于把提示注入的防线写进了工作流本身,和 Agent 提示注入怎么防 是同一类思路。

四、superpowers:技能是要能顶住合理化的纪律文本

superpowers 只有 14 个技能目录,但每一篇的目标跟前两者不一样。skills/writing-skills/SKILL.md 第一句话就把方法论摆出来了:写技能就是把测试驱动开发用到流程文档上。对应关系它列成了一张表——压力场景等于测试用例,SKILL.md 等于生产代码,没有技能时 agent 违反规则等于测试变红,有技能后 agent 合规等于测试变绿,堵漏洞等于重构。

核心原则写得没有回旋余地:如果你没亲眼看过 agent 在没有这个技能时怎么失败,你就不知道这个技能教的是不是对的东西。文档里那条「铁律」是全大写的一行——没有失败的测试就不许有技能,并且注明这条对新建技能和修改既有技能同样适用,紧跟着是一串堵口子的话:先写技能后测试?删掉,重来。不许留着当参考,不许边测边改,不许再看一眼,删就是删。

这种写法本身是有依据的。同一篇里有一节叫「让形式匹配失败类型」,把四类基线失败对应到四种该用的形式:明知故犯型的违纪,用禁令加合理化对照表加红旗清单;输出形状不对(提示词臃肿、结论被埋、复述规格),用正向配方,直接说输出由哪几部分按什么顺序组成;漏掉必填元素,用结构化手段,在模板里留一个标了 REQUIRED 的槽位;行为该随条件变化,用挂在可观察谓词上的条件句。

关键在于它给出了反例证据:在针对派发提示词措辞做的对照测试里,用禁令的那一组产出的不想要内容明显多于用配方的那一组,两组分布完全分开,而且禁令组在趋势上还不如不给任何指导的对照组。原文对这个结论的措辞是克制的:它只说「趋势上更差」,紧接着提醒读者去微测自己的场景而不要照搬结论,唯一的硬建议是「别把禁令当默认选项」。文档由此给出一条硬规矩——不许加「除非重要否则不要 X」这类留有余地的从句,因为给一个原本稳定的配方追加一条余地从句,会让它从稳定退化成飘忽;而豁免从句根本不起作用,「这条限制不适用于代码块」照样会把代码块压没。

描述字段那条规则同理,也是测出来的。规则本身是:description 只写触发条件,绝不概括技能的流程。原因写得很具体——有个描述写成「任务之间做代码评审」,结果 agent 照着描述只做了一次评审,而技能正文的流程图明确要求两次(先查规格符合度,再查代码质量);把描述改成不含流程概括的版本之后,agent 才真去读流程图并执行了两段式评审。文档管这叫陷阱:描述里一旦出现工作流摘要,就等于给了 agent 一条捷径,技能正文就变成没人看的文档。

它给的好坏对照是这样的:

# ❌ BAD: Summarizes workflow - agents may follow this instead of reading skill
description: Use when executing plans - dispatches subagent per task with code review between tasks

# ✅ GOOD: Just triggering conditions, no workflow summary
description: Use when executing implementation plans with independent tasks in the current session

token 效率被单列成一节,因为入门类技能会进入每一次会话。目标字数给到具体数:入门工作流每篇 150 词以内,高频加载的技能全篇 200 词以内,其他技能 500 词以内,并且给了验证方式就是 wc -w。省字数的手法包括把参数细节推给 --help、用交叉引用代替重复、压缩示例。交叉引用还有一条硬约束:引用别的技能只写技能名并加上 **REQUIRED SUB-SKILL:****REQUIRED BACKGROUND:** 这种明确标记,不许用 @ 语法,因为那会立刻把文件强制加载进来、在你还用不到它的时候就烧掉大量上下文。

这套强度在入口技能 skills/using-superpowers/SKILL.md 里体现得最直接。它在一个 <EXTREMELY-IMPORTANT> 块里写:只要你觉得有 1% 的可能某个技能适用于你在做的事,你就绝对必须调用它;如果一个技能适用于你的任务,你没有选择权。后面跟一句「你没法靠合理化绕出去」。再往下是一张红旗表,把「这只是个简单问题」「我得先了解点上下文」「我先看看代码库」「这个技能有点小题大做」这些念头逐条驳回。同一篇也留了让路条款:用户指令(CLAUDE.md、AGENTS.md 或直接要求)优先于技能,技能优先于默认行为。

这三份文件是同一套逻辑的三层:writing-skills 定义怎么写,using-superpowers 保证被读,而 writing-skills/ 目录下的 testing-skills-with-subagents.mdpersuasion-principles.mdanthropic-best-practices.mdgraphviz-conventions.dotrender-graphs.js 承接被主文件挪出去的重型内容——这正是它自己那条「重型参考和可复用工具才拆文件、原则概念和短代码保持内联」的规则在自己身上的应用。

五、边界与代价:各自放弃了什么

pi 这套的代价在于宽松。 校验大多只告警,同名冲突静默地保留先发现的那个,加上五类发现来源、其中一类还是 npm 包,你完全可能在不知情的情况下多出几个技能。文档自己挂的那条安全提示不是客套。分级披露也不是白拿的:只有描述常驻上下文,正文靠模型自觉去 read,文档明说模型不总会读——所以 pi 提供的是 /skill:name 这种人工兜底,而不是从措辞上逼模型就范。它没打算管你的技能内容写得好不好,那是另一层的事。

ECC 这套的代价在于规模本身。 281 个技能意味着描述之间的区分度是持续的维护成本,一个太宽的技能名会长期抢走别人的命中。指南要求写完就本地实测激活,但在这个量级上,逐个回归是件真活儿。文档和实际文件的字段偏差(顶层 originmetadata.origin)也说明大库存在漂移。另外它的技能定位是被动知识,激活靠上下文匹配,本身不带强制力——tdd-workflow 那种把纪律写进流程的篇目是例外而非通例。它明确不管的是运行时怎么发现技能,那是各 harness 的事,README 里为此写了一长串按 harness 分的安装方式。

superpowers 这套的代价最直白,而且它自己写在了正文里。 铁律要求你为每个技能先跑基线场景、记录 agent 逐字的合理化说辞,再写最小技能,再复跑验证,发现新说辞继续堵。这套流程会让写文档明显变慢。措辞微测那节更狠:每个变体要跑 5 次以上,每一处标红的命中要人工读一遍(因为模板回声和被引用的反例会伪装成命中),而且必须有一个不给任何指导的对照组——对照组要是根本没出现那个失败,就直接停手别写这段指导。这是相当高的启动成本,对一次性的小改动就是过度设计,指南自己也列了不该建技能的情形:一次性方案、别处已有充分文档的标准做法、项目专属约定(放进你的指令文件)、以及能用正则或校验器机械执行的约束(那就自动化,文档只留给需要判断的部分)。

还有一层代价是 token。using-superpowers 那种「1% 可能就必须调用」的强度,必然带来更多的技能加载和更啰嗦的自述过程;agent 会花额外的轮次宣布自己在用哪个技能、把清单展开成待办项。这在需要纪律的长任务上是划算的,在你只想改一行配置的时候就是纯开销。想量化这块开销,Agent 框架的 token 效率怎么比 里的口径可以直接用。

三者的适用面因此并不重叠:你在做运行时、要决定技能文件从哪些路径进来并怎么进上下文,pi 那份文档是直接可参照的;你在给一个多语言多框架的团队攒领域知识、要靠描述命中,ECC 的窄焦点与激活段落写法更对症;你要治的是 agent 明知规矩却在压力下绕过去,superpowers 的失败类型分类和堵漏洞手法是冲着这个来的。

六、上手与避坑清单

别把 pi 的 --no-skills 当成全关。 会踩是因为名字看着像总开关,但文档写明 --skill 指定的路径在 --no-skills 下仍然加载。避法:排错时正好利用这一点,--no-skills 关掉自动发现、只用 --skill 挂上你要验证的那一个,逐个二分定位是谁在污染上下文。

别在 .agents/skills/ 根下放散装 .md 就指望 pi 认。 会踩是因为 ~/.pi/agent/skills/.pi/skills/ 确实认根级单文件,人容易把这个规则外推。避法:跨运行时共享的目录一律用「一个目录一个 SKILL.md」的形态,这在三个项目里都成立。

别漏写 description 会踩是因为 pi 对绝大多数校验问题只告警、技能照常加载,你会误以为字段都是软要求。避法:记住文档标为 Exception 的那一条——缺描述的技能不加载,而且它不会以报错的形式打断你,只会安静地不出现。

别把 ECC 的技能名起得太宽。 会踩是因为写的时候只有自己那一个技能,react 这种名字显得干净利落。避法:照指南那张对照表的粒度收窄到 react-hook-patterns 这一级,并且把 When to Activate 写成具体动作场景,让它在几百个候选里有区分度。

别照 ECC 指南的字段表写 frontmatter 就完事。 会踩是因为文档把 origin 列为顶层字段,而仓库里绝大多数技能把它放在 metadata 下。避法:动手前先打开两三个同类既有技能的头部看实际写法,以文件为准;顺手也留意有没有 argument-hint 之类文档没覆盖的字段。

别在 superpowers 风格的 description 里概括流程。 会踩是因为把流程写进描述看起来是在帮 agent 省事。避法:只写触发条件、以 Use when 开头,工作流一个字都不放进去——文档记录的那个两段式评审被压成一次的案例,就是这么来的。

别用「除非…否则不要 X」这种留余地的措辞给已经生效的规则打补丁。 会踩是因为你想照顾一个真实存在的例外。避法:把例外写成挂在可观察条件上的独立条件句,而不是给原规则挂从句;文档还提醒豁免从句不会按你想的那样限定范围。

别在没跑对照组之前就动手写一段行为指导。 会踩是因为你已经预设 agent 会犯那个错。避法:先跑一遍不给指导的基线,确认失败真实存在再写;每个变体跑 5 次以上,标红的命中人工过一遍,别信自动计数。

别把三个项目的做法混着抄进同一个仓库。 会踩是因为三者的名字和 frontmatter 长得很像,看着可以拼装。避法:先想清楚你要解决的是发现与加载、还是知识命中、还是纪律执行;确定层次之后,字段、篇幅、验证方式整套照一个来源走。选型上的通用判断口径,Agent 框架怎么对比 里有更完整的展开。


给你一条现在就能用的自检:打开你自己的技能目录,随手挑一篇,问三个问题。第一,只看它的 description,你能判断出什么时候该加载它吗?判断不了,问题在 ECC 那一层的命中设计。第二,模型在真实会话里会不会主动去读它的正文?如果只能靠人工斜杠命令兜底,问题在 pi 那一层的加载路径与分级披露。第三,模型读了之后在赶时间的场景下会不会照做?会绕过去,问题在 superpowers 那一层的措辞形式。

三个问题对应三份文件,也就是接下来该读哪个:pi 的 packages/coding-agent/docs/skills.md、ECC 的 docs/SKILL-DEVELOPMENT-GUIDE.md、superpowers 的 skills/writing-skills/SKILL.md。三个仓库都以 MIT 许可证发布,地址分别是 https://github.com/earendil-works/pihttps://github.com/affaan-m/ECChttps://github.com/obra/superpowers ,本文提到的每一处路径和字段都可以拉下来当场核对。

文中三个项目各有中文专题:pi 开源编程 AgentECC 增强套件superpowers 方法论

想系统学会用 AI?报名体系课或加入会员,照着学、照着用。