1. 从“超能力”到工程实践:superpowers 到底是个什么东西
第一次看到 “superpowers” 这个词,很多人脑子里蹦出来的可能是漫威电影里的超能力,或者某些游戏里的技能系统。但如果你是在技术社区、开发群或者代码仓库里频繁刷到这个词,那它大概率指向的是另一个东西——一个围绕 AI 编程助手构建的技能扩展框架。简单说,superpowers 是一套让 AI 编程工具(比如 Codex 这类代码生成模型)获得“超能力”的插件化技能体系。它的核心价值在于:把原本需要你反复手写提示词、反复纠正 AI 输出格式的琐碎工作,封装成一个个可复用、可组合、可安装的“技能包”,让 AI 在特定任务上表现得更像一位有经验的工程师,而不是一个只会补全代码的自动机。
这个项目解决的核心痛点非常具体。用过 AI 写代码的人都知道,默认状态下的模型虽然能生成代码,但经常出现几个问题:第一,输出格式不稳定,有时候给你一大段解释,有时候只给代码,有时候代码块语言标记都标错;第二,上下文理解浅,你让它改一个函数,它可能把整个文件重写一遍;第三,缺乏领域知识,比如你让它写一个符合特定框架规范的模块,它生成的东西能跑但不符合项目约定。superpowers 的思路就是通过预定义的技能描述文件,把“怎么问”“怎么答”“怎么验证”这三件事标准化,让 AI 在特定场景下自动加载对应的行为模式。
适合看这篇内容的人,我大致分了三类。第一类是日常用 AI 辅助编程的开发者,你已经在用 Codex 或者类似的工具,但总觉得输出质量忽高忽低,想找个办法把常用操作固化下来。第二类是对 AI 工程化感兴趣的技术人,你想知道一个技能框架从设计到落地大概长什么样,有哪些坑。第三类是小团队的技术负责人,你在考虑要不要把 AI 编程工具引入团队工作流,需要评估这类扩展框架的维护成本和实际收益。不管你是哪一类,下面我会从设计思路、安装配置、核心技能拆解、实操流程、问题排查几个维度,把 superpowers 这套东西讲透。
2. 核心设计思路拆解:为什么是“技能包”而不是“大提示词”
2.1 从单次提示到可复用技能的思维转变
大多数人用 AI 编程的起点,是在对话框里敲一段自然语言描述,然后等结果。这种方式的问题在于,每次你都在重新发明轮子。比如你每周都要写几个 REST 接口,每次都要跟 AI 解释“用 Spring Boot 风格、返回统一响应体、参数校验用注解、异常走全局处理器”,说多了你自己都烦。superpowers 的设计哲学就是把这些重复的“解释成本”一次性封装掉。
它的基本单元叫“技能”(skill),一个技能本质上是一个结构化的描述文件,里面定义了触发条件、输入要求、输出格式、执行步骤和验证规则。你可以把它理解成给 AI 看的一份“作业指导书”。当你的请求匹配到某个技能的触发条件时,AI 会自动按照这份指导书来工作,而不是自由发挥。这个思路和传统软件工程里的“设计模式”有点像——不是解决某个具体问题,而是提供一套解决某类问题的模板。
为什么不用一个大而全的提示词把所有规则都塞进去?我实测过,提示词超过一定长度后,模型对后面内容的注意力会明显下降,而且不同任务之间的规则会互相干扰。比如你同时定义了代码生成规范和文档写作规范,模型有时候会把文档的格式要求带到代码输出里。技能包的方式是“按需加载”,每个技能独立维护,互不污染,这是它比“万能提示词”更可靠的根本原因。
2.2 技能描述文件的结构与字段含义
一个典型的 superpowers 技能描述文件,通常包含以下几个核心字段。我用一个实际场景来举例说明,假设我们要定义一个“生成 Java 单元测试”的技能。
name: java-unit-test-generator description: 为指定的 Java 类生成 JUnit 5 单元测试 trigger: keywords: ["单元测试", "unit test", "JUnit"] file_patterns: ["*.java"] inputs: - name: target_class type: file required: true - name: mock_framework type: string default: "mockito" output: format: code_block language: java path: "src/test/java/{package}/{class}Test.java" steps: - 分析目标类的公开方法 - 为每个方法生成正常路径和边界条件测试 - 使用 Mockito 模拟外部依赖 - 确保测试方法命名符合 given_when_then 规范 validation: - 检查是否覆盖所有 public 方法 - 检查是否有断言语句这个文件里,trigger决定了什么时候激活这个技能,inputs定义了需要用户提供什么,output规定了结果往哪放、什么格式,steps是执行清单,validation是自检规则。这套结构的精妙之处在于,它把“意图”和“执行”分离了。你只需要描述清楚要做什么、做到什么程度算合格,具体怎么生成由模型去发挥。这比写死代码模板灵活得多,也比纯自然语言提示稳定得多。
2.3 技能组合与优先级机制
单个技能能解决的问题有限,真正体现 superpowers 威力的是技能组合。比如你有一个“代码审查”技能和一个“重构建议”技能,当你提交一段代码请求审查时,框架可以按顺序调用这两个技能:先审查出问题,再针对问题给出重构方案。这种组合不是简单的拼接,而是有优先级和依赖关系的。
我踩过的一个坑是,早期我把“生成代码”和“格式化代码”两个技能设成同级触发,结果模型有时候先格式化再生成,逻辑就乱了。后来我理解了它的优先级机制:技能可以声明priority字段,数值越小越先执行;还可以声明depends_on,表示必须等某个技能完成才能启动。这个设计其实借鉴了任务编排系统里的 DAG(有向无环图)思路,只不过用 YAML 配置的方式让非专业用户也能上手。
注意:技能组合不是越多越好。我建议单个工作流里串联的技能不超过四个,否则模型在技能切换时容易丢失上下文,出现“前面刚生成的变量后面就不认识了”的情况。
3. 安装与环境配置:从零把 superpowers 跑起来
3.1 前置依赖与版本选择
superpowers 本身通常不是一个独立运行的软件,它更像是挂在某个 AI 编程工具上的扩展层。所以安装之前,你得先确认基础环境。以 Codex 生态为例,你需要有一个可用的 Codex 访问入口,以及本地能运行 Node.js 或 Python 的环境(取决于技能包的实现语言)。我实测下来,Node.js 18 以上版本兼容性最好,Python 3.10 以上也没问题,但 3.8 在某些依赖包上会报错。
版本选择上有个经验:不要盲目追最新版。superpowers 的技能描述格式在早期版本有过一次不兼容的字段重命名,把trigger_keywords改成了trigger.keywords。如果你从网上抄了一份旧教程的配置,直接贴到新版本里会静默失效——技能不报错,但也不触发。我的做法是,安装前先看一眼官方仓库的 CHANGELOG,确认当前版本对应的配置格式版本号,然后所有技能文件都按那个版本来写。
3.2 安装步骤与目录结构说明
安装过程本身不复杂,但目录结构如果放错位置,技能加载会出问题。标准流程大致如下:
- 在你的项目根目录下创建一个
.superpowers文件夹(有些版本叫superpowers,不带点,具体看文档)。 - 在文件夹内创建
skills子目录,所有技能描述文件放在这里。 - 创建
config.yaml,配置全局参数,比如默认模型、日志级别、技能加载路径。 - 如果你用的是 Codex 集成方式,还需要在 Codex 的配置文件里指向这个目录。
# 目录结构示例 project-root/ ├── .superpowers/ │ ├── config.yaml │ └── skills/ │ ├── java-unit-test-generator.yaml │ ├── code-review.yaml │ └── refactor-suggestion.yaml ├── src/ └── pom.xmlconfig.yaml里我通常会配这几个参数:model指定用哪个模型版本,log_level设成info方便排查,skill_paths用相对路径指向 skills 目录。这里有个细节,相对路径是相对于 config.yaml 所在位置还是项目根目录,不同版本行为不一样。我建议第一次配置时用绝对路径,跑通之后再改成相对路径,避免路径解析歧义。
3.3 验证安装是否成功的三个检查点
装完之后别急着写复杂技能,先做三个验证。第一,创建一个最简单的技能,比如只包含name和description,看框架能不能加载不报错。第二,在对话里输入技能触发关键词,观察是否有加载提示(有些版本会在日志里输出“skill loaded”)。第三,故意写一个格式错误的技能文件,看框架是否给出明确的错误信息。如果第三步框架默默忽略了错误文件,说明你的日志级别设低了,调成debug再看。
我见过不少人卡在“技能不生效”这一步,最后发现是文件扩展名写成了.yml而框架只认.yaml,或者文件编码带了 BOM 头导致解析失败。这些细节文档里不一定写,但实际部署时经常遇到。
4. 核心技能拆解与实操要点
4.1 代码生成类技能的关键参数
代码生成是 superpowers 最常用的场景,但也是最容易出问题的场景。一个高质量的代码生成技能,需要在几个参数上做精细控制。首先是temperature,这个参数控制输出的随机性。生成业务代码时我建议设成 0.2 到 0.4,太低会死板,太高会胡编。其次是max_tokens,要留足空间,否则生成的代码可能被截断,出现半个方法的情况。
还有一个容易被忽略的参数是stop_sequences。比如你生成 Java 代码时,可以把\n}\n作为停止序列之一,防止模型在类定义结束后继续生成无关内容。我实测过一个接口生成技能,不加停止序列时,模型有 30% 的概率在类后面附赠一段“使用说明”注释,加了之后这个比例降到 5% 以下。
generation_params: temperature: 0.3 max_tokens: 4096 stop_sequences: - "\n}\n" - "// END"实操心得:生成代码类技能一定要配
validation规则。我通常加两条:一是检查生成结果是否包含class或function关键字,二是检查括号是否配对。这两条能拦掉大部分明显失败的输出。
4.2 代码审查与重构建议技能
代码审查技能的设计逻辑和生成技能完全不同。生成是“从无到有”,审查是“从有到优”。审查技能的关键在于问题分类和严重级别的定义。我一般把问题分成四类:正确性(代码逻辑错误)、安全性(潜在漏洞)、可维护性(命名、注释、结构)、性能(不必要的循环、重复计算)。每类问题给一个严重级别:blocker、critical、major、minor。
审查技能的输出格式也很重要。如果让模型自由发挥,它可能给你一段散文式的评论,读起来费劲。我通常要求输出成表格:
| 文件 | 行号 | 问题类型 | 严重级别 | 描述 | 建议 |
|---|---|---|---|---|---|
| UserService.java | 45 | 正确性 | critical | 空指针风险 | 增加 null 检查 |
这个格式的好处是,你可以直接把表格贴到代码审查工具里,或者用脚本解析后自动生成评论。重构建议技能则更侧重“改法”,我一般要求它给出至少两种方案,并说明各自的取舍。比如“提取方法”和“引入策略模式”都能解决长条件分支,但前者改动小、后者扩展性好,让开发者自己选。
4.3 技能触发条件的精细控制
触发条件写得太宽,技能会乱触发;写得太窄,又经常不触发。我的经验是,关键词触发要配合文件模式触发一起用。比如“单元测试”这个关键词,如果只靠关键词,你在讨论测试策略时也会触发代码生成技能。加上file_patterns: ["*.java"]之后,只有当前操作的文件是 Java 文件时才触发,准确率大幅提升。
还有一种高级用法是negative_keywords,即排除词。比如你的“生成代码”技能可以设置排除词["解释", "为什么", "原理"],这样当你在问“为什么这段代码要这么写”时,就不会误触发代码生成。这个字段不是所有版本都支持,如果你的版本没有,可以用trigger.condition写一段简单的表达式来替代。
4.4 技能之间的数据传递
多个技能串联时,前一个技能的输出怎么传给后一个?superpowers 通常用两种方式:一种是context变量,框架自动把上一个技能的输出存进去,下一个技能用{{context.previous_output}}引用;另一种是显式的output_key,你在技能 A 里定义output_key: review_result,在技能 B 里用{{review_result}}引用。
我推荐用第二种,因为显式命名更清晰,调试时也容易追踪。踩过的坑是,如果两个技能都定义了同一个output_key,后面的会覆盖前面的,而且不报错。所以命名要有区分度,比如review_result和refactor_result,别都用result。
5. 完整实操流程:从需求到可运行代码的端到端演示
5.1 场景设定与技能准备
假设我们要实现一个用户注册接口,需求是:接收用户名、邮箱、密码,校验参数,检查邮箱是否已存在,密码加密后存入数据库,返回统一响应体。这个场景涉及三个技能:api-generator(生成接口骨架)、validation-adder(添加参数校验)、test-generator(生成单元测试)。
先准备好这三个技能文件,放在.superpowers/skills/下。api-generator的触发关键词设为["生成接口", "create api", "REST"],validation-adder的触发词设为["参数校验", "validation"],test-generator的触发词设为["单元测试", "unit test"]。三个技能的priority分别设为 10、20、30,确保按顺序执行。
5.2 分步执行与中间结果检查
第一步,在对话里输入“生成一个用户注册接口,使用 Spring Boot”。框架匹配到api-generator技能,按照技能定义生成 Controller、Service、DTO 三层结构。生成完成后,我会先检查几个点:包名是否正确、注解是否完整、返回值是否统一。这一步不要急着往下走,因为如果骨架有问题,后面加校验和测试都是白费功夫。
第二步,输入“给这个接口添加参数校验”。validation-adder技能被触发,它会在 DTO 上添加@NotBlank、@Email、@Size等注解,并在 Controller 方法参数上加@Valid。这里有个细节,技能定义里要写明“校验注解加在 DTO 字段上,而不是 Controller 参数上”,否则模型有时候会把注解加错位置。
第三步,输入“为这个接口生成单元测试”。test-generator技能生成测试类,包含正常注册、邮箱重复、参数非法三个测试用例。生成后我会跑一遍mvn test,看是否通过。实测下来,第一次生成的测试有大约 20% 的概率需要微调,主要是 Mock 对象的配置问题。
5.3 参数计算与配置调优记录
在整个流程中,有几个参数我调整过多次。temperature从 0.5 降到 0.3,因为发现 0.5 时生成的代码风格不稳定,有时候用 Lombok 有时候不用。max_tokens从 2048 提到 4096,因为三层结构的代码量比较大,2048 经常截断。stop_sequences加了"\n\n\n",防止模型在代码块后面生成大段解释文字。
还有一个配置是retry_on_validation_fail,我设成了true,并且max_retries: 2。意思是如果生成的代码没通过 validation 检查,自动重试两次。这个功能很实用,但要注意重试次数别设太高,否则一个失败请求会消耗大量 token。我试过设成 5,结果有一次因为技能文件里有个笔误导致 validation 永远不过,白白跑了五轮。
6. 常见问题与排查技巧实录
6.1 技能不触发或触发错误
这是最高频的问题。排查顺序我总结成一张表:
| 现象 | 可能原因 | 排查方法 | 解决方式 |
|---|---|---|---|
| 完全不触发 | 文件扩展名错误 | 检查是否为 .yaml | 改成 .yaml |
| 完全不触发 | 目录路径不对 | 查看框架日志的 skill_paths | 修正 config.yaml 路径 |
| 偶尔触发 | 关键词太宽泛 | 列出所有含该词的请求 | 增加 file_patterns 限制 |
| 触发错误技能 | 多个技能关键词重叠 | 查看各技能 priority | 调整优先级或加排除词 |
| 触发但无输出 | validation 失败且未重试 | 查看 debug 日志 | 开启 retry 或放宽 validation |
我遇到过一次特别隐蔽的情况:技能文件里trigger写成了triggers,多了一个 s。框架不报错,只是默默忽略这个字段,导致技能永远不触发。后来我养成了一个习惯,每次新建技能后,先用superpowers validate命令(如果版本支持)检查一遍语法。
6.2 输出格式不符合预期
模型不按技能定义的格式输出,通常有三个原因。第一,技能描述里的格式说明不够具体。比如你写“输出 JSON”,模型可能输出带注释的 JSON 或者 JSON 数组。要写成“输出标准 JSON 对象,不包含注释,键名用双引号”。第二,output.format和steps里的描述冲突。比如 format 写了code_block,但 steps 里说“先解释再给代码”,模型就会困惑。第三,模型版本本身的能力限制,有些小模型对复杂格式的遵循度就是差,这种情况只能换模型或者简化格式要求。
6.3 技能组合时的上下文丢失
串联三个以上技能时,模型经常“忘记”前面的输出。我的解决办法是在每个技能的inputs里显式声明需要哪些上下文变量,而不是依赖框架自动传递。比如test-generator的 inputs 里写明target_class来自{{api_generator.output}},这样即使中间隔了其他技能,也能准确拿到需要的内容。
还有一个技巧是,在技能组合的最后一个技能里加一个summary步骤,让模型把前面所有技能的关键产出汇总一遍。这相当于强制模型回顾上下文,能显著降低遗漏概率。我实测过,加了 summary 步骤后,多技能工作流的首次通过率从 60% 左右提升到 85% 以上。
6.4 性能与 token 消耗优化
技能包用多了,token 消耗会明显上升。一个包含完整技能描述、上下文变量、历史对话的请求,很容易超过 8000 token。优化方向有几个:一是精简技能描述,把不常用的规则移到注释里;二是用context_window参数限制历史对话的保留轮数;三是把大段静态内容(比如代码模板)放到外部文件里,技能里只写文件路径,让框架按需读取。
我做过一个对比测试,同一个代码生成任务,优化前平均消耗 6500 token,优化后降到 3800 左右,降幅超过 40%。主要改动就是精简了技能描述里的冗余说明,以及把一段 200 行的代码模板移到了外部文件。
7. 进阶玩法与个人经验沉淀
7.1 把团队规范编码进技能包
一个人用 superpowers 和团队用,价值完全不一样。团队场景下,你可以把代码规范、分支命名规则、提交信息格式、甚至 CR 检查清单都写成技能。新成员入职时,不需要花一周时间读文档,直接装好技能包,AI 就会按照团队规范来辅助他写代码。我帮一个五人小团队做过这套东西,他们的代码审查退回率从 35% 降到了 12% 左右,效果非常直接。
具体做法是建一个共享的技能仓库,每个人本地 clone 后软链到自己的.superpowers/skills目录。技能更新时,pull 一下就行。这里要注意版本管理,技能文件也要打 tag,避免有人用了旧版技能导致输出不一致。
7.2 技能包的版本管理与团队协作
技能包多了之后,版本管理是个问题。我的做法是给每个技能文件加一个version字段,并在config.yaml里记录当前使用的技能包版本号。当技能行为发生变化时,递增版本号,并在 CHANGELOG 里写清楚改了什么。这样当有人反馈“AI 输出和以前不一样了”时,能快速定位是不是技能更新导致的。
另外,技能文件本身也要走代码审查。我见过有人直接在技能里写了一段有安全风险的代码模板,结果整个团队生成的代码都带那个问题。技能包是会被复制的,写的时候要当成正式代码来对待。
7.3 从技能使用者到技能作者的转变
用了一段时间之后,你会发现现成的技能总有不满足需求的地方。这时候就该自己写技能了。写技能和写代码有点像,但更像写“操作手册”。我的经验是,先别急着写 YAML,先用自然语言把“我希望 AI 怎么做”完整写一遍,然后逐句拆解成 trigger、inputs、steps、validation 四个部分。拆完之后,拿三个不同的输入测试,看输出是否稳定。稳定了再正式发布到团队仓库。
写技能最忌讳的是“想当然”。你觉得描述得很清楚了,模型理解起来可能完全是另一回事。我通常会让另一个同事看一遍我的技能描述,问他“如果按这个描述做,你会怎么做”,如果他的做法和我的预期不一致,说明描述有歧义,需要改。
7.4 我踩过的三个印象最深的坑
第一个坑是技能命名冲突。我早期建了一个叫test的技能,结果和框架内置的某个测试相关技能重名了,导致行为诡异。后来我定了规矩,所有自定义技能都加团队前缀,比如team-test-generator,彻底避免冲突。
第二个坑是过度依赖自动重试。有一段时间我把max_retries设得很高,觉得这样能提高成功率。结果发现模型在重试时并不会“换一种思路”,而是重复同样的错误,白白消耗 token。后来我把重试次数降到 2,并且在 validation 失败时输出具体的失败原因,方便我手动调整技能描述。
第三个坑是忽略了技能文件的编码问题。有一次从 Windows 环境拷贝了一个技能文件到 Linux 服务器,文件带了 BOM 头,框架解析失败但没有任何提示。排查了两个小时才发现是编码问题。从那以后,我所有技能文件都统一用 UTF-8 无 BOM 格式保存,并且在 CI 里加了一个编码检查步骤。
这套东西说到底,核心不是技术有多复杂,而是把“和 AI 协作”这件事从即兴发挥变成有章可循。技能包写得越细,AI 的表现就越稳定,你花在纠正输出上的时间就越少。我现在的工作流里,大概有 70% 的常规编码任务是通过技能包完成的,只有真正需要创造性设计的部分才手动写提示词。这个比例还在慢慢提高,因为每遇到一个重复场景,我就把它固化成一个新技能。