Architecture Overview
OpenCode v2 is a monorepo built around a client-server architecture. A managed background service owns sessions, configuration, plugins, permissions, and tool execution. Client interfaces (TUI, desktop, web) connect to this service over HTTP.
System Topology
The lifecycle shell binds before the application boots. This lets clients distinguish a slow winner from an absent server during startup.
Package Structure
V2 separates concerns across packages. V1 lives in packages/opencode for reference only.
| Package | Role |
|---|---|
packages/core | Application behavior: sessions, agents, tools, permissions, plugins, config |
packages/server | HTTP transport, routes, handlers, auth, middleware |
packages/protocol | API contracts, groups, middleware, error types |
packages/schema | Schema definitions for sessions, permissions, events, agents |
packages/cli | CLI entry point, service config, daemon management |
packages/tui | Terminal user interface (Solid) |
packages/client | Generated TypeScript HTTP client |
packages/sdk-next | In-process Effect-native SDK (no HTTP listener) |
packages/plugin | Plugin API for extending OpenCode |
packages/ai | Provider-neutral LLM abstraction (@opencode-ai/ai) |
packages/app | Web app |
packages/desktop | Desktop application |
Gotcha: The default branch is
v2, notdevormain. Base all new branches onv2ororigin/v2.
Runtime Dependency Direction
Dependencies flow in one direction: Schema to Core and Protocol, then Core and Protocol to Server. Client runtime code depends on Schema and Protocol but never Core or Server. The sdk-next package composes Client, Core, and Server.
Service Election
The managed V2 service uses a process-held OS lock to elect exactly one server owner for its lifetime. This replaced the earlier heartbeat lease approach after incident #36688.
| Concept | Authority |
|---|---|
| Ownership | Process-held OS lock (flock on POSIX, named pipe on Windows) |
| Discovery | Registration file with endpoint URL |
| Lifecycle | Minimal HTTP shell bound before application boot |
Key invariants:
- Only one process may hold the service lock per installation channel
- A contender performs no expensive initialization before acquiring the lock
- The lock is held for the entire process lifetime
- Transport loss is retryable - never a terminal error for TUIs
- Only a fresh TUI launch enforces package version (existing TUIs reconnect)
Service Status
The server reports a status discriminant that clients use for reconnection logic:
| Status | Meaning |
|---|---|
starting | Owner acquired lock, application boot in progress |
ready | Application initialized, serving normally |
stopping | Graceful replacement in progress |
failed | Boot failed; owner stays bound with diagnostic message |
During starting or stopping, application requests get an immediate 503 with Retry-After: 1.