从 Codex 移植到 OpenCode 原生插件:superpowers 的跨平台技能架构设计与落地实现
导读
本文以 superpowers 仓库中的 OpenCode 支持设计文档 为主体,剖析"如何把一套以技能(Skills)为核心的 Agent 方法论,从仅支持 Claude Code / Codex 移植到 OpenCode.ai"。文档给出了"抽取共享核心模块 + 平台原生插件"的架构决策,读者可从中掌握跨 Coding Agent 平台做技能发现、解析与引导注入(bootstrap)的通用设计方法,并对照仓库当前实现,了解设计落地后的演进与取舍。
一、背景:为什么需要一个"原生 OpenCode 插件"
superpowers 是一个"Agent 技能框架与软件开发方法论"仓库,其核心资产是一组以 SKILL.md 形式组织的技能目录,每个技能通过 YAML frontmatter 声明自己的 name 与 description,从而被 Agent 在合适的时机自动发现与调用。它的三个目标平台差异很大:
| 平台 | 能力形态 | superpowers 接入方式 |
|---|---|---|
| Claude Code | Anthropic 原生插件系统 + 基于文件的技能 | 原生插件 |
| Codex | 无插件系统 | 引导 Markdown + CLI 脚本 |
| OpenCode.ai | JavaScript/TypeScript 插件,提供事件钩子(event hooks)与自定义工具 API | 原生 JS/TS 插件 |
设计文档明确指出,此前为 OpenCode 做的移植尝试(PR #93、PR #116)都采用"文件复制"方式,难以维护。而 OpenCode 具备真正的插件系统,因此本设计(2025-11-22,状态标注为 Design Complete, Awaiting Implementation)的路线是:使用 OpenCode 的原生 JS/TS 插件系统,同时与 Codex 实现共享核心代码。
设计文档还梳理了 OpenCode 的 Agent 体系:主 Agent 分为 Build(默认、全权限)与 Plan(受限、只读);子 Agent(Subagents)面向研究、检索与多步任务;子 Agent 既可由主 Agent 自动派发,也可通过 @mention 语法手动召唤;自定义 Agent 可写在 opencode.json 或 ~/.config/opencode/agent/ 中。这些能力决定了技能如何在 OpenCode 中被装载和复用。
二、架构设计:共享核心 + 平台包装器
设计文档给出了三层结构:
- 共享核心模块
lib/skills-core.js——技能发现(discovery)与解析(parsing)的公共逻辑,Codex 与 OpenCode 两端共用; - 平台专属包装器——Codex 侧为 CLI 脚本
.codex/superpowers-codex,OpenCode 侧为插件模块.opencode/plugin/superpowers.js; - 技能目录——核心技能位于
~/.config/opencode/superpowers/skills/(或安装位置),个人技能位于~/.config/opencode/skills/,个人技能通过同名遮蔽(shadowing)覆盖核心技能。
2.1 代码复用策略
设计文档的核心诉求是"单一事实来源"(single source of truth)。它计划把 .codex/superpowers-codex 中散落的逻辑抽取为一个 CommonJS 模块:
// lib/skills-core.js
module.exports = {
extractFrontmatter(filePath), // Parse name + description from YAML
findSkillsInDir(dir, maxDepth), // Recursive SKILL.md discovery
findAllSkills(dirs), // Scan multiple directories
resolveSkillPath(skillName, dirs), // Handle shadowing (personal > core)
checkForUpdates(repoDir) // Git fetch/status check
};
五个函数的职责边界非常清晰:
extractFrontmatter:读取SKILL.md,逐行解析---包裹的 YAML 头,仅提取name与description两个字段;findSkillsInDir:递归扫描目录树,对每个含SKILL.md的子目录收集技能信息,返回包含path、name、description、sourceType的结构化数组;resolveSkillPath:实现遮蔽语义——先查个人目录,除非技能名显式带superpowers:前缀强制指向核心目录;checkForUpdates:用git fetch origin && git status --porcelain=v1 --branch检查远端是否有新提交,并设置 3 秒超时,网络不可用时静默返回false,避免阻塞引导流程。
2.2 技能 Frontmatter 格式
设计文档明确了当前仓库的技能头格式——只有 name 与 description,没有 when_to_use 字段(抽取核心逻辑时需保持兼容):
---
name: skill-name
description: Use when [condition] - [what it does]; [additional context]
---
这一点可以用仓库中的真实技能验证,例如 using-superpowers 技能 与 brainstorming 技能 的 frontmatter 都遵循 name + description 两字段约定,其中 description 往往用"Use when …"条件句描述触发时机,这是后续 Agent 自动匹配技能的依据。
三、OpenCode 插件实现设计
设计文档用可执行的伪代码/代码草图描述了插件形态,共包含两类自定义工具与一个会话级钩子。
3.1 自定义工具 use_skill
等价于 Claude Code 的 Skill 工具,把指定技能的正文注入当前对话。设计草图使用 zod 做参数校验,skill_name 形如 "superpowers:brainstorming",执行时经共享核心解析路径、剥离 frontmatter 后,按统一模板返回技能标题 + 描述 + 支撑文件目录 + 正文:
{
name: 'use_skill',
description: 'Load and read a specific skill to guide your work',
schema: z.object({
skill_name: z.string().describe('Name of skill (e.g., "superpowers:brainstorming")')
}),
execute: async ({ skill_name }) => {
const { skillPath, content, frontmatter } = resolveAndReadSkill(skill_name);
const skillDir = path.dirname(skillPath);
return `# ${frontmatter.name}
# ${frontmatter.description}
# Supporting tools and docs are in ${skillDir}
# ============================================
${content}`;
}
}
返回模板刻意附带 skillDir 目录,因为技能目录里往往还躺着配套脚本、附加文档与专用工具——Agent 必须知道去哪里找它们。
3.2 自定义工具 find_skills
列出所有可用技能及其元数据,输出格式为 namespace:name + 描述 + 目录:
{
name: 'find_skills',
description: 'List all available skills',
schema: z.object({}),
execute: async () => {
const skills = discoverAllSkills();
return skills.map(s =>
`${s.namespace}:${s.name}
${s.description}
Directory: ${s.directory}
`).join('\n');
}
}
3.3 会话启动钩子(session.started)
设计文档规划了在 session.started 事件触发时执行四步引导:
- 注入 using-superpowers 全文——建立"必须先调用技能再作答"的强制性工作流;
- 自动执行
find_skills——开场即把全部可用技能列表连同目录展示给 Agent; - 注入工具映射指令——把 superpowers 技能中引用的 Claude Code 风格工具名翻译成 OpenCode 等价物:
TodoWrite→update_plan、Task(带子 Agent)→ OpenCode 子 Agent 体系(@mention)、Skill工具 →use_skill自定义工具、Read/Write/Edit/Bash → OpenCode 原生工具; - 非阻塞更新检查——带超时的快速
git fetch,有新版本时提示用户。
设计文档还给出了插件入口的结构草图,导出形如 SuperpowersPlugin 的工厂函数,从插件对象中读取会话上下文、注册 session.started 钩子与两个自定义工具,路径基址分别指向 ~/.config/opencode/superpowers 与 ~/.config/opencode/skills。
3.4 目标文件结构
superpowers/
├── lib/
│ └── skills-core.js # NEW: Shared skill logic
├── .codex/
│ ├── superpowers-codex # UPDATED: Use skills-core
│ ├── superpowers-bootstrap.md
│ └── INSTALL.md
├── .opencode/
│ ├── plugin/
│ │ └── superpowers.js # NEW: OpenCode plugin
│ └── INSTALL.md # NEW: Installation guide
└── skills/ # Unchanged
四、实施计划:分三阶段推进
设计文档把落地拆成三个渐进阶段,每阶段都带验证关口(这是仓库方法论一贯的"先验证再前进"风格):
- Phase 1 重构共享核心:创建
lib/skills-core.js,从.codex/superpowers-codex中逐个抽出 frontmatter 解析、技能发现与路径解析(含遮蔽),并把格式收敛到仅name/description;随后改造.codex/superpowers-codex改为require('../lib/skills-core')、删除重复代码;回归验证 bootstrap、use-skill、find-skills 三条命令。 - Phase 2 构建 OpenCode 插件:创建
.opencode/plugin/superpowers.js,实现自定义工具与session.started钩子;编写.opencode/INSTALL.md;验证会话引导、两个工具与技能目录可达性。 - Phase 3 文档收尾:更新 README、主文档与 RELEASE-NOTES,双平台并行测试。
配套的 OpenCode 支持实施计划文档 进一步把它细化为 18 个可执行任务,包含每个函数的完整代码、node -c 语法校验命令、逐任务 git commit 规范,以及需要真实 OpenCode 环境的 7 项手动测试清单与成功标准。Next Steps 部分还强调:用 git worktrees 创建隔离工作区(分支 feature/opencode-support)、共享核心函数走 TDD、增量实现、双平台并排回归、最后 PR 合入主分支。
五、设计带来的收益
设计文档结尾归纳了这套"共享核心 + 平台包装"路线的五个收益,可看作方案评审的标准:
- 代码复用:技能发现与解析只有一份实现;
- 可维护性:一处修复,双平台受益;
- 可扩展性:未来接入 Cursor、Windsurf 等新平台只需新增薄包装;
- 原生集成:充分使用 OpenCode 的插件系统而非文件复制;
- 体验一致:所有平台上技能使用体验统一。
六、仓库现状对照:设计落地后的真实演进
设计文档标注为 2025-11-22"待实现",但仓库当前快照已包含完成的 OpenCode 插件。把设计与现状对照,可以看到实际实现沿原架构方向落地,但 API 选择上发生了明显演进。以下均以仓库现有文件为据。
6.1 插件入口与钩子的变化
当前插件位于 .opencode/plugins/superpowers.js(注意目录为 plugins 而非设计稿的 plugin),且 package.json 的 main 字段直接指向 .opencode/plugins/superpowers.js,说明 OpenCode 插件包体系已经成为标准安装通道。
插件函数 SuperpowersPlugin 的签名保留了 client/directory,但没有采用设计稿的 session.started,而是注册了两个钩子:
config钩子:把path.resolve(__dirname, '../../skills')(即安装包内自带技能目录)写入config.skills.paths,让 OpenCode 免去 symlink 或手改配置即可自动发现全部 superpowers 技能。注释特别解释:Config.get()返回缓存单例,这里就地修改会在技能被懒加载发现时生效。experimental.chat.messages.transform钩子:负责把 bootstrap 上下文注入每轮会话第一条用户消息之前,而不是以 system 消息注入。注释给出了两条动机:避免每条 system 消息每轮都重复计入 token 开销(#750);多条 system 消息会破坏 Qwen 等模型的解析(#894)。
钩子内部还有防止重复注入的守卫(检测首条用户消息是否已含 EXTREMELY_IMPORTANT 标记),并对注入文本用 <EXTREMELY_IMPORTANT> 块包裹,顶部声明"你已经拥有 superpowers",并提示 using-superpowers 技能"已加载,不要重复加载"。
6.2 自定义工具让位于 OpenCode 原生 skill 工具
设计稿规划的自定义工具 use_skill/find_skills 在当前插件中并未出现——实现演进为直接利用 OpenCode 的原生 skill 工具,因为新版本 OpenCode CLI 本身已具备"列出并加载技能"的能力。这一点在 .opencode/INSTALL.md 与 docs/README.opencode.md 中得到印证:使用方式简化为 use skill tool to list skills、use skill tool to load brainstorming。README.opencode 还注明其中的工具映射"已对照已安装 OpenCode CLI 的工具清单验证过"。
相应地,工具映射表从"桥接缺失工具"变成了"动作语义到工具清单的翻译"。技能用动作描述需求(create a todo、dispatch a subagent、read a file),映射如下:
- 创建/完成待办 →
todowrite - 派发通用子 Agent →
task工具 +subagent_type: "general"(代码库探索用"explore") - 调用技能 → OpenCode 原生
skill工具 - 读写删文件 →
read/apply_patch - 执行命令 →
bash - 检索文件内容与文件名 →
grep、glob - 抓取 URL →
webfetch
6.3 技能目录与优先级的变化
设计稿假设核心技能装在 ~/.config/opencode/superpowers/skills/;当前实现则把技能与插件一起作为 npm/git 包发布,技能目录按插件文件相对位置 ../../skills 解析(测试环境的标准布局可参考 tests/opencode/setup.sh 的注释:$OPENCODE_CONFIG_DIR/superpowers/skills/ 即包内 ../../skills)。技能优先级规则在真实使用中按 Project > Personal > Superpowers 排列,其中项目技能放在项目内 .opencode/skills/,个人技能放在 ~/.config/opencode/skills/。需要留意的是,设计稿所设想的"同名个人技能遮蔽核心技能"在当前 OpenCode 版本中未必成立——见 6.5 中测试脚本的注释。
6.4 版本引导与启动缓存优化
针对设计稿中"会话启动注入"的需求,实现上额外引入了一个模块级缓存:由于 experimental.chat.messages.transform 在每一步都会触发(OpenCode 的 prompt 组装每步都从数据库重载消息,fresh 的消息数组可能需要重复注入),而 SKILL.md 在会话期间不会变化,插件首次读取并解析一次后即缓存(.opencode/plugins/superpowers.js 注释引用 #1202 的完整分析),缓存未命中与缺失以 undefined/null 区分。配套的 tests/opencode/test-bootstrap-caching.mjs 通过 monkey-patch fs.existsSync/fs.readFileSync 并多次调用 transform 钩子,断言磁盘访问次数不会随 agent 步数线性增长。
6.5 测试体系:用隔离环境验证插件行为
仓库为 OpenCode 支持建立了专门的测试套件(tests/opencode/run-tests.sh 为统一入口,支持 --integration / --verbose / --test 等参数):
- setup.sh:用
mktemp -d构建隔离 HOME,铺出opencode 配置目录 + superpowers 包 + plugins symlink的标准安装布局,并预置 personal-test / project-test 等测试技能夹具(内含PERSONAL_SKILL_MARKER_12345等唯一标记); - test-plugin-loading.sh:校验插件 symlink 存在且目标有效、技能目录非空、
using-superpowers(bootstrap 关键技能)存在、插件 JS 语法通过node --check,并回归防止插件继续引用旧的误导性技能路径; - test-tools.sh:通过
opencode run --format json真实驱动 CLI,断言原生skill工具能加载 personal、project 与内置 brainstorming 技能,并在输出中匹配"tool":"skill"与技能正文标记; - test-priority.sh:在 superpowers / personal / project 三处创建同名
priority-test,如实记录当前 OpenCode 对重名技能的实际行为——注意其注释说明,测试脚本并不假装 local shadowing 已经生效,而是"记录现状、保持测试套件诚实",将期望行为单独跟踪。
这些测试文件同时展示了"设计文档中提到的双平台回归、引导内容可见性、技能目录可达性"等验收标准,在真实 OpenCode 环境里如何被机械地检查。
七、安装、使用与排障(基于当前仓库)
结合 .opencode/INSTALL.md 与 docs/README.opencode.md,当前版本的推荐接入方式如下。
安装:在全局或项目级 opencode.json 的 plugin 数组中,以 git 包规范声明 superpowers(即 superpowers@git+<仓库地址> 形式),重启 OpenCode 后由插件管理器完成安装并注册全部技能,可用提问 "Tell me about your superpowers" 验证。若你同时使用 Claude Code / Codex 等其它 harness,需要在每个 harness 中分别安装。
个人技能:在 ~/.config/opencode/skills/<skill-name>/SKILL.md 放置带 frontmatter 的 Markdown 文件即可;项目技能则放在项目内 .opencode/skills/。
更新与版本锁定:OpenCode 与 Bun 的部分版本会把 git 依赖 pin 进 lockfile 或缓存,导致重启后拿不到最新提交;如更新不生效,需清理 OpenCode 包缓存或重装插件。需要锁定时可改用分支或 tag 规范,如 superpowers@git+<仓库地址>#v5.0.3。
已知坑位(Windows):部分 Windows 版 OpenCode 对 git 源插件规范存在上游安装问题(含 git+https URL 的缓存路径问题、以及 Bun 在正常终端可用却找不到 git.exe 的情况)。规避方式是改用系统 npm 安装到 OpenCode 配置目录,再把 opencode.json 的 plugin 指向本地包路径,例如把包装到 ~/.config/opencode/node_modules/superpowers 后声明 "plugin": ["~/.config/opencode/node_modules/superpowers"]。
排障要点:插件未加载可执行 opencode run --print-logs "hello" 2>&1 | grep -i superpowers 查看日志并核对 opencode.json 插件声明;技能找不到时先用 skill 工具查看发现结果,并确认每个技能都含合法 YAML frontmatter 的 SKILL.md。
结语
回看这份 OpenCode 支持设计文档,它的价值并不止于"让 superpowers 多支持一个平台"。extractFrontmatter → findSkillsInDir → resolveSkillPath → checkForUpdates 这套共享核心的切分、个人技能遮蔽语义、会话启动引导注入与工具映射表的构思,构成了一个"如何让同一套 Agent 技能在不同 harness 上以原生方式复现"的可复用模板。而仓库当前实现中"config 钩子注册技能路径 + messages.transform 注入 bootstrap + 原生 skill 工具 + 模块级缓存防重读"的组合,则是这份设计在真实 OpenCode API 约束下经过验证的最终答案——设计与实现之间的落差,恰好是读者理解跨平台插件移植时最有价值的参考。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0627
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00