migrate-v1.mdx 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  1. ---
  2. title: "Migrate from V1"
  3. ---
  4. OpenCode 1 and OpenCode 2 can be installed side by side. V1 runs as `opencode`, while V2 installs and runs separately as
  5. `opencode2`.
  6. ## Breaking changes
  7. V2 has three intentional breaking changes:
  8. - [Plugins](#plugins) use a new plugin API.
  9. - The [server API and clients](#server-api-and-clients) have new contracts.
  10. - [Terminal client configuration](/cli/config) moves from layered `tui.json(c)` files to one global `cli.json` file (auto
  11. migrated).
  12. Supported V1 functionality outside those areas is intended to remain compatible with V1. Some fields accepted by the V1
  13. schema never had a V2 equivalent and are intentionally ignored; these are listed under
  14. [Accepted but unsupported fields](#accepted-but-unsupported-fields).
  15. Existing supported server config fields, agent definitions, command definitions, skills, and other files in `.opencode/`
  16. should continue to work without changes. If supported behavior described in this guide stops working in V2, treat it as a
  17. beta compatibility bug rather than an expected migration requirement.
  18. <Callout type="tip">
  19. If supported V1 functionality does not work in V2, follow the issue-reporting guidance in
  20. [Troubleshooting](/troubleshooting) and file a compatibility issue.
  21. </Callout>
  22. <Callout type="warning">
  23. OpenCode 2.0 is in beta. Features may break unintentionally, and the server and plugin APIs may continue to change.
  24. </Callout>
  25. ## Install the beta
  26. The V2 terminal client is published on the `beta` distribution tag. See the [terminal startup guide](/cli).
  27. ## Configuration
  28. This section covers both JSON/JSONC configuration and file-based definitions under `.opencode/`.
  29. ### Use your existing configuration
  30. V2 reads existing global and project configuration from the same locations as V1:
  31. ```text
  32. ~/.config/opencode/opencode.json(c)
  33. <project>/opencode.json(c)
  34. <project>/.opencode/opencode.json(c)
  35. ```
  36. V2 reads these same locations. It normalizes supported V1 and native V2 fields in memory without rewriting the source
  37. file. Existing supported V1 configuration is intended to keep working, so you do not need to convert it to try or adopt
  38. V2.
  39. ### Ask OpenCode to migrate
  40. The V1 config format remains supported. The native V2 format is optional and makes several settings more explicit and
  41. ergonomic.
  42. The recommended migration path is to ask OpenCode to update the configuration for you:
  43. ```text
  44. Migrate my OpenCode configuration, including file-based definitions, from the V1 format to the native V2 format.
  45. Preserve its behavior and all unrelated settings.
  46. ```
  47. OpenCode can inspect the complete file, apply the relevant changes below, and avoid rewriting settings that do not need to
  48. change. Conversion does not need to happen all at once: supported V1 and native V2 fields may coexist at the top level.
  49. When both forms set the same canonical value, a valid native V2 value takes precedence regardless of JSON key order.
  50. Nested mixing is intentionally bounded. OpenCode recognizes mixed V1 and V2 members within `mcp`, `compaction`, and
  51. `experimental`, but it does not recursively infer formats inside individual agents, providers, commands, or models. Keep
  52. each of those nested entries entirely in one format. Supported V1 syntax remains quiet by itself; malformed values,
  53. unsupported legacy fields, and conflicting V1/V2 values produce warnings while unrelated valid settings continue to load.
  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. ### Media
  133. Rename the singular `attachment` object to `media`. Nested image settings keep the same names:
  134. ```jsonc
  135. // V1
  136. { "attachment": { "image": { "auto_resize": true } } }
  137. // V2
  138. { "media": { "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` keeps its name. V2 has no native `tail_turns` or `prune` field; both legacy fields are ignored with a warning. Recent
  195. context is retained by token budget instead. 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. V2 consolidated two legacy provider namespaces:
  278. | V1 provider ID | Canonical V2 provider ID |
  279. | -------------------------- | ------------------------ |
  280. | `azure-cognitive-services` | `azure` |
  281. | `google-vertex-anthropic` | `google-vertex` |
  282. Migration of unambiguous V1 provider, agent, command, and provider-filter fields uses these canonical IDs. The shared
  283. top-level `model` field keeps its exact provider ID because the same syntax is valid in native V2 config; update that field
  284. to the canonical ID when migrating a legacy built-in provider.
  285. ### Models and variants
  286. Models remain nested under their provider, but several model fields become more explicit:
  287. - `id` becomes `modelID`.
  288. - `tool_call` and `modalities` become `capabilities.tools`, `capabilities.input`, and `capabilities.output`.
  289. - A `status` of `"deprecated"` becomes `disabled: true`.
  290. - Cache costs move from `cache_read` and `cache_write` to `cache.read` and `cache.write`.
  291. - Provider-specific `options` become `settings`.
  292. - A V1 variants object becomes a V2 array with an `id` on each entry.
  293. ```jsonc
  294. // V1
  295. {
  296. "variants": {
  297. "high": {
  298. "reasoningEffort": "high"
  299. }
  300. }
  301. }
  302. // V2
  303. {
  304. "variants": [
  305. {
  306. "id": "high",
  307. "settings": {
  308. "reasoningEffort": "high"
  309. }
  310. }
  311. ]
  312. }
  313. ```
  314. See [Models](/models) for the complete native model shape.
  315. ### Supported fields without direct native equivalents
  316. Most fields that keep the same shape, including `shell`, `model`, `default_agent`, `autoupdate`, `watcher`, `formatter`,
  317. `lsp`, `instructions`, `enterprise`, and `tool_output`, require no migration.
  318. The V1 provider filters do not have one-to-one native V2 config fields, but their behavior remains supported:
  319. - `enabled_providers` becomes an internal deny-by-default provider policy followed by allows for the listed providers.
  320. - `disabled_providers` becomes internal deny policies for the listed providers.
  321. - `small_model` becomes the `model` selection for the built-in `title` agent. Native V2 configuration should use
  322. `agents.title.model` instead.
  323. You may keep these fields in V1 syntax. OpenCode normalizes them without warning.
  324. ### Accepted but unsupported fields
  325. The V1 schema also accepted fields that have no supported V2 behavior. V2 ignores these values and emits a warning so
  326. they are not mistaken for active configuration:
  327. - `logLevel`: use `OPENCODE_LOG_LEVEL` when starting OpenCode.
  328. - `server`: use the V2 service and explicit server options; the server API is an intentional breaking change.
  329. - Top-level `subagent_depth`: use `experimental.subagent_depth` instead.
  330. - `compaction.tail_turns` and `compaction.prune`: V2 uses `compaction.keep.tokens` and checkpoint-based compaction instead.
  331. - Agent `name` inside V1 JSON configuration.
  332. - An enabled-only V1 MCP entry without a `type`.
  333. - V1 experimental fields `batch_tool`, `openTelemetry`, `primary_tools`, and `continue_loop_on_deny`.
  334. - V1 provider fields `id`, `whitelist`, and `blacklist`.
  335. - V1 provider-model fields `release_date`, `attachment`, `reasoning`, `temperature`, `experimental`, a non-`deprecated`
  336. `status`, and boolean `interleaved`.
  337. Ignoring these fields is intentional and is not a compatibility regression. If V2 does not preserve behavior identified
  338. as supported elsewhere in this guide, follow the issue-reporting guidance in [Troubleshooting](/troubleshooting).
  339. ### Agent files
  340. V1 agent files may use `agent/`, `agents/`, `mode/`, or `modes/`. V2 still discovers all four directories. The preferred
  341. V2 location is:
  342. ```text
  343. .opencode/agents/<name>.md
  344. ```
  345. Files under a V1 `mode/` or `modes/` directory represent primary agents. When moving one into `agents/`, add
  346. `mode: primary` to its frontmatter. Files under `agent/` can move to `agents/` without changing their path-derived ID.
  347. When converting the frontmatter to native V2 fields:
  348. - Keep the Markdown body as the agent's system instructions.
  349. - Rename `prompt` to `system` when it appears in JSON configuration; file bodies do not need a `system` field.
  350. - Rename `disable` to `disabled` and `permission` to `permissions`.
  351. - Join `model` and `variant` as `provider/model#variant`.
  352. - Move `temperature`, `top_p`, and provider-specific options under `request.body`.
  353. V2 translates legacy agent frontmatter automatically, so these edits are optional. See [Agents](/agents).
  354. ### Command files
  355. V1 command files may use `command/` or `commands/`. V2 discovers both. The preferred location is:
  356. ```text
  357. .opencode/commands/<name>.md
  358. ```
  359. Move files from `command/` to the same relative path under `commands/` to preserve command names. The Markdown body remains
  360. the command template, and `description`, `agent`, and `subtask` frontmatter keep the same names. If frontmatter has separate
  361. `model` and `variant` fields, append the variant to the model and remove `variant`:
  362. ```yaml
  363. # V1
  364. model: anthropic/claude-sonnet-4-5
  365. variant: high
  366. # V2
  367. model: anthropic/claude-sonnet-4-5#high
  368. ```
  369. See [Commands](/commands).
  370. ### Skill files
  371. V2 discovers skills from both `.opencode/skill/` and `.opencode/skills/`. The preferred layout is:
  372. ```text
  373. .opencode/skills/<skill-id>/SKILL.md
  374. ```
  375. Move the complete skill directory, not only `SKILL.md`, so relative scripts, references, and other supporting files remain
  376. available. Keep the directory name stable to preserve the skill ID. Existing skill frontmatter and Markdown bodies do not
  377. require a V2 rewrite. See [Skills](/skills).
  378. ### Instruction files
  379. Existing `AGENTS.md` files stay in place. V2 discovers the global `~/.config/opencode/AGENTS.md` and ambient `AGENTS.md`
  380. files from the current directory up to home. For projects outside home, discovery stops at the project root.
  381. If a V1 setup relied on a `CLAUDE.md` fallback, move that guidance into the applicable `AGENTS.md`. V2 currently only
  382. discovers `AGENTS.md`; because non-API V1 behavior is intended to remain compatible, also file a compatibility issue with
  383. the affected project details. See [Instructions](/instructions).
  384. ## Terminal client configuration
  385. V2 replaces layered V1 `tui.json(c)` files with one global terminal client configuration file:
  386. ```text
  387. ~/.config/opencode/cli.json
  388. ```
  389. The terminal client owns this file; the background service does not load it. When `cli.json` is absent, the first V2
  390. terminal client startup migrates supported global `tui.json` settings and persisted preferences while leaving V1 files
  391. unchanged. Project-local client configuration is not migrated because V2 client configuration is global. See
  392. [CLI config](/cli/config) for current client settings.
  393. ## Plugins
  394. Rename `plugin` to `plugins`. Replace a package-and-options tuple with an object:
  395. ```jsonc
  396. // V1
  397. {
  398. "plugin": [
  399. "opencode-example-plugin",
  400. ["./plugin/local.ts", { "enabled": true }]
  401. ]
  402. }
  403. // V2
  404. {
  405. "plugins": [
  406. "opencode-example-plugin",
  407. {
  408. "package": "./plugin/local.ts",
  409. "options": { "enabled": true }
  410. }
  411. ]
  412. }
  413. ```
  414. V2 discovers local plugins from both `.opencode/plugin/` and `.opencode/plugins/`; use `.opencode/plugins/` for V2 files.
  415. Moving a file between these directories does not migrate its implementation.
  416. <Callout type="warning">V1 plugins will not work in V2.</Callout>
  417. The config entry can be translated automatically, but plugin implementation code must be ported to the new API. The V2
  418. plugin API is still being finalized during beta, and detailed plugin migration guidance will be published when it is
  419. ready.
  420. Once the V2 plugin API is finalized, OpenCode should be able to migrate the majority of V1 plugins while keeping related
  421. local modules and dependencies together. See the current beta [Plugins guide](/build/plugins).
  422. ## Server API and clients
  423. OpenCode 2 has a revised, more ergonomic server API and a new set of clients. Integrations that call the V1 server API
  424. must migrate to the V2 API.
  425. Use the `@opencode-ai/client` package to access the new clients. The server API and clients are still being finalized
  426. during beta, so their contracts may continue to change. See the generated [API reference](/api) for the current endpoints,
  427. request types, and responses.
  428. ## Verify your setup
  429. Verify your model, provider credentials, agents, permissions, MCP servers, and plugins in a project before relying on the
  430. beta for regular work. Keep your V1 setup until you have confirmed the V2 behavior you need, and do not point V1 at
  431. configuration that you have converted to the native V2 shape.