1. 从“superpowers”这个热词说起:它到底是什么
第一次看到“superpowers”这个词挂在技术社区热搜上的时候,我下意识以为是某个新出的超级英雄题材游戏,点进去才发现,这其实是一个在开发者圈子里悄悄火起来的效率工具组合概念。简单来说,superpowers 是一套围绕 AI 编程助手(尤其是 Codex 这类工具)构建的增强能力集合,它把原本零散、需要手动拼接的提示词、工作流、上下文管理技巧打包成一套可复用的“超能力”,让 AI 在写代码、改 bug、读项目、生成文档这些场景里表现得更像一个真正懂你项目的搭档,而不是一个只会背八股文的实习生。
你可能会问,市面上 AI 编程工具已经够多了,为什么还要搞一个 superpowers?我自己的体会是,原生 AI 助手最大的问题不是不够聪明,而是“记性差”和“不懂规矩”。你让它改一个函数,它可能顺手把你整个文件重写了;你让它读项目,它只看了你贴的那几行,完全不知道你用的是哪个框架、哪个版本、团队有什么代码规范。superpowers 要解决的就是这个断层——它通过一套结构化的配置和调用方式,把项目上下文、编码规范、任务拆解逻辑提前喂给 AI,让每次对话都站在“已经了解项目”的基础上进行。
这套东西适合谁?如果你满足下面任意一条,就值得花时间研究一下:每天要跟 AI 编程助手来回拉扯十几次以上;团队里多人共用一套 AI 辅助流程但效果参差不齐;经常需要让 AI 理解一个陌生代码库然后做修改;或者你单纯觉得现在用 AI 写代码“差点意思”,想把它调教得更顺手。它不要求你是 AI 专家,但需要你对项目结构和基本开发流程有概念,否则配置出来的东西也是空中楼阁。
我最初接触 superpowers 是因为一个实际痛点:手头有个 Java 老项目,代码分层混乱,注释稀少,每次让 AI 帮忙加功能,它都要我把相关类从头贴一遍,贴完它还经常改错 import。后来在社区看到有人分享用 superpowers 的思路做“项目记忆层”,我照着搭了一套,虽然踩了不少坑,但效果确实肉眼可见——现在 AI 改代码前会先确认包路径和依赖版本,改完还会自己跑一遍我预设的检查清单。下面我就把这套东西的来龙去脉、配置细节和实操经验完整拆一遍。
2. superpowers 的核心设计思路与方案选型
2.1 为什么不是简单的“提示词模板”
很多人第一次听说 superpowers,会以为它就是一堆写好的提示词,复制粘贴就能用。我一开始也这么想,结果发现完全不是那么回事。单纯的提示词模板是静态的、无状态的,你这次让它“用 Java 8 的语法写”,下次开新对话它又忘了。而 superpowers 的核心在于状态管理和上下文注入——它维护了一份关于你项目的“档案”,每次调用 AI 时自动把相关部分塞进对话里,让 AI 始终在一个受控的认知框架内工作。
这个设计思路借鉴了软件工程里的“依赖注入”思想:AI 的能力是运行时,项目上下文是依赖项,superpowers 就是那个容器。它不改变 AI 模型本身,而是改变 AI 接收到的信息结构和顺序。这样做的好处是可移植性强——你今天用 Codex,明天换另一个支持自定义上下文的助手,只要把档案格式适配一下,核心逻辑不用重写。
2.2 三层架构:档案层、调度层、执行层
我拆解了社区里几个高赞的 superpowers 实现,发现它们基本都遵循一个三层结构,我自己也按这个思路搭了一套,确实比一锅粥好维护。
档案层负责存储项目元信息。包括但不限于:项目类型(Maven/Gradle/纯 Java)、JDK 版本、核心依赖及版本号、包结构约定、命名规范、日志框架、测试框架、甚至团队内部的“禁止使用的 API 列表”。这些信息以结构化格式(我用的 YAML,也有人用 JSON 或 TOML)存放在项目根目录的.superpowers/文件夹下。为什么强调结构化?因为 AI 对结构化数据的解析准确率远高于自然语言描述,你写“我们用 Java 8”和写jdk_version: 1.8,后者被正确执行的几率高得多。
调度层是核心逻辑,决定“什么时候把什么信息喂给 AI”。比如你发出“帮我加一个用户查询接口”的指令,调度层会判断:这是新增功能,需要注入包结构约定、命名规范、Controller 层模板、Service 层模板、以及最近修改过的相关文件列表。如果你发出的是“这个空指针怎么修”,调度层则优先注入异常堆栈、相关类源码、以及该类的最近变更记录。调度策略的精细程度直接决定 superpowers 好不好用,我见过有人把所有信息一股脑全塞进去,结果 AI 被无关信息干扰,反而更容易出错。
执行层就是实际调用 AI 接口的部分,负责把调度层组装好的上下文和用户指令拼接成最终 prompt,发送给 Codex 或其他助手,再把返回结果做后处理(比如提取代码块、校验 import、跑格式化)。这一层通常需要写一点胶水代码,我用 Python 写的,大概两百行左右,核心就是 HTTP 请求加字符串处理,没什么高深技术。
2.3 为什么选择 Codex 作为主要载体
热词里出现了codex superpowers,说明很多人是把 superpowers 和 Codex 搭配使用的。我试过几个不同的 AI 编程助手,最后也固定在 Codex 上,原因有三个。第一,Codex 对长上下文的支持比较稳,superpowers 注入的档案信息动辄几千 token,上下文窗口小的助手直接截断,效果大打折扣。第二,Codex 的代码补全和对话模式切换自然,我可以在写代码时让它自动补全,遇到复杂逻辑再切到对话模式详细讨论,superpowers 的调度层可以针对两种模式做不同注入。第三,社区生态,用的人多意味着踩坑有人分享,我遇到的好几个问题都是在社区讨论里找到答案的。
当然这不是说其他助手不能用,superpowers 的设计本身是平台无关的,只是 Codex 目前适配得最顺。如果你用的是别的工具,只要它支持自定义系统提示或上下文注入,理论上都能改造。
3. 核心细节解析:档案怎么写、调度怎么配
3.1 项目档案的字段设计与填写要点
档案层是整个 superpowers 的地基,写得好不好直接决定后续效果。我一开始图省事,只写了项目名和 JDK 版本,结果 AI 还是经常用错日志框架。后来我把档案扩充到下面这些字段,效果才稳定下来。
# .superpowers/profile.yaml project: name: user-center type: maven jdk_version: 1.8 spring_boot_version: 2.3.12.RELEASE build_tool: maven encoding: UTF-8 structure: base_package: com.example.usercenter layers: - controller - service - service.impl - mapper - entity - dto - config resource_dirs: - src/main/resources - src/test/resources conventions: naming: class: UpperCamelCase method: lowerCamelCase constant: UPPER_SNAKE_CASE db_column: lower_snake_case logging: framework: slf4j annotation: "@Slf4j" forbidden: System.out.println exception: base_class: com.example.usercenter.exception.BizException handler: com.example.usercenter.config.GlobalExceptionHandler api_response: wrapper: com.example.usercenter.common.Result success_code: 200 error_code_prefix: 4 dependencies: - groupId: org.springframework.boot artifactId: spring-boot-starter-web version: 2.3.12.RELEASE - groupId: com.baomidou artifactId: mybatis-plus-boot-starter version: 3.4.3.2 - groupId: org.projectlombok artifactId: lombok version: 1.18.20 forbidden: - "使用 java.util.Date,统一用 java.time.LocalDateTime" - "在 Controller 里写业务逻辑" - "直接返回 Entity,必须转 DTO" - "使用 SELECT *"这份档案有几个关键点值得展开说。forbidden字段是我踩坑最多的地方,一开始没写,AI 生成的代码里System.out.println和SELECT *满天飞,后来我把团队代码规范里最常被违反的几条列进去,AI 就老实了。注意措辞要具体,写“不要用 Date”不如写“使用 java.util.Date,统一用 java.time.LocalDateTime”,后者给了明确替代方案,AI 执行起来不犹豫。
conventions.naming里的db_column字段容易被忽略,但如果你用 MyBatis-Plus 这类 ORM,实体类字段和数据库列的映射规则必须提前说清楚,否则 AI 生成的@TableField注解可能对不上。我见过有人因为没写这条,AI 把userName映射到user_name又映射到username,调试了半天。
依赖版本号要写全,包括RELEASE后缀。AI 对版本号很敏感,你写2.3.12和2.3.12.RELEASE,它生成的pom.xml片段可能不一样。这个细节看似吹毛求疵,但实际项目中版本号不完整会导致构建失败,返工成本很高。
3.2 调度层的触发规则与优先级
调度层要解决的核心问题是:用户说了一句话,我该往 AI 的上下文里塞哪些档案片段?我的做法是维护一个“触发词-档案片段”映射表,再加一层优先级排序。
# scheduler.py 核心逻辑示意 TRIGGER_RULES = [ { "keywords": ["新增", "添加", "创建", "写一个"], "inject": ["structure", "conventions.naming", "conventions.api_response", "forbidden"], "priority": 10 }, { "keywords": ["修改", "改成", "调整", "重构"], "inject": ["structure", "conventions.naming", "forbidden", "recent_changes"], "priority": 9 }, { "keywords": ["报错", "异常", "空指针", "失败"], "inject": ["dependencies", "conventions.exception", "recent_changes"], "priority": 8 }, { "keywords": ["测试", "单元测试", "test"], "inject": ["structure", "conventions.naming", "dependencies"], "priority": 7 } ]这个映射表不是拍脑袋写的,是我根据实际使用频率和出错率慢慢调出来的。新增功能时最容易犯的错是命名不规范和返回格式不对,所以把conventions.naming和conventions.api_response的优先级调高。修改代码时最容易破坏原有结构,所以注入structure和recent_changes,让 AI 知道最近谁动过哪些文件,避免冲突。
recent_changes这个字段需要动态生成,我的做法是用 Git 命令抓最近三次提交涉及的文件列表和变更摘要,存成一个临时文件,调度时读取。这样 AI 在改代码前会“看到”最近有人改过同一个类,它会主动提醒你可能存在冲突。这个功能帮我避免了好几次覆盖别人代码的事故。
优先级排序的逻辑是:当多个规则同时命中时,按 priority 从高到低取前三个规则的注入内容,去重后拼接。为什么不全部注入?因为上下文窗口有限,塞太多反而稀释了关键信息。我实测下来,每次注入的档案内容控制在 2000 token 以内效果最好,超过 4000 token 后 AI 的注意力明显分散,开始忽略一些约束条件。
3.3 执行层的后处理与校验清单
执行层不只是发请求收响应,后处理才是保证输出质量的关键环节。我给自己定了一套校验清单,每次 AI 返回代码后自动跑一遍,不通过就打回重问。
| 校验项 | 检查方式 | 不通过时的处理 |
|---|---|---|
| import 完整性 | 正则提取 import 语句,对比项目已有类 | 自动补全缺失的 import |
| 禁止 API | 扫描是否出现 forbidden 列表中的模式 | 打回并附上禁止原因 |
| 命名规范 | 正则匹配类名、方法名、常量名 | 打回并指出具体违规处 |
| 返回类型 | 检查 Controller 方法返回是否为 Result 包装 | 打回并要求重新生成 |
| 日志使用 | 检查是否用了 @Slf4j 而非 System.out | 打回并替换 |
| 空指针防护 | 检查对象调用前是否有判空 | 打回并提示补充判空 |
这套校验清单是我用血泪换来的。最开始我没做后处理,AI 生成的代码看着像模像样,一编译就报错,不是缺 import 就是返回类型对不上。后来我把这些检查写成脚本,每次自动跑,返工率从最初的 40% 降到了 10% 左右。剩下的 10% 主要是业务逻辑层面的问题,那个确实需要人工判断,自动化脚本搞不定。
提示:校验脚本不要写得太严格,否则 AI 会被频繁打回,对话轮次暴增,反而降低效率。我的经验是只校验“硬性规范”,比如 import、禁止 API、返回类型这些,命名规范可以适当放宽,因为 AI 有时候会用同义词,不影响功能。
4. 完整实操流程:从零搭一套可用的 superpowers
4.1 环境准备与目录结构
动手之前先把环境理清楚。我假设你用的是 Java 项目加 Codex 助手,其他语言和助手可以类比调整。需要准备的东西不多:一个能跑 Python 脚本的环境(我用 3.8+),Git 命令行工具,以及 Codex 的 API 访问权限(如果你用的是网页版,需要确认它支持自定义上下文注入,不支持的话得换支持 API 的方式)。
目录结构我建议这样组织,放在项目根目录下:
your-project/ ├── .superpowers/ │ ├── profile.yaml # 项目档案 │ ├── scheduler.py # 调度逻辑 │ ├── validator.py # 后处理校验 │ ├── recent_changes.txt # 动态生成的最近变更 │ └── templates/ # 常用代码模板 │ ├── controller.tpl │ ├── service.tpl │ └── test.tpl ├── src/ └── pom.xml.superpowers/文件夹建议加入.gitignore的例外,也就是说档案文件要提交到仓库,但recent_changes.txt这种动态生成的文件不提交。这样团队每个人拉下来就有统一的档案,减少“我这里跑得好好的”这类扯皮。
4.2 档案初始化:用脚本自动提取项目信息
手写profile.yaml太累且容易漏,我写了个初始化脚本,自动扫描项目提取关键信息。核心逻辑是解析pom.xml或build.gradle拿依赖列表,扫描源码目录推断包结构,读取现有代码统计命名风格。
# init_profile.py 核心片段 import xml.etree.ElementTree as ET import os import re def parse_pom(pom_path): tree = ET.parse(pom_path) root = tree.getroot() ns = {'m': 'http://maven.apache.org/POM/4.0.0'} deps = [] for dep in root.findall('.//m:dependency', ns): groupId = dep.find('m:groupId', ns).text artifactId = dep.find('m:artifactId', ns).text version_el = dep.find('m:version', ns) version = version_el.text if version_el is not None else 'managed' deps.append({ 'groupId': groupId, 'artifactId': artifactId, 'version': version }) return deps def infer_package_structure(src_dir): packages = set() for root, dirs, files in os.walk(src_dir): for f in files: if f.endswith('.java'): with open(os.path.join(root, f), 'r', encoding='utf-8') as fh: content = fh.read() match = re.search(r'package\s+([\w.]+);', content) if match: packages.add(match.group(1)) return sorted(packages)这个脚本跑一遍,能自动填好dependencies和structure.base_package以及layers的大部分内容。剩下的conventions和forbidden需要手动补,因为那些是团队约定,脚本猜不出来。我一般会花十分钟跟团队确认这几条,一次确认长期受益。
4.3 调度脚本的调用方式与参数说明
调度脚本我设计成命令行工具,方便在终端里直接调用,也方便集成到编辑器的快捷键里。
# 基本用法:传入用户指令,输出组装好的 prompt python .superpowers/scheduler.py --input "帮我加一个根据用户ID查询订单列表的接口" # 指定输出格式,直接写入文件供 Codex 读取 python .superpowers/scheduler.py --input "修复订单查询的空指针" --output prompt.txt # 查看当前会注入哪些档案片段(调试用) python .superpowers/scheduler.py --input "新增接口" --dry-run--dry-run这个参数我强烈建议加上,调试调度规则时特别有用。你可以看到针对不同指令,实际会注入哪些档案片段,如果发现某个该注入的没注入,或者注入了无关内容,就回去调TRIGGER_RULES。我调了大概二十几次才把规则调顺,现在基本能做到“该有的都有,不该有的不塞”。
调度脚本的输出格式也有讲究。我最终采用的格式是:
[项目档案] {注入的档案片段,YAML 格式} [最近变更] {recent_changes.txt 内容} [用户指令] {原始输入} [输出要求] 1. 只输出代码,不要解释 2. 代码块用 ```java 包裹 3. 如果需要新增文件,先输出文件路径 4. 修改现有文件时,只输出变更部分,用注释标注上下文最后那段“输出要求”是固定模板,它比档案本身还重要。没有这段约束,AI 会给你写一大段解释文字,代码混在里面,提取起来很麻烦。加上这段之后,输出干净多了,我写了个简单的解析器就能自动提取代码块和文件路径。
4.4 与 Codex 的对接实操
对接方式取决于你用的是什么形态的 Codex。如果是 API 方式,直接发 HTTP 请求就行:
import requests def call_codex(prompt, api_key): headers = { 'Authorization': f'Bearer {api_key}', 'Content-Type': 'application/json' } payload = { 'model': 'codex', 'messages': [ {'role': 'system', 'content': '你是一个严格遵守项目规范的 Java 开发助手。'}, {'role': 'user', 'content': prompt} ], 'temperature': 0.2, 'max_tokens': 2000 } resp = requests.post('https://api.example.com/v1/chat/completions', headers=headers, json=payload) return resp.json()['choices'][0]['message']['content']temperature设成 0.2 是我反复试出来的。设 0 太死板,AI 有时候会卡在一个错误方案上反复输出;设 0.5 以上又太发散,生成的代码风格飘忽不定。0.2 在稳定性和灵活性之间平衡得比较好。
如果你用的是网页版 Codex,没有 API 权限,那就手动把调度脚本生成的 prompt 复制粘贴进去。虽然多了一步操作,但效果是一样的。我早期就是这么干的,后来调用频繁了才换成 API。
4.5 后处理校验脚本的集成
校验脚本我集成在调用 Codex 之后自动执行,流程是:调度生成 prompt → 调用 Codex → 提取代码 → 跑校验 → 通过则写入文件,不通过则把校验失败原因拼回 prompt 重新调用。
def validate_and_fix(code, profile): errors = [] # 检查禁止 API for forbidden in profile['forbidden']: pattern = forbidden.split(',')[0].replace('使用 ', '') if pattern in code: errors.append(f'使用了禁止的 API: {pattern}') # 检查 import 完整性 imports = re.findall(r'import\s+([\w.]+);', code) # ... 对比项目已有类,补全缺失 import # 检查返回类型 if 'Controller' in code and 'Result' not in code: errors.append('Controller 方法未使用 Result 包装返回') return errors校验失败时,我会把errors列表拼成一段话追加到原 prompt 后面,再调一次 Codex。通常第二次就能过,因为 AI 看到具体错误原因后会针对性修正。如果第二次还不过,我就人工介入,不再自动重试,避免陷入死循环浪费 token。
5. 常见问题与排查技巧实录
5.1 档案写了但 AI 不遵守怎么办
这是最常见的问题,我一开始也遇到。档案里明明写了“禁止使用 System.out.println”,AI 还是照写不误。排查下来原因有三个。第一是档案位置不对,AI 根本没读到。检查方法是用--dry-run看注入内容里有没有你写的约束。第二是约束太靠后,被前面的内容稀释了。解决办法是把最重要的约束放在档案最前面,或者单独拎出来放在 prompt 的开头部分。第三是措辞太模糊,AI 理解不了。比如写“注意代码规范”等于没写,要写“类名用 UpperCamelCase,方法名用 lowerCamelCase”这种可执行的规则。
我现在的做法是把最关键的 3-5 条约束单独拎出来,放在 prompt 的最开头,用醒目的标记包起来,比如:
[硬性约束 - 必须遵守] 1. 禁止使用 System.out.println,统一用 @Slf4j 2. Controller 必须返回 Result 包装 3. 禁止使用 java.util.Date这样 AI 几乎不会违反。剩下的约束放在档案里作为补充,违反率也低了很多。
5.2 上下文太长导致 AI “失忆”
superpowers 注入的档案加上项目源码,很容易超过 AI 的上下文窗口。我遇到过注入内容太长,AI 把前面的约束忘了,只记得最后几行的情况。解决办法是分层注入:核心约束永远放在最前面且保持简短,详细档案放在中间,最近变更放在后面。如果还是超长,就只注入与当前任务最相关的档案片段,而不是全量注入。
我做了个简单的 token 估算函数,用字符数除以 4 粗略估算 token 数,超过 3000 就触发裁剪逻辑,按优先级从低到高丢弃档案片段。这个粗暴的方法实测够用,比精确计算 token 省事多了。
5.3 生成的代码风格与项目不一致
AI 生成的代码能跑,但风格跟项目里其他代码格格不入,比如别人用@Autowired构造器注入,它用字段注入;别人用Optional判空,它用if (obj != null)。这个问题根源在于档案里没有提供足够的风格样本。我的解决办法是在templates/文件夹里放几个“标杆文件”,也就是项目里写得最规范的几个类,调度时把标杆文件的关键片段也注入进去。AI 看到实际样本后,模仿能力比看文字描述强得多。
5.4 常见问题速查表
| 问题现象 | 可能原因 | 排查方法 | 解决措施 |
|---|---|---|---|
| AI 不遵守约束 | 档案未注入/措辞模糊/位置靠后 | 用 --dry-run 检查注入内容 | 核心约束前置,措辞具体化 |
| 上下文超长失忆 | 注入内容过多 | 估算 token 数 | 分层注入,按优先级裁剪 |
| 代码风格不一致 | 缺少风格样本 | 对比标杆文件 | 注入标杆文件片段 |
| import 缺失 | 后处理未校验 | 跑校验脚本 | 自动补全或打回重问 |
| 返回类型错误 | 档案未强调 | 检查 api_response 字段 | 加入硬性约束列表 |
| 命名不规范 | 命名规则未注入 | 检查 conventions 字段 | 补充命名规则并前置 |
| 重复生成相同错误 | 重试时未附错误原因 | 检查重试逻辑 | 把校验错误拼回 prompt |
| 调度规则不生效 | 关键词未命中 | 用 --dry-run 测试 | 调整 TRIGGER_RULES 关键词 |
这张表是我踩坑踩出来的,基本上覆盖了 90% 的常见问题。建议把这张表打印出来贴在显示器旁边,遇到问题先查表,能省不少排查时间。
5.5 几个容易被忽略的实操心得
第一,档案要版本化。我把.superpowers/profile.yaml提交到 Git,每次修改都写 commit message,比如“增加禁止使用 Date 的约束”。这样当 AI 行为发生变化时,可以回溯是哪次档案修改导致的。我遇到过改了档案后 AI 突然开始用错日志框架,回滚档案就恢复了。
第二,定期清理 recent_changes。这个文件如果一直追加不清理,会越来越长,最终拖垮上下文。我的做法是只保留最近 7 天的变更记录,更早的自动归档到另一个文件,不参与注入。
第三,不同任务用不同档案。我维护了两份档案,一份是“开发模式”,约束严格,适合写新功能;一份是“探索模式”,约束宽松,适合让 AI 快速读代码、做分析。切换档案比改档案方便,也避免了探索时被一堆约束束手束脚。
第四,别指望一次配置到位。superpowers 是个需要持续调优的东西,我用了三个月还在微调调度规则。把它当成一个需要迭代的项目,而不是一次性配置,心态会好很多。每次 AI 出错,不要只骂它笨,想想是不是档案或调度哪里可以改进,改完下次就好了。
6. 进阶玩法:把 superpowers 用到 Java 之外
虽然热词里superpowers java出现频率最高,但这套思路并不局限于 Java。我后来把它迁移到了前端项目和一个 Python 数据处理脚本上,核心逻辑完全一样,只是档案字段和校验规则换了。
前端项目里,我把conventions换成 ESLint 规则摘要,forbidden换成“禁止使用 var”“禁止直接操作 DOM”这类约束,templates里放 React 函数组件的标杆写法。效果同样明显,AI 生成的组件风格统一多了,不会再一会儿用 class 组件一会儿用函数组件。
Python 项目里,我把structure.layers换成模块划分,conventions.naming换成 PEP 8 摘要,forbidden加上“禁止使用 mutable 默认参数”这类 Python 特有的坑。校验脚本里加了flake8的调用,AI 生成的代码直接过一遍 lint,不通过就打回。
迁移的关键是抽象出“档案-调度-校验”这个骨架,然后针对不同语言填充具体内容。骨架代码几乎不用改,改的是 YAML 档案和校验规则。我大概花了半天时间就把前端版本搭起来了,因为核心逻辑已经跑通了。
如果你团队里有人用不同的技术栈,可以各自维护自己的.superpowers/档案,但共享调度和校验脚本。这样既保证了各栈的个性化,又避免了重复造轮子。我们团队现在就是这么干的,Java 组和前端组各有一份档案,调度脚本是同一份,维护成本很低。
最后分享一个我最近在试的玩法:把 superpowers 的档案生成也交给 AI。我写了个脚本,让 AI 读一遍项目源码,自动生成profile.yaml的初稿,我再人工审核修改。这样初始化新项目时能省不少事,虽然生成的档案不够精确,但作为起点足够了,改起来比从零写快得多。这个思路还在打磨中,等稳定了再单独写一篇分享。