OpenCode 2 不是版本号更新, 是一次重写。官方迁移文档只承认 三个故意的破坏性变更: 新的插件 API、新的 server API 契约、tui.json(c) 分层文件合并为单个全局 cli.json。其余部分设计上都要继续工作——v2 读取 v1 的配置位置并在内存里归一化旧键, 所以转换成原生 v2 形态是可选的。本指南把每个面对照清楚。
安装与共存
两个版本的二进制都叫 opencode, 默认不再并排安装——先卸载包管理器装的 v1; v2 的 curl 安装脚本会替换 v1 二进制。
| 方式 |
v1 |
v2 |
| 安装脚本 |
curl -fsSL https://opencode.ai/install | bash |
curl -fsSL https://opencode.ai/v2/install | bash |
| npm 包 |
opencode-ai |
@opencode/cli |
| Homebrew |
anomalyco/tap/opencode |
anomalyco/tap/opencode-v2 |
| Arch/AUR |
opencode / opencode-bin |
opencode-beta |
| mise |
mise use -g github:anomalyco/opencode |
mise use -g opencode(需要 mise ≥ 2026.10.9, 旧版会装成 v1) |
| Windows |
choco / scoop / npm |
包管理器不支持, 只有二进制下载 |
| Docker |
ghcr.io/anomalyco/opencode |
ghcr.io/anomalyco/opencode:2.0.0(按版本打 tag) |
配置位置——没有变
v2 读取与 v1 相同的系统、全局和项目配置位置——/etc/opencode、/Library/Application Support/opencode、%ProgramData%\opencode、macOS 托管偏好 ai.opencode.managed、~/.config/opencode/opencode.json(c)、项目 opencode.json(c) 与 .opencode/opencode.json(c)。每个被发现的 .opencode 配置都覆盖所有直接配置, 不只是同目录的。托管配置依旧最高优先; v2 里真正“限制”用户的方式是 policies 而不是普通设置。
逐键对照
Agents 与 modes
| v1 |
v2 |
agent 对象; mode map |
agents——mode 条目变成 primary agent |
prompt |
system |
disable |
disabled |
permission(对象) |
permissions——有序 {action, resource, effect} 规则, 末条胜出 |
tools |
permissions——false 变成 deny 规则 |
variant(独立字段) |
并入模型引用——provider/model#high |
temperature、top_p、options |
归入 request.body——注意: v2 运行器会保留这些值但尚不随请求发送; 生效的请求设置请配置在 provider/model/variant 上 |
maxSteps |
steps |
内置 scout |
移除 |
agent/、agents/、mode/、modes/ 目录 |
四种都还会被扫描; 首选 .opencode/agents/——mode(s)/ 里的文件是 primary agent, 迁移后加 mode: primary; 文件正文无需 system 字段 |
| 平铺 agent id |
嵌套目录命名——team/reviewer |
权限
| v1 |
v2 |
permission 对象 |
permissions 有序规则列表 |
动作 bash、task |
shell、subagent——write/patch 也并入 edit |
.env 读取默认 deny |
.env 读取默认 ask |
external_directory 默认 ask |
默认 allow——要保持 v1 行为需加 { "action": "external_directory", "resource": "*", "effect": "ask" } |
doom_loop、lsp 键 |
不再是 v2 动作 |
| todos 始终开启 |
默认关闭——experimental.todo: true |
enabled_providers / disabled_providers |
policies 声明 |
MCP 服务器
| v1 |
v2 |
mcp.<name> 平铺 |
mcp.servers.<name> 嵌套 |
enabled |
disabled(语义取反) |
timeout 单值 |
timeout: { catalog, execution }; experimental.mcp_timeout 作为默认值来源 |
OAuth clientId、clientSecret、callbackPort、redirectUri |
client_id、client_secret、callback_port、redirect_uri |
交互式 mcp add |
旗标式 mcp add --url/--env/--header/--global |
| (无) |
/mcps 在应用内管理服务器 |
命令
| v1 |
v2 |
command map |
commands |
subtask |
subagent(旧 subtask 仍被接受); 委托命令自动在后台运行并把结果汇报给父会话 |
variant 字段 |
model#variant |
command/、commands/ 目录 |
都会被扫描; 首选 commands/ |
| 仅平铺命令名 |
目录即命名空间——team/review.md → /team/review |
@file 在存储时展开 |
调用时才附加 |
| 新增文件要重启 |
保存即热加载 |
终端客户端——tui.json → cli.json
v1 已经把 TUI 设置分层放在 tui.json(c)(全局和项目本地)。v2 合并为单个全局 ~/.config/opencode/cli.json——终端客户端独占该文件, server 不加载, 首次启动 v2 TUI 会自动迁移全局 tui.json 的设置且不动 v1 文件。项目本地客户端配置不会被迁移, 因为 v2 客户端配置只有全局一层。内部: keybinds 取值形式不变("none"/false 解绑, key/event/preventDefault/fallthrough 对象)但命令 id 从 snake_case 换成点分式(app_exit→app.exit, input_paste→prompt.paste), leader_timeout 变成平级的顶层 leader.timeout; 另有 theme、session、tabs、diffs、attention、plugins 等。环境变量也变了形态: v1 OPENCODE_TUI_CONFIG 指向文件路径; v2 OPENCODE_CLI_CONFIG_CONTENT 携带内联 JSON 合并进 cli.json。
插件与 provider
| v1 |
v2 |
plugin 数组 |
plugins——元组形态变成 { "package", "options" } 对象 |
.opencode/plugin/ 目录 |
.opencode/plugins/(两种都扫描) |
| v1 插件代码可运行 |
v1 插件在 v2 不能运行——按插件迁移指南改造 |
provider |
providers; id/whitelist/blacklist 字段被忽略 |
provider npm |
package——AI SDK 包加 aisdk: 前缀 |
provider api |
settings.baseURL |
provider options |
按用途拆成 settings / headers / body; options.setCacheKey→compatibility.supportsPromptCacheKey |
| provider id |
合并——azure-cognitive-services→azure, google-vertex-anthropic→google-vertex(顶层 model 保持原 id, 需自行更新) |
| model 字段 |
id→modelID · tool_call/modalities→capabilities.{tools,input,output} · status:"deprecated"→disabled: true · cache_read/cache_write→cache.read/cache.write · options→settings · variants 对象→带 id 的数组 |
small_model |
agents.title.model |
杂项改名、同形与忽略
|
|
| 改名/提升 |
snapshot→snapshots · attachment→media · autoupdate→update(notify/auto/disable) · reference→references(v1 本就接受复数形) · experimental.policies→policies(v1 键仍合并生效) · skills 对象 {paths, urls} → 平铺数组 · compaction.preserve_recent_tokens→keep.tokens + reserved→buffer |
| 同形无需迁移 |
tool_output、instructions、shell、formatter、watcher、model、default_agent、enterprise |
| 带警告忽略 |
server(用 v2 service + 显式 server 选项; v1 API 是破坏性变更——集成应迁移到 @opencode/client)、logLevel(改用 OPENCODE_LOG_LEVEL 环境变量)、顶层 subagent_depth(改用 experimental.subagent_depth)、agent 的 name、无 type 的 enabled-only MCP 条目、compaction.tail_turns/prune、experimental batch_tool/openTelemetry/primary_tools/continue_loop_on_deny、provider id/whitelist/blacklist、provider-model release_date/attachment/reasoning/temperature/experimental/非 deprecated 的 status/布尔 interleaved |
| v2 新增 |
warming、websearch、worktree、username |
| 形同虚设 |
lsp 配置被接受并保留但 v2 不运行语言服务器——改用 lint/typecheck 命令 |
| 备注 |
/share TUI 命令已不在命令文档列表中; share 配置键仍在 schema 里(manual/auto/disabled), 与 enterprise.url 并存 · v1 的 CLAUDE.md 回退在 v2 不会被发现——把它并入 AGENTS.md(v2 发现全局 + 向上到 home 的 AGENTS.md; home 之外的项目发现截止于项目根) · skill 目录: .opencode/skill/ + .opencode/skills/ 都会扫描, 迁移时移动整个目录 · v1/v2 键混用有边界——只有 mcp/compaction/experimental 会递归归一化; 冲突时原生 v2 值胜出 · 顶层 model 不接受 #variant 后缀 |
产品面
| v1 |
v2 |
| OpenCode Zen(精选模型, 按请求计费) |
OpenCode Console |
| — |
OpenCode Go——$10/月订阅 |
TUI + opencode web + IDE 扩展 + 桌面应用 |
TUI + 桌面应用 + opencode pair Web UI(一次性链接, 5 分钟过期) |
文档 opencode.ai/docs/ |
文档 opencode.ai/v2/docs/——CLI 设置归入 /cli/ |
迁移清单
按官方文档, 你可以保留 v1 配置直接启动 v2——转换是可选的。实操顺序:
- 保留现有配置和文件定义; 启动 v2; 验证模型、凭据、agents、权限、MCP 服务器。
- 移植插件——v1 实现不能运行。
- 调用 v1 server API 的集成迁移到
@opencode/client。
- 准备好后再把配置转成原生 v2 形态——或者直接让 opencode 来做: 它能应用上述映射且不动无关设置。
- 验证期间保留 v1 配置副本——两版读相同位置, 转成 v2 专属形态后别让 v1 再指向这些文件。
- 复查
external_directory——v1 默认 ask 而 v2 默认 allow。
延伸阅读