migrate-v1.mdx 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576
  1. ---
  2. title: "Migrate from V1"
  3. description: "Move from OpenCode V1 to the OpenCode 2.0 beta."
  4. ---
  5. ## Breaking changes
  6. V2 has three intentional breaking changes:
  7. - [Plugins](#plugins) use a new plugin API.
  8. - The [server API and clients](#server-api-and-clients) have new contracts.
  9. - [TUI configuration](#tui-configuration) moves from layered `tui.json(c)` files to one global `cli.json` file (auto migrated).
  10. All other functionality is intended to remain compatible with V1.
  11. Existing server config files, agent definitions, command definitions, skills, and other files in `.opencode/` should
  12. continue to work without changes. If one of these stops working in V2, treat it as a beta compatibility bug rather than
  13. an expected migration requirement.
  14. <Tip>
  15. Run `/report` if existing V1 functionality does not work in V2. The report skill collects diagnostics and helps you file
  16. a compatibility issue.
  17. </Tip>
  18. <Warning>
  19. OpenCode 2.0 is in beta. Beta data may be wiped, features may break unintentionally, and the server and plugin APIs may
  20. continue to change.
  21. </Warning>
  22. During the beta, OpenCode V1 and V2 use different executable names. You can keep using `opencode` for V1 while trying V2
  23. with `opencode2`.
  24. ## Install the beta
  25. Install the beta from the `next` distribution tag:
  26. ```bash
  27. npm install -g @opencode-ai/cli@next
  28. ```
  29. Start it in your project with:
  30. ```bash
  31. opencode2
  32. ```
  33. ## Configuration
  34. This section covers both JSON/JSONC configuration and file-based definitions under `.opencode/`.
  35. ### Use your existing configuration
  36. V2 reads existing global and project configuration from the same locations as V1:
  37. ```text
  38. ~/.config/opencode/opencode.json(c)
  39. <project>/opencode.json(c)
  40. <project>/.opencode/opencode.json(c)
  41. ```
  42. V2 reads these same locations. It detects V1-shaped configuration and translates it in memory without rewriting the
  43. source file. Existing V1 configuration is intended to keep working, so you do not need to convert it to try or adopt V2.
  44. ### Ask OpenCode to migrate
  45. The V1 config format remains supported. The native V2 format is optional and makes several settings more explicit and
  46. ergonomic.
  47. The recommended migration path is to ask OpenCode to update the configuration for you:
  48. ```text
  49. Migrate my OpenCode configuration, including file-based definitions, from the V1 format to the native V2 format.
  50. Preserve its behavior and all unrelated settings.
  51. ```
  52. OpenCode can inspect the complete file, apply the relevant changes below, and avoid rewriting settings that do not need to
  53. change. Do not mix V1 and V2 field names manually in one file.
  54. ### Sharing
  55. The deprecated V1 `autoshare` boolean becomes the explicit `share` policy:
  56. ```jsonc
  57. // V1
  58. { "autoshare": true }
  59. // V2
  60. { "share": "auto" }
  61. ```
  62. Use `"manual"`, `"auto"`, or `"disabled"`. If the V1 file already uses `share`, no change is needed.
  63. ### Permissions and tools
  64. V1 groups permission effects by tool. V2 uses one ordered `permissions` array, making precedence and exceptions explicit:
  65. ```jsonc
  66. // V1
  67. {
  68. "permission": {
  69. "bash": {
  70. "git push *": "ask"
  71. },
  72. "edit": "allow"
  73. },
  74. "tools": {
  75. "websearch": false
  76. }
  77. }
  78. // V2
  79. {
  80. "permissions": [
  81. { "action": "shell", "resource": "git push *", "effect": "ask" },
  82. { "action": "edit", "resource": "*", "effect": "allow" },
  83. { "action": "websearch", "resource": "*", "effect": "deny" }
  84. ]
  85. }
  86. ```
  87. Permission actions also changed: `bash` is now `shell`, `task` is now `subagent`, and `write` and `patch` are now `edit`.
  88. See [Permissions](/permissions) for the ordered V2 rule format.
  89. ### Agents and modes
  90. The singular `agent` and deprecated `mode` maps become `agents`. Agent fields become more consistent with the rest of the
  91. V2 config:
  92. ```jsonc
  93. // V1
  94. {
  95. "agent": {
  96. "reviewer": {
  97. "prompt": "Review for correctness and missing tests.",
  98. "model": "anthropic/claude-sonnet-4-5",
  99. "variant": "high",
  100. "disable": false,
  101. "permission": {
  102. "edit": "deny"
  103. }
  104. }
  105. }
  106. }
  107. // V2
  108. {
  109. "agents": {
  110. "reviewer": {
  111. "system": "Review for correctness and missing tests.",
  112. "model": "anthropic/claude-sonnet-4-5#high",
  113. "disabled": false,
  114. "permissions": [
  115. { "action": "edit", "resource": "*", "effect": "deny" }
  116. ]
  117. }
  118. }
  119. }
  120. ```
  121. `prompt` becomes `system`, `disable` becomes `disabled`, and a separate `variant` joins the model reference after `#`.
  122. `temperature`, `top_p`, and provider-specific `options` move under `request.body`. `maxSteps` becomes `steps`. Entries from
  123. the old `mode` map become primary agents.
  124. ### Snapshots
  125. Rename the singular `snapshot` field to `snapshots`. Its boolean value does not change:
  126. ```jsonc
  127. // V1
  128. { "snapshot": false }
  129. // V2
  130. { "snapshots": false }
  131. ```
  132. ### Attachments
  133. Rename the singular `attachment` object to `attachments`. Nested image settings keep the same names:
  134. ```jsonc
  135. // V1
  136. { "attachment": { "image": { "auto_resize": true } } }
  137. // V2
  138. { "attachments": { "image": { "auto_resize": true } } }
  139. ```
  140. ### MCP servers
  141. V2 groups servers under `mcp.servers`, replaces `enabled` with the inverse `disabled`, and separates timeout purposes:
  142. ```jsonc
  143. // V1
  144. {
  145. "mcp": {
  146. "playwright": {
  147. "type": "local",
  148. "command": ["npx", "@playwright/mcp"],
  149. "enabled": true,
  150. "timeout": 30000
  151. }
  152. }
  153. }
  154. // V2
  155. {
  156. "mcp": {
  157. "servers": {
  158. "playwright": {
  159. "type": "local",
  160. "command": ["npx", "@playwright/mcp"],
  161. "disabled": false,
  162. "timeout": {
  163. "catalog": 30000,
  164. "execution": 30000
  165. }
  166. }
  167. }
  168. }
  169. }
  170. ```
  171. Remote OAuth fields use snake case: `clientId` becomes `client_id`, `clientSecret` becomes `client_secret`,
  172. `callbackPort` becomes `callback_port`, and `redirectUri` becomes `redirect_uri`. The V1 `experimental.mcp_timeout` value
  173. also becomes the default `mcp.timeout.catalog` and `mcp.timeout.execution` values. See [MCP servers](/mcp-servers).
  174. ### Compaction
  175. V2 groups the retained-context token budget under `keep` and gives the reserve a clearer name:
  176. ```jsonc
  177. // V1
  178. {
  179. "compaction": {
  180. "preserve_recent_tokens": 8000,
  181. "reserved": 20000
  182. }
  183. }
  184. // V2
  185. {
  186. "compaction": {
  187. "keep": {
  188. "tokens": 8000
  189. },
  190. "buffer": 20000
  191. }
  192. }
  193. ```
  194. `auto` and `prune` keep their names. V2 has no native `tail_turns` field; recent context is retained by token budget instead.
  195. See [Compaction](/compaction).
  196. ### Skills
  197. V1 separates extra skill paths and URLs. V2 combines both into one ordered array:
  198. ```jsonc
  199. // V1
  200. {
  201. "skills": {
  202. "paths": ["./team-skills"],
  203. "urls": ["https://example.com/skills/"]
  204. }
  205. }
  206. // V2
  207. {
  208. "skills": ["./team-skills", "https://example.com/skills/"]
  209. }
  210. ```
  211. Existing skill files and automatic `.opencode/skills/` discovery do not change. See [Skills](/skills).
  212. ### Commands
  213. Rename the singular `command` map to `commands`. Join a separate model `variant` to the model reference:
  214. ```jsonc
  215. // V1
  216. {
  217. "command": {
  218. "review": {
  219. "template": "Review the current changes.",
  220. "model": "anthropic/claude-sonnet-4-5",
  221. "variant": "high"
  222. }
  223. }
  224. }
  225. // V2
  226. {
  227. "commands": {
  228. "review": {
  229. "template": "Review the current changes.",
  230. "model": "anthropic/claude-sonnet-4-5#high"
  231. }
  232. }
  233. }
  234. ```
  235. `template`, `description`, `agent`, and `subtask` keep their names. Existing Markdown command definitions remain supported.
  236. See [Commands](/commands).
  237. ### References
  238. Rename the deprecated singular `reference` map to `references`:
  239. ```jsonc
  240. // V1
  241. { "reference": { "docs": "../docs" } }
  242. // V2
  243. { "references": { "docs": "../docs" } }
  244. ```
  245. V1 already accepts `references`, so no change is needed when the file uses it. Reference entries keep the
  246. same shapes. See [References](/references).
  247. ### Providers
  248. Rename the singular `provider` map to `providers`. V2 separates the runtime package, endpoint, and request settings:
  249. ```jsonc
  250. // V1
  251. {
  252. "provider": {
  253. "acme": {
  254. "npm": "@ai-sdk/openai-compatible",
  255. "api": "https://llm.example.com/v1",
  256. "options": {
  257. "apiKey": "{env:ACME_API_KEY}"
  258. }
  259. }
  260. }
  261. }
  262. // V2
  263. {
  264. "providers": {
  265. "acme": {
  266. "package": "aisdk:@ai-sdk/openai-compatible",
  267. "settings": {
  268. "baseURL": "https://llm.example.com/v1",
  269. "apiKey": "{env:ACME_API_KEY}"
  270. }
  271. }
  272. }
  273. }
  274. ```
  275. V1 `npm` becomes `package`, and AI SDK packages receive the `aisdk:` prefix. `api` becomes `settings.baseURL`. Provider
  276. `options` are separated into `settings`, `headers`, and `body` according to their request role. See [Providers](/providers).
  277. ### Models and variants
  278. Models remain nested under their provider, but several model fields become more explicit:
  279. - `id` becomes `modelID`.
  280. - `tool_call` and `modalities` become `capabilities.tools`, `capabilities.input`, and `capabilities.output`.
  281. - A `status` of `"deprecated"` becomes `disabled: true`.
  282. - Cache costs move from `cache_read` and `cache_write` to `cache.read` and `cache.write`.
  283. - Provider-specific `options` become `settings`.
  284. - A V1 variants object becomes a V2 array with an `id` on each entry.
  285. ```jsonc
  286. // V1
  287. {
  288. "variants": {
  289. "high": {
  290. "reasoningEffort": "high"
  291. }
  292. }
  293. }
  294. // V2
  295. {
  296. "variants": [
  297. {
  298. "id": "high",
  299. "settings": {
  300. "reasoningEffort": "high"
  301. }
  302. }
  303. ]
  304. }
  305. ```
  306. See [Models](/models) for the complete native model shape.
  307. ### Fields without native equivalents
  308. Most fields that keep the same shape, including `shell`, `model`, `default_agent`, `autoupdate`, `watcher`, `formatter`,
  309. `lsp`, `instructions`, `enterprise`, and `tool_output`, require no migration.
  310. These V1 fields do not have one-to-one native V2 config fields:
  311. - `logLevel`: use `OPENCODE_LOG_LEVEL` when starting OpenCode.
  312. - `server`: use the V2 service and explicit server options; the server API is an intentional breaking change.
  313. - `layout`: remove it; V1 already treated it as deprecated and always used stretch layout.
  314. - `enabled_providers` and `disabled_providers`: there is no native provider allowlist or denylist field yet.
  315. - `small_model`: V2 selects models for internal maintenance agents without a separate top-level field.
  316. - `compaction.tail_turns`: V2 uses `compaction.keep.tokens` instead.
  317. If your V1 configuration relies on a field without a native equivalent, keep using the supported V1 format rather than
  318. forcing a manual conversion. Run `/report` if V2 does not preserve the behavior you rely on.
  319. ### Agent files
  320. V1 agent files may use `agent/`, `agents/`, `mode/`, or `modes/`. V2 still discovers all four directories. The preferred
  321. V2 location is:
  322. ```text
  323. .opencode/agents/<name>.md
  324. ```
  325. Files under a V1 `mode/` or `modes/` directory represent primary agents. When moving one into `agents/`, add
  326. `mode: primary` to its frontmatter. Files under `agent/` can move to `agents/` without changing their path-derived ID.
  327. When converting the frontmatter to native V2 fields:
  328. - Keep the Markdown body as the agent's system instructions.
  329. - Rename `prompt` to `system` when it appears in JSON configuration; file bodies do not need a `system` field.
  330. - Rename `disable` to `disabled` and `permission` to `permissions`.
  331. - Join `model` and `variant` as `provider/model#variant`.
  332. - Move `temperature`, `top_p`, and provider-specific options under `request.body`.
  333. V2 translates legacy agent frontmatter automatically, so these edits are optional. See [Agents](/agents).
  334. ### Command files
  335. V1 command files may use `command/` or `commands/`. V2 discovers both. The preferred location is:
  336. ```text
  337. .opencode/commands/<name>.md
  338. ```
  339. Move files from `command/` to the same relative path under `commands/` to preserve command names. The Markdown body remains
  340. the command template, and `description`, `agent`, and `subtask` frontmatter keep the same names. If frontmatter has separate
  341. `model` and `variant` fields, append the variant to the model and remove `variant`:
  342. ```yaml
  343. # V1
  344. model: anthropic/claude-sonnet-4-5
  345. variant: high
  346. # V2
  347. model: anthropic/claude-sonnet-4-5#high
  348. ```
  349. See [Commands](/commands).
  350. ### Skill files
  351. V2 discovers skills from both `.opencode/skill/` and `.opencode/skills/`. The preferred layout is:
  352. ```text
  353. .opencode/skills/<skill-id>/SKILL.md
  354. ```
  355. Move the complete skill directory, not only `SKILL.md`, so relative scripts, references, and other supporting files remain
  356. available. Keep the directory name stable to preserve the skill ID. Existing skill frontmatter and Markdown bodies do not
  357. require a V2 rewrite. See [Skills](/skills).
  358. ### Instruction files
  359. Existing `AGENTS.md` files stay in place. V2 discovers the global `~/.config/opencode/AGENTS.md` and project `AGENTS.md`
  360. files from the current directory up to the project root.
  361. If a V1 setup relied on a `CLAUDE.md` fallback, move that guidance into the applicable `AGENTS.md`. V2 currently only
  362. discovers `AGENTS.md`; because non-API V1 behavior is intended to remain compatible, also run `/report` with the affected
  363. project details. See [Instructions](/instructions).
  364. ## TUI configuration
  365. V1 loaded `tui.json(c)` from the global config directory and from project directories discovered while walking up from
  366. the current directory. V2 instead stores CLI and TUI settings in one global file:
  367. ```text
  368. ~/.config/opencode/cli.json
  369. ```
  370. The CLI owns this file. The background service does not load it, and V2 does not discover or merge project-local
  371. `tui.json(c)` or `cli.json` files.
  372. The native V2 format groups related settings. For example:
  373. ```jsonc
  374. // V1: ~/.config/opencode/tui.json
  375. {
  376. "theme": "tokyonight",
  377. "scroll_speed": 2,
  378. "scroll_acceleration": {
  379. "enabled": true
  380. }
  381. }
  382. // V2: ~/.config/opencode/cli.json
  383. {
  384. "theme": {
  385. "name": "tokyonight"
  386. },
  387. "scroll": {
  388. "speed": 2,
  389. "acceleration": true
  390. }
  391. }
  392. ```
  393. V2 migrates the global TUI configuration automatically. On the first CLI or TUI startup, when `cli.json` does not already
  394. exist, it:
  395. - Reads `~/.config/opencode/tui.json`.
  396. - Reads persisted TUI preferences from the legacy `kv.json` state file.
  397. - Converts supported settings to the native grouped format and writes `~/.config/opencode/cli.json`.
  398. - Leaves the V1 files unchanged so V1 can continue using them.
  399. Migration runs only while `cli.json` is absent. Once that file exists, V2 treats it as the source of truth and does not
  400. continually synchronize later changes from `tui.json` or `kv.json`. If you created `cli.json` before starting V2, merge any
  401. V1 settings you still need into it manually.
  402. Project-local V1 TUI configuration is not migrated because V2 has no project-local CLI configuration. Move settings you
  403. still want into the global `cli.json`; when multiple projects used different values for the same setting, choose the
  404. global behavior you want V2 to use.
  405. ## Plugins
  406. Rename `plugin` to `plugins`. Replace a package-and-options tuple with an object:
  407. ```jsonc
  408. // V1
  409. {
  410. "plugin": [
  411. "opencode-example-plugin",
  412. ["./plugin/local.ts", { "enabled": true }]
  413. ]
  414. }
  415. // V2
  416. {
  417. "plugins": [
  418. "opencode-example-plugin",
  419. {
  420. "package": "./plugin/local.ts",
  421. "options": { "enabled": true }
  422. }
  423. ]
  424. }
  425. ```
  426. V2 discovers local plugins from both `.opencode/plugin/` and `.opencode/plugins/`; use `.opencode/plugins/` for V2 files.
  427. Moving a file between these directories does not migrate its implementation.
  428. <Warning>V1 plugins will not work in V2.</Warning>
  429. The config entry can be translated automatically, but plugin implementation code must be ported to the new API. The V2
  430. plugin API is still being finalized during beta, and detailed plugin migration guidance will be published when it is
  431. ready.
  432. Once the V2 plugin API is finalized, OpenCode should be able to migrate the majority of V1 plugins while keeping related
  433. local modules and dependencies together. See the current beta [Plugins guide](/build/plugins).
  434. ## Server API and clients
  435. OpenCode 2 has a revised, more ergonomic server API and a new set of clients. Integrations that call the V1 server API
  436. must migrate to the V2 API.
  437. Use the `@opencode-ai/client` package to access the new clients. The server API and clients are still being finalized
  438. during beta, so their contracts may continue to change. See the generated [API reference](/api) for the current endpoints,
  439. request types, and responses.
  440. ## Verify your setup
  441. Start `opencode2` in a project and verify your model, provider credentials, agents, permissions, MCP servers, and plugins
  442. before relying on the beta for regular work. Keep your V1 setup until you have confirmed the V2 behavior you need, and do
  443. not point V1 at configuration that you have converted to the native V2 shape.