本文档介绍 opencode2-skill-creator 如何从 OpenCode 1(V1)迁移到 OpenCode 2(V2),
包括迁移动因、插件 API 变化、配置与安装方式、评测流程的兼容性,以及用户侧升级步骤。
面向读者:使用本插件的用户、维护者,以及希望对照移植自己插件的 OpenCode 插件作者。
1. 背景:为什么必须适配 V2
OpenCode 2 有三处有意为之的破坏性变更(来自官方迁移指南):
- 插件使用全新的插件 API。V1 插件实现无法在 V2 中运行,仅仅移动文件或改配置项名称是不够的。
- 服务器 API 与客户端采用新契约。
- 终端客户端配置从分层的
tui.json(c)迁移为全局cli.json。
本项目的核心产物是一个 OpenCode 插件(注册技能校验、评测、描述优化、基准测试、评审等工具),
因此插件 API 的破坏性变更直接决定了适配工作。
对插件而言最关键的两条:
| 维度 | V1 | V2 |
|---|---|---|
| 配置键 | plugin |
plugins |
| 包 | @opencode-ai/plugin |
@opencode/plugin |
| 入口形态 | export const Plugin: Plugin = async (ctx) => ({ tool: {...} }) |
export default Plugin.define({ id, setup(ctx) }) |
| 注册工具 | 返回 tool 映射(tool() 辅助函数) |
ctx.tool.transform((editor) => editor.add(...)) |
| 工具入参 schema | tool.schema 参数表 |
JSON Schema input |
| 工具返回值 | 直接返回字符串 | { content } 结构化内容 |
官方结论:
V1 plugin implementations do not run in V2.
2. 版本与兼容策略
| 项目 | 值 |
|---|---|
| 适配版本 | opencode2-skill-creator@0.3.0(V2) |
| 插件 API 依赖 | @opencode/plugin peer >=2.0.0(开发依赖 ^2.0.18) |
| V1 兼容 | 不再支持;V1 用户应停留在 opencode-skill-creator@0.2.x |
| 配置键 | plugins(原生 V2);已存在的 V1 plugin 数组会被保留并继续追加 |
| 本地插件目录 | .opencode/plugins/ 与 .opencode/plugin/ 均会被 V2 发现 |
兼容策略是「V2 专用」而非「单入口同时支持 V1/V2」 。
官方允许一个包同时导出 setup()(V2)与 server()(V1),但本项目选择直接切到 V2:
通过包名与主版本(0.2.x / 0.3.x)区分,避免在同一个入口里维护两套生命周期语义。
3. 插件入口迁移
3.1 V1 形态
ts
import { type Plugin, tool } from "@opencode-ai/plugin"
export const SkillCreatorPlugin: Plugin = async (ctx) => {
ensureBundledSkillInstalled({ /* ... */ })
void maybeAutoRefreshPluginCache()
return {
tool: {
skill_validate: tool({
description: "Validate a skill directory.",
args: {
skillPath: tool.schema.string().describe("Path to the skill directory"),
},
async execute(args) {
return JSON.stringify(validateSkill(args.skillPath), null, 2)
},
}),
// ...其余工具
},
}
}
export default SkillCreatorPlugin
3.2 V2 形态
ts
import { Plugin } from "@opencode/plugin"
export const SkillCreatorPlugin = Plugin.define({
id: "opencode2-skill-creator",
async setup(ctx) {
ensureBundledSkillInstalled({ /* ... */ })
void maybeAutoRefreshPluginCache()
await ctx.tool.transform((editor) => {
editor.add(
defineTool({
name: "skill_validate",
description: "Validate a skill directory.",
properties: {
skillPath: { type: "string", description: "Path to the skill directory" },
},
required: ["skillPath"],
async execute(args) {
return JSON.stringify(validateSkill(args.skillPath), null, 2)
},
}) as never,
)
})
},
})
export default SkillCreatorPlugin
3.3 工具定义适配层
V2 的 input 是 JSON Schema,execute 返回 { content }。项目用 defineTool 统一封装:
ts
function defineTool(spec: ToolSpec) {
return {
name: spec.name,
description: spec.description,
input: {
type: "object",
properties: spec.properties ?? {},
required: spec.required ?? [],
additionalProperties: false,
},
// 只有显式声明 codemode: true,工具才会进入 Code Mode 的工具目录,
// 智能体才能通过 search 发现并调用它们。
options: { codemode: true },
execute: async (input: unknown) => ({
content: await spec.execute((input ?? {}) as Record<string, any>),
}),
}
}
要点:
id必须稳定:V2 用它标识插件、划分存储作用域,并出现在状态与诊断中。ctx.tool.transform的回调保持同步 :它是可重放的「状态编辑」,不应有一次性副作用;
需要外部数据时先在setup中加载,再在回调里引用。codemode: true:这是 V2 Code Mode 的行为开关。本项目所有工具都是给 Code Mode 下的智能体调用的。runtime-entry.ts只做一件事------把skill-creator.ts的默认导出转发出去,
让发布入口保持单一默认导出,而skill-creator.ts仍保留命名导出供测试使用。
4. 上下文能力迁移
V2 的 ctx 既是 OpenCode 客户端,也是插件扩展 API,能力按域组织。本插件用到的关键差异:
| 用途 | V1 做法 | V2 做法 |
|---|---|---|
| 检测已安装技能名冲突 | 执行 opencode debug skill 并解析输出 |
ctx.skill.list() |
| 技能列表结构 | CLI 文本 | { data: [{ name, path }] } |
V1 的冲突检测依赖 shell 调用 opencode debug skill;该命令在 V2 中已不存在。
现在改为直接调用 ctx.skill.list(),读取返回的 data:
ts
const listAvailableSkills = async () => {
const result = await ctx.skill.list()
return result?.data ?? []
}
await assertNoInstalledSkillConflict(meta.name, listAvailableSkills)
冲突检测的语义保持不变:评测会创建一个名为 <skill>-skill-<id> 的合成技能,
如果已安装技能与待测技能同名 ,它可能「抢走」触发,导致假阴性。
因此 skill_eval / skill_optimize_loop 在运行前仍会先检查同名技能并直接报错。
5. 配置与安装适配
5.1 原生 plugins 数组
安装器(bin/opencode2-skill-creator.js)写入 V2 原生的 plugins 数组:
jsonc
{
"plugins": ["opencode2-skill-creator"]
}
同时兼容旧配置:
- 若检测到 V1 的
plugin数组(且没有plugins),则继续追加到plugin,
以保留已有条目并避免被 V2 归一化覆盖。 - 支持
opencode.jsonc,并使用jsonc-parser增量编辑以保留注释与格式。 - 全局安装时清理过期的 OpenCode 包缓存目录
(~/.cache/opencode/packages/opencode2-skill-creator@latest),
并清理桌面端因旧插件加载失败留下的错误通知。
5.2 本地插件目录
V2 从 .opencode/plugin/ 与 .opencode/plugins/ 两处发现本地插件。
推荐把 V2 文件放在 .opencode/plugins/。
5.3 技能目录
技能发现规则在 V2 中不变,仍在 .opencode/skills/<name>/SKILL.md 与全局
~/.config/opencode/skills/<name>/SKILL.md。插件首次启动会把内置技能复制到:
text
~/.config/opencode/skills/opencode2-skill-creator/
6. 重命名与旧版本清理
本次适配同时把项目从 opencode-skill-creator 重命名为 opencode2-skill-creator,
涉及包名、bin、插件 id、技能名/目录、版本标记文件、npm 缓存路径、状态文件与自动更新环境变量。
旧文件夹处理:启动时若发现旧目录且带有插件自有的版本标记
(.opencode-skill-creator-version 或 .opencode2-skill-creator-version),
会将其重命名为非活跃备份,并把 SKILL.md 改为 SKILL.md.backup:
~/.config/opencode/skills/opencode-skill-creator/~/.config/opencode/skills/skill-creator/
若目录没有该标记,则视为第三方或用户手动安装的技能,保持不动。
其它兼容点:
- 旧的环境变量
OPENCODE_SKILL_CREATOR_AUTO_UPDATE仍然生效(新变量为
OPENCODE2_SKILL_CREATOR_AUTO_UPDATE)。 - 安装技能时先复制后安装 ,不用
rename,规避 Windows 上的EPERM。
7. 构建与打包
plugin/scripts/build.mjs 用 Bun 打包为单文件 ESM(dist/skill-creator.js):
bash
bun build ./runtime-entry.ts \
--target=bun \
--format=esm \
--outfile=dist/skill-creator.js \
--external @opencode/plugin
关键点:
- 外部化必须用空格形式
--external @opencode/plugin;
Bun 的--external:<pkg>冒号形式会静默地把依赖打进产物。 - 发布产物是编译后的 JS ,并且会复制
templates/、skill/、package.json,
使 OpenCode 无需在node_modules下剥离 TypeScript。 - 生成
dist/build-manifest.json,记录源码哈希,用于校验dist/是否由当前源码构建。
8. 评测流程在 V2 中的行为
lib/run-eval.ts 通过 shell 调用 opencode run --format json 执行触发评测。
V2 中这条链路仍然成立:
- V2 的
opencode run --format json仍然输出tool_use事件;技能仍以
tool_use且tool === "skill"的形式出现(同时兼容read)。 - 评测会为每个查询创建独立的临时项目根,并用
PWD固定到该临时目录。
原因:opencode依据$PWD解析项目根与项目级技能,
若继承调用方的PWD,真实项目技能可能被加载并抢占触发,导致假 0 分。 - V2 同时从
.opencode/skills/与.opencode/skill/发现技能,
评测镜像项目.opencode配置时会覆盖这两个目录名。 - 触发评测使用显式智能体(默认
build),避免默认智能体委派导致的假 0 分;
若所有 should-trigger 查询零触发且无运行错误,会给出对应告警。
9. 跨平台修复
适配过程中一并修复了若干跨平台问题:
- 校验器容忍 CRLF 的
SKILL.mdfrontmatter。 - 技能安装用复制替代重命名(Windows
EPERM)。 - 打开评审查看器的浏览器失败时不再崩溃。
- 安装器与编译入口点测试在 Windows 上可移植运行。
10. 安装与升级
10.1 全新安装(OpenCode V2)
推荐方式(全局安装,一条命令):
bash
npx opencode2-skill-creator install --global
只想在单个项目启用:
bash
npx opencode2-skill-creator install --project
可选的自检命令:
bash
npx opencode2-skill-creator --version
npx opencode2-skill-creator --help
npx opencode2-skill-creator --about
安装器做了什么:
- 优先更新已存在的
opencode.jsonc,否则创建/更新opencode.json; - 把
"opencode2-skill-creator"加入 V2 原生的plugins数组; - 若检测到旧的 V1
plugin数组(且没有plugins),则追加到plugin以保留已有条目; - 使用 JSONC 增量编辑,保留注释与格式;
- 全局安装时清理过期的 OpenCode 包缓存与桌面端旧插件错误通知。
等价的纯手工配置(全局路径 ~/.config/opencode/opencode.json(c),
项目路径 <项目根>/opencode.json(c)):
jsonc
{
"plugins": ["opencode2-skill-creator"]
}
已有其它插件时,追加而不是替换:
jsonc
{
"plugins": [
"your-existing-plugin",
"opencode2-skill-creator"
]
}
然后重启 OpenCode(插件配置只在启动时加载),并验证:
bash
ls ~/.config/opencode/skills/opencode2-skill-creator/SKILL.md
text
使用 opencode2-skill-creator 创建一个帮助编写 API 文档的技能。
首次启动时,插件会把内置技能自动复制到
~/.config/opencode/skills/opencode2-skill-creator/。
10.2 从 V1(0.2.x)升级到 V2
关键点:包名从 opencode-skill-creator 变成了 opencode2-skill-creator,
旧的 V1 插件条目必须移除------V2 无法运行 V1 插件实现,保留旧条目会导致加载失败。
-
确认已安装 OpenCode 2 。V1 与 V2 默认不再并行安装,二者可执行文件都叫
opencode。 -
删除旧条目 :从配置里去掉
"opencode-skill-creator"。jsonc// 升级前(V1) { "plugin": ["opencode-skill-creator"] } -
安装新版本 (会写入 V2 的
plugins键):bashnpx opencode2-skill-creator install --globaljsonc// 升级后(V2) { "plugins": ["opencode2-skill-creator"] } -
重启 OpenCode。
-
旧技能目录自动归档 :若
~/.config/opencode/skills/下存在带插件标记的opencode-skill-creator/或skill-creator/,启动时会重命名为*.opencode2-skill-creator-backup-<时间戳>/并把SKILL.md改为SKILL.md.backup,使其不再被加载(详见第 6 节)。
-
清理 npm 缓存(可选):若升级后仍加载旧版本,删除 OpenCode 包缓存后重启:
bashrm -rf ~/.cache/opencode/packages/opencode2-skill-creator@latest
提示:V2 在内存中归一化受支持的 V1 配置,不会自动改写源文件。
因此
plugin与plugins可以暂时共存,但转换后不要让 V1 再读取该文件。
10.3 升级到新版本(0.3.x 及以后)
插件内置了自动更新检查:启动时最多每 24 小时查询一次 npm registry,
发现新版本会清理本地包缓存,使下次启动安装最新版。手动升级或强制刷新:
bash
# 重新执行安装器
npx opencode2-skill-creator install --global
# 干净重装技能文件
rm -rf ~/.config/opencode/skills/opencode2-skill-creator/
# 然后重启 OpenCode
关闭自动更新检查:
bash
export OPENCODE2_SKILL_CREATOR_AUTO_UPDATE=0
# 旧变量 OPENCODE_SKILL_CREATOR_AUTO_UPDATE=0 仍然生效
10.4 手动安装(离线 / 不使用 npm)
bash
git clone https://github.com/wqs-base/opencode2-skill-creator.git
cd opencode2-skill-creator
# 安装技能(全局)
cp -r opencode2-skill-creator/ ~/.config/opencode/skills/opencode2-skill-creator/
# 安装插件(全局)
cp -r plugin/ ~/.config/opencode/plugins/skill-creator/
按需创建 ~/.config/opencode/package.json:
json
{
"dependencies": {
"@opencode/plugin": ">=2.0.0"
}
}
10.5 卸载与回滚
- 卸载 :从
plugins数组删除"opencode2-skill-creator",并删除
~/.config/opencode/skills/opencode2-skill-creator/,然后重启 OpenCode。 - 回滚到 V1 :安装
opencode-skill-creator@0.2.x,
并在配置的plugin数组中使用旧包名。注意 V1 与 V2 不能共用同一份已转换为原生 V2 形态的配置。
10.6 常见问题
- 改完配置没反应:完整重启 OpenCode,插件配置只在启动时加载。
- 仍有另一个 skill-creator 技能 :若
~/.config/opencode/skills/skill-creator/没有.opencode2-skill-creator-version
或.opencode-skill-creator-version标记,则它不属于本插件,需单独处理。 npx命令失败 :先运行npx opencode2-skill-creator --help,
再使用install或install --global。- 想彻底重装 :删除
~/.config/opencode/skills/opencode2-skill-creator/后重启。
11. 兼容性速查
| 维度 | V1(0.2.x) | V2(0.3.x) |
|---|---|---|
| 包名 | opencode-skill-creator |
opencode2-skill-creator |
| 插件 API | @opencode-ai/plugin |
@opencode/plugin |
| 配置键 | plugin |
plugins |
| 入口 | Plugin 函数返回 tool 映射 |
Plugin.define({ id, setup }) |
| 工具注册 | tool() + tool.schema |
ctx.tool.transform + JSON Schema |
| 工具返回 | 字符串 | { content } |
| 技能冲突检测 | opencode debug skill |
ctx.skill.list() |
| 技能目录 | .opencode/skills/ |
.opencode/skills/、.opencode/skill/ |
| 本地插件目录 | .opencode/plugins/ |
.opencode/plugins/、.opencode/plugin/ |
12. 参考
- OpenCode V2 总迁移指南:https://opencode.ai/v2/docs/migrate-v1/
- OpenCode 插件 V1 → V2 迁移:https://opencode.ai/v2/docs/build/plugins/migrate-v1
- OpenCode V2 插件总览:https://opencode.ai/v2/docs/build/plugins
项目: