OpenCode 2: What's New and What Breaks
AIDevOpsOpenCode 2 arrived on npm at @opencode/cli on 11 September 2026. By 14 October it had reached 2.0.29 — 29 releases in 32 days. Yet npm install -g opencode-ai still installs 1.19.0, and the default installer on opencode.ai still pulls 1.x. Release 1.19.0 exists mainly to hand you one command: opencode upgrade --major. If you run it, you are on 2.x. The changelog lists only 2.x releases now, and Anomaly's docs treat 2.x as the present. So: what changed, what broke, and how our SAIA plugin stayed ahead of both.
Note on naming: the old opencode-ai/opencode project is archived and continued as Crush by Charmbracelet. This article is about Anomaly's anomalyco/opencode — the
@opencode/clipackage on npm.
The Shared-Service Rewrite
OpenCode 2 introduces one long-running background service. Terminal, desktop and web UI all attach to the same process. State lives in ~/.local/state/opencode/service.json, session history in ~/.local/share/opencode/opencode.db. The service starts on demand and can be controlled with opencode service start|stop|status. Use opencode pair to expose the local service to another host via OpenTunnel — you get a QR code or copyable link. Sessions opened in one UI appear in all of them.
For programmeers, OpenCode 2 exposes a JSON-over-HTTP API with Server-Sent Events for streaming session logs. There is an official @opencode/client package that auto-discovers the local service. OpenCode 2 can even call its own API to create git worktrees, move sessions or interrupt runaway ones. An embeddable @opencode/sdk spins up the same engine in-memory, so you can run OpenCode inside your own Node.js/Bun process or on a Cloudflare Worker.
The Three Intentional Breaking Changes
1. Plugin API
V1 plugins export a function or a Plugin object. V2 plugins default-export a definition with id and a setup(ctx) function. The server prints a WARN for every V1 module it tries to load — then keeps running with the plugin absent.
// V1 (does not load in V2)
export const MyPlugin: Plugin = async ({ project, client, $ }) => ({
"tool.execute.before": (input) => { /* ... */ },
});
// V2 (required shape)
export default {
id: "acme.hello",
async setup(ctx) {
await ctx.tool.hook("execute.before", (event) => { /* ... */ });
},
};
V2 still discovers the V1-era directories (~/.config/opencode/plugin/ singular as well as .opencode/plugins/ plural). On first start it also auto-installs @opencode-ai/plugin into ~/.config/opencode/package.json so plugins can declare dependencies.
2. CLI Config: tui.json becomes global cli.json
V1 used layered tui.json files per workspace. V2 flattens terminal settings into one global cli.json. The migration is automatic — but only on the first TUI start, not during a headless command. Legacy fields are normalised in memory on read:
| Legacy field (V1 / project) | Normalised field (V2 / global) |
|---|---|
permission: { bash: "ask", edit: "allow" } | permissions: [{ action: "shell", resource: "*", effect: "ask" }] |
mcp: { server: { enabled: false } } | mcp.servers: { server: { disabled: true } } |
provider: | providers: |
agent: or mode: | agents: |
compaction.preserve_recent_tokens | compaction.keep.tokens |
3. Server API and Client Libraries
Custom server clients need @opencode/client instead of the V1 contracts. Anything talking to the old API must port; if you do not run a server client, this break is invisible.
What Is New in 2.0.28–29
- Automatic response continuation — outputs that hit a provider's output-token limit now continue automatically from the continuation checkpoint
- Remote device pairing via OpenTunnel — Settings → Pairing gives a QR code or copyable link; other hosts connect to your local service
- Provider account management — switch, rename, remove or add provider accounts from Settings → Providers or the connect dialog
- Trackpad image navigation — pinch-zoom and two-finger scroll pan SVG / image previews, with a Fit to reset
- Stable
policieskey — moved fromexperimental.policiesto top-level - Per-project auto-accept permissions — override defaults per project;
mod+shift+atoggles in-session, or set in Settings → Projects - Release highlights in TUI —
/highlightsreopens the notes after an upgrade; disable withhighlights: falseincli.json - Native Windows ARM64 — CLI, desktop and bundled terminal use native ARM64 builds
- WinGet packages —
winget install --id Anomaly.OpenCode -eor-e Anomaly.OpenCode.Desktop - Continuous response streaming — split long responses from Google Vertex/Vertex-Gemini now stream as one response
- Built-in worktree tools —
worktree_create,worktree_list,worktree_remove
Code Mode: MCP Servers as Callable Functions
Code Mode (@opencode/codemode) is a lightweight interpreter that lets agents write short scripts importing MCP tool calls and OpenAPI endpoints as plain functions, chaining them in one round-trip. All MCP servers opt into Code Mode by default (codemode: false to opt out). The sandbox has no filesystem, dynamic imports, timers or fetch — only the tools passed to it. The payoff is collapsing multi-turn tool-planning conversations into one concise workflow.
Background sub-agents (background: true) can return immediately while they continue working, and background shell commands run without a default timeout. Hit Ctrl+B to move the current foreground agent to background.
Dual V1+V2: How the opencode-saia-plugin Keeps Working
OpenCode's own migration guide explicitly allows a dual-export pattern: one package can expose both a V1 server() function and a V2 setup() inside a default export.
Our opencode-saia-plugin (mirror on Codeberg) does exactly this. Since v0.4.0, it exports a default with id + setup(ctx) for V2 and retains a server() entry-point for V1 ≥1.18.29. The plugin registers once in each era's config — cli.json (plugins key, V2) and tui.json (plugin key, V1).
SAIA is the GWDG Chat AI public academic service in Göttingen. The plugin fetches the live SAIA model list through the public API, auto-generates an opencode.json with 14 models organised by role (reasoning, coder, vision, medical, research, agentic, large-context, general), then copies the result to your project directory so OpenCode sees it. The default is saia/deepseek-v4-flash-0731 with 1M-token context and reasoning support. A live TUI quota counter reads the SAIA API's x-ratelimit-remaining-* headers and prints the headroom in the prompt bar:
27/m · 117/h · 519/d · 2.5k/mo
A minimal project configuration alongside the injected SAIA models looks like this:
{
"$schema": "https://opencode.ai/config.json",
"plugins": ["opencode-saia-plugin"],
"permissions": [
{ "action": "shell", "resource": "*", "effect": "ask" }
]
}
Because one codebase exposes both plugin contracts, the same release works unchanged on OpenCode 1.x today and 2.x tomorrow.
LSP support
V1 would start language servers and produce LSP diagnostics. V2 keeps the lsp configuration key for backward compatibility, but does not run language servers or produce diagnostics. Run your linter, type checker or compiler through shell/edit tools instead.
Upgrade Path
- From 1.19.0: run
opencode upgrade --major - Fresh install:
curl -fsSL https://opencode.ai/v2/install | bashornpm install -g @opencode/cli - macOS (Homebrew):
brew install anomalyco/tap/opencode-v2 - Windows:
winget install --id Anomaly.OpenCode -e
Try it in a throwaway HOME first — V2 creates new files (package.json, node_modules, .gitignore, cli.json, service.json) on the first two starts. Always back up your existing ~/.config/opencode before upgrading.
Existing Resources on graphwiz.ai
We have practical guides that complement this overview:
- Vibe Coding with OpenCode, oh-my-opencode and Superpowers skills
- Zot vs Pi vs OpenCode: A Hard Look at AI Coding Agent Harnesses
Verdict
OpenCode 2 is the version where Anomaly now ship all new features. It ships every 1–2 days. Upgrading from 1.19.0 is a single command. If you have no V1 plugins and no server clients, it is effectively friction-free. Plugin maintainers need a small export rewrite (default { id, setup } and domain-specific registrations) and a little testing against the V2 surfaces. The three intentional breaks are visible: plugin WARN at start-up, cli.json created on first TUI start, and server clients must move to @opencode/client. Our opencode-saia-plugin proves the dual-export pattern works: one codebase serving both 1.x users and 2.x adopters without interventions.
FAQ
Is OpenCode 2.0 considered stable?
As of 14 October 2026 Anomaly have not labelled it "stable", but the changelog lists only 2.x releases, 1.19.0 is purely a bridge release to hand you the --major upgrade path, and Anomaly ship regular dot-releases. The shell installers at opencode.ai still default to 1.x, while the v2 install path is at opencode.ai/v2/install.
Do V1 plugins still work with OpenCode 2.x?
No. V2 implements a new plugin API. V1 plugin exports are silently rejected (WARN level) and never load. Porting is usually small: switch to a default export with id and setup(ctx), then reregister hooks through domain methods (ctx.tool.hook, etc.).
What breaks when I upgrade to OpenCode 2.x?
Three intentional breaking changes: ① plugin API (v1 exports do not load), ② CLI config (tui.json → one global cli.json, migration runs only on first TUI session), and ③ server API (@opencode/client replaces the v1 contracts). In practice, V2 also no longer runs LSP servers or produces LSP diagnostics, keeping the key but not the functionality — use linter/compile commands instead.
Disclosure: The author maintains the opencode-saia-plugin referenced above, which supports OpenCode 2.0 since v0.4.0.