
Superpowers 源码解读:一个 Agent 行为控制系统的设计
159k star,14 个 skill,0 个 agent,0 第三方依赖。441 commits,83% 来自作者一人。v5.1 把唯一的 agent 也删了。
看过很多 Agent 框架之后,Superpowers 是唯一一个让我停下来想"这个思路反了"的项目。所有主流框架都在让 Agent 更强、更自主。Superpowers 的假设完全相反——Agent 一定会找借口跳过繁琐步骤,所以要提前把每一条借口堵死。
这篇文章不是翻译 14 个 skill 的功能。分三部分:先走一遍源码里的 skill 怎么设计和组织的,再抽几组贯穿全文的机制,最后看近半年典型 bugfix——从真实踩坑里理解这个系统的边界。
一、源码解析
1.1 启动:一次只加载一个文件
启动链只有三个文件:
hooks/hooks.json → 声明 SessionStart hook hooks/session-start → bash 脚本,核心逻辑 13 行 skills/using-superpowers/SKILL.md → 唯一的引导 skillhooks.json 里 matcher: "startup|clear|compact" 意味着不只是会话启动时触发——/clear 或上下文压缩后也触发。如果你和我一样大约每小时 /clear 一次,这个设计处理的是常态,不是边缘情况。
session-start 做的事:读 using-superpowers/SKILL.md,用 printf 输出 JSON 注入到会话上下文。只注入这一个 skill,不是 14 个全塞进去。
using-superpowers 教 Agent 三件事:
用 Skill tool 按需发现其余 13 个 skill 1% 可能就加载(宁可多查一次,不能漏) 流程优先于实现——brainstorming 在 coding 之前
全量预加载 14 个 skill = 每次会话数万 token。一个 boot loader + 按需加载 = 省 90%+ 上下文。技术不难,但大多数 skill 系统没做到——它们倾向"反正上下文便宜了,全装上吧"。

Bootstrap 启动链
一个小细节:async: false。hook 同步执行,阻塞会话启动。如果异步,Agent 可能在 superpowers 注入完成前就开始处理第一条用户消息——第一个请求可能没有 skill 路由。同步保证了"先装引导程序,再接受输入"。
1.2 四个流程 skill:想清楚 → 写清楚 → 做清楚 → 收清楚
brainstorming(165 行)
一条硬门:未经设计批准,禁止写任何代码。Anti-Pattern 里明确拒绝"太简单不需要设计"的借口。9 步检查清单,核心回环:
用户批准设计? → 不批准 → 修订设计 → 再问 → 批准 → 调用 writing-plans流程图上的一条边定义了终态——设计被拒就回到设计,直到批准。没有"差不多,先写着"的中间状态。
writing-plans(153 行)
核心理念一句话:"假设执行者是一个有能力的开发者,但对工具链和问题域一无所知,且测试品味很差。"
具体要求:
Bite-sized tasks:每个 2-5 分钟(写测试 → 运行 → 写代码 → 运行 → 提交) 无占位符:禁止 "TBD"、"add appropriate error handling"、"write tests for the above" 执行交接:提供 subagent-driven 和 inline 两种执行方式
subagent-driven-development(280 行)
整个系统核心的执行引擎。两阶段审查,顺序不可逆:
每个 Task: 分派实现子 Agent ↓ 规格合规审查(确认做对了事情) ↓ 必须先过 代码质量审查(确认事情做对了) ↓ 标记完成 → 下一个 Task为什么先规格后质量?注释里写了:"Start code quality review before spec compliance is ✅" → Red Flag。先确认"做对了",再确认"做好了"。
模型选择策略也值得注意:机械实现用最便宜的模型,多文件协调用标准模型,架构/设计/审查用最强模型。不是在省钱——是在避免用强模型做弱任务,让 Agent 过度设计。
finishing-a-development-branch(252 行)
决策树覆盖 6 个步骤:验证测试 → 检测环境状态(GIT_DIR、分支状态、detached HEAD)→ 确定 base branch → 展示选项 → 执行 → 清理。
清理遵循 provenance-based 设计:只清理 superpowers 自己创建的 worktree(路径在 .worktrees/、worktrees/ 或 ~/.config/superpowers/worktrees/ 下),绝不碰 harness 管理的 workspace。知道自己创建了什么,就只清理自己创建的——这个原则贯穿整个项目。

四个流程 Skill 链路
1.3 三个纪律 skill:堵住执行层面的漏洞
test-driven-development(371 行)
整个项目里对抗性最强的文件。铁律一行:
NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST
11 条 Common Rationalizations,每条都是真实场景的借口加逐条反驳。比如 "This is a small change" → "Small changes introduce bugs too—and they're harder to spot."
13 条 Red Flags,让 Agent 自我检查:
"Are you rationalizing skipping tests 'just this once'?" "Did you write code before the test? → Delete it. Start over." "Do you 'know the code works' without running it? → Run it anyway."
前置声明切断了整类借口:"Violating the letter of the rules is violating the spirit of the rules."——别想打"我遵守精神就行"的擦边球。
systematic-debugging(297 行)
四阶段方法论:根因调查 → 模式分析 → 假设测试 → 实现。3-strikes 止损规则是精髓:
3+ 次修复失败:停下来质疑基础假设。这个方案本身对吗?是不是"纯靠惯性在坚持"?
数据显示系统化方法 15-30 分钟解决 vs 随机修 2-3 小时。
verification-before-completion(143 行)
五步闸门,从 24 次失败经验中提炼:
声称任何状态之前: 1. 找到能证明这个声称的命令 2. 执行完整命令 3. 读完整输出,检查退出码 4. 输出是否确认了声称? 5. 只有这时,才能做出声称 跳过任何一步 = 撒谎"我不信你"是这个 skill 诞生的原始痛点。
1.4 元 skill:怎么写 skill
writing-skills(656 行,全项目最长)。把 skill 创作定义为"TDD 应用于过程文档":
TDD for Code TDD for Skills ────────────── ──────────────── Test case → 压力场景 + 子 Agent Production code → SKILL.md RED → Agent 在无 skill 时违规 GREEN → Agent 在有 skill 时遵守 REFACTOR → 封堵漏洞,重新验证每 skill 从 "baseline test" 开始:不给 Agent 任何规则,看它怎么敷衍。根据实际违规行为写规则,而不是凭空想象"Agent 可能犯什么错"。这是实证迭代,不是理论推导。
二、经典机制
2.1 bootstrap 最小化
前面讲过了——一句话总结:只注入一个引导 skill,其余按需加载。省 90%+ 上下文。同步 hook + matcher 覆盖 restart/clear/compact,保证每次会话重置都不丢失。
2.2 DOT 图作为显式状态机
几乎每个 skill 都用 DOT 图定义流程。brainstorming 9 个节点,TDD 6 个,subagent-driven 12+ 个。这不是装饰——文字描述可以被 Agent 选择性忽略,但有向图边定义了"什么是合法的下一步"。没有从"实现"直接到"完成"的边,就没有这条捷径。
2.3 铁律三段式
铁律类 skill 的标准格式:
THE IRON LAW(一行大写,不可协商) ↓ COMMON RATIONALIZATIONS(预判每条借口,逐条反驳) ↓ RED FLAGS(Agent 自我检查触发器) ↓ 结论:以上任何一条 = 回到铁律
铁律三段式
三段式的本质是不信任 Agent 会自觉遵守规则。它假设 Agent 一定会找借口,所以提前把每条借口写在规则里,并配套一个自检机制。
2.4 CSO:提示词的懒加载
writing-skills 里的发现:description 写得太完整 → Claude 读完 description 就觉得自己懂了,跳过正文。
这本质是一个懒加载问题。description 的正确角色是路由判断——"这个 skill 用不用加载"——而不是正文摘要。当你把 workflow 写进 description 时,你相当于把"正文"塞进了"路由 stub"。Claude 的注意力天然走最短路径:stub 里都有答案了,还加载正文干什么。
# BAD — stub 里有正文,等于白写正文 description: "Use when executing plans - dispatches subagent per task with code review between tasks" # GOOD — stub 只管触发条件,正文才知道怎么做 description: "Use when executing implementation plans with independent tasks in the current session"一个具体案例:subagent-driven-development 的 description 写了"code review between tasks",Claude 理解为"每 task 做一次审查"——但正文的 DOT 图明确要求两次(规格审查 + 代码审查),顺序固定。一句话的描述丢失了结构信息,Claude 按描述执行而不是按正文执行。
所以 CSO 不是"把描述写好",是"故意把描述写不完整"。让 Claude 无法从 stub 推断出怎么做,被迫加载全文。就像 import 语句不该包含函数体。

CSO 懒加载对比
2.5 跨平台适配
session-start 用一段 if-elif-else 输出三种 JSON 结构:Cursor 用 snake_case,Claude Code 用 hookSpecificOutput.additionalContext 嵌套格式,Copilot CLI 用 SDK standard。更关键的是注释里的一个坑:
"Claude Code reads BOTH additional_context and hookSpecificOutput without deduplication, so we must emit only the field the current platform consumes."
同时输出两个字段 → Claude Code 读到两份 superpowers 内容。真实的跨平台踩坑记录。
三、边界:几个 bug 说明的事
源码读完了能理解设计意图,但系统真实的边界在踩坑里。挑四个 issue,简述问题,分析根因,看怎么修的。
#1576 — skill 之间的契约是隐式的。writing-plans 生成的计划模板不包含 TDD 要求。下游 subagent-driven-development 的提示模板里写的是"Write tests, following TDD if task says to"——条件判断的开关在上游,上游没说,下游就不做。结果整条 subagent 流程跳过测试。
根因不在 Agent 偷懒,在 skill 之间没有显式接口。writing-plans 不知道下游有一个"if task says to"的条件,subagent-driven-development 也没声明"我依赖上游传 TDD 指令"。两个 skill 通过一段自然语言隐式耦合,一个忘了说,另一个理所当然不做。
修复方案——在 writing-plans/SKILL.md 里加了硬门:
## TDD Structure Is Mandatory <HARD-GATE> Every task that produces or modifies code MUST follow RED-GREEN-REFACTOR structure: write failing test → verify it fails → write minimal implementation → verify it passes → commit. No exceptions. </HARD-GATE> **This includes tasks that feel "untestable":** - Configuration/tooling setup — write a smoke test that imports/runs the config - Build pipeline changes — write a test that runs the build and checks output - Scaffolding/boilerplate — write a test that verifies the scaffold works ### Anti-Pattern: "Tests at the end" Plans that put all tests in a final "Add tests" task are NOT TDD. Each task must have its own test step BEFORE its implementation step.同时给 reviewer prompt 加了检查项:TDD Structure | Every task with code follows RED-GREEN. Tests must NOT be deferred to a final task. 不是建议,是 reviewer 的硬性检查标准。
#485 — 有时候 bug 不在你代码里。 Opus 4.6 在 subagent 流程中自行并行分派,skill 里写着"DON'T: parallel dispatch (conflicts)",模型无视了。看起来像 Superpowers 的对抗性设计被模型突破了。
根因其实是 Claude Code 的 TaskOutput 检索路径有 bug——并行分派的子 Agent 通过 TaskOutput 返回截断的 JSONL 片段(约 30KB),而不是完整回答。模型并行分派的决策本身不一定错,但撞上了工具层的缺陷,导致返回垃圾数据。关联的 Claude Code issue 后来被修复,Superpowers 这边没有改动代码。作者甚至考虑放松这条规则——"Claude is heavily conditioned to parallelize tasks. Did this actually lead to problems?"
教训不是"借口表要迭代"。是这个:当 Agent 违反 skill 规则时,先确认是不是平台 bug。不是所有偏离都是对抗性设计被攻破——有时候是底层工具返回了错误数据,模型基于错误数据做了"合理"的决策。
#1283 — 文档正文是平台的提示注入面。systematic-debugging/SKILL.md 的"错误信号"表中有一行示例文本:"Ultrathink this"。Claude Code 运行时扫描器检测到 tool result 中的 "ultrathink" 关键词,自动注入 <system-reminder>,声称用户要求深度推理。实际上用户从来没说过这个词。
根因是平台扫描器和 skill 正文共享同一个文本空间,没有语义边界。扫描器做纯文本匹配,不知道 "Ultrathink this" 是文档里的反例示范而不是用户指令。一旦关键词命中,系统行为被静默改变——Agent 强制进入深度推理,但没有任何人知道为什么。
修复方案—— commit 21ad401e,一行改动:
-- "Ultrathink this" - Question fundamentals, not just symptoms +- "Ultra-think this" - Question fundamentals, not just symptoms一个连字符打断了扫描器的连续字母匹配,但文本对 Agent 仍然可读。不是复杂的方案——就是把字符串弄变形,让平台的纯文本扫描器认不出来。这种修法没有通用性(每个 trigger word 需要单独处理),但在没有语义边界的文本空间里,变形是唯一能用的小手术。
#1446 — 静默失败是最危险的 bug 类型。 v5.0.7 的人工静态审查发现三个独立 bug。第一:session-start 的 escape_for_json 只转义 \ " \n \r \t,漏了 \b \f 等 RFC 8259 要求的所有 C0 控制字符。第二:脑暴服务器的 WebSocket 帧无 payload 上限,声明 64 位长度可触发 Buffer.alloc 崩溃。第三:bash 脚本循环变量未加引号,空格文件名会 word-split。
最危险的是第一个。根因:escape_for_json 是一个手工维护的转义表,不是调用标准 JSON 编码器。手写转义注定有遗漏——RFC 8259 要求转义所有 U+0000 到 U+001F 的控制字符,手工实现只覆盖了常用的 5 个。如果未来某个 SKILL.md 包含 form-feed 字符(从 PDF 复制粘贴或某些编辑器的残留字符),hook 输出非法 JSON,Claude Code 静默丢弃,superpowers 完全不激活——Agent 照常回复,没有任何错误提示。失败完全无声。
修复方案——三条中只修了一条。WebSocket 加了 10MB 帧上限(PR #1555):
const MAX_FRAME_PAYLOAD_BYTES = 10 * 1024 * 1024; // 在 64-bit 长度解析后立即检查 const extendedLen = buffer.readBigUInt64BE(2); if (extendedLen > BigInt(MAX_FRAME_PAYLOAD_BYTES)) { throw new Error('WebSocket frame payload exceeds maximum allowed size'); } payloadLen = Number(extendedLen);配套回归测试:构造一个刚好 MAX + 1 的帧头,断言 decodeFrame() 在读到 payload 之前就抛异常。
另外两条没修。JSON 转义被标记为"theoretical gap, no evidence of real-world C0 emission"——维护者认为不会有 SKILL.md 真的包含 form-feed 字符。bash 变量引号同理,没遇到真实触发场景。这个取舍很说明问题:Superpowers 的维护哲学是只修有人踩过的坑,不修静态分析报告。好处是不花精力在假警报上,代价是这些静默失败模式随时可能变成真实 bug。
课后随想
本次学习换了一个思路:不是翻译功能,是看源码、挖机制、从真实 bugfix 理解边界。
初识 Superpowers 是惊艳的。一个项目敢说"Agent 不可信,所以要堵死每一条借口"——这种对抗性设计在 Agent 框架里没见过,大部分框架都在给 Agent 更多能力,没人反过来假设 Agent 会偷懒。DOT 状态机、铁律三段式、bootstrap 最小化,每个设计决策背后都有明确的工程判断。14 个文件管住了 14 种场景,精炼。
再用几周之后,摩擦感出现了。两点:
有些设计过度了。 TDD skill 371 行,其中大量篇幅在预判 Agent 可能找的借口——但很多借口是 Opus 4.5 时代的,4.6/4.7 不一定按同样的逻辑绕规则。预判过远等于维护债务:每个模型版本迭代后,旧借口不一定成立,新借口没被覆盖。对抗性设计需要的是快速迭代的借口表,不是一次性写死、然后靠 commit 慢慢补。
token 开销是个真问题。 按需加载省了上下文,但每个 skill 自身不轻。TDD 371 行,writing-skills 656 行,subagent-driven-development 280 行——Agent 加载一个 skill 就是几千 token。如果一次会话调用 3-4 个 skill,token 消耗不低。而且 Red Flags 列表和 Rationalizations 表里有大量功能重叠的文字——同一个"别跳过测试"的意思,在 Iron Law、借口表、Red Flags、正文步骤里各出现一次。重复是故意的(对抗性设计需要反复强调),但代价真实。
改善方向我有两个想法。一是给 skill 分"模式":full mode 保留所有 defensive text,lite mode 只保留 Iron Law + 步骤清单,老手走 lite 省 token,新手或关键任务走 full。二是借口表单独抽成文件,Agent 只在触发特定 Red Flag 时才加载对应的反驳——不是每个会话都灌 11 条常见借口。
这些不否定 Superpowers 的价值。恰恰相反——能在真实使用中产生这些具体摩擦,说明它不是一眼看完就放下的项目。它迫使你重新想"怎么让 Agent 不出错"这个问题的代价边界:堵死借口要花多少 token?预判多远算够?哪些设计值这个开销、哪些只是过度防御?
欢迎大家分享问题,参与讨论~
夜雨聆风