OpenCode — the harness as a server
The most starred open-source coding agent answers every one of the eleven slots, and answers them the same way: put it in the server. The agent loop is a headless HTTP service with a published OpenAPI contract; the terminal UI, the desktop app, the web viewer, the IDE extension, and the CI job are all thin clients watching one event stream.
Identification
- Repository
- anomalyco/opencode
- Steward
- Anomaly (ex-SST)
- Runtime
- TypeScript on Bun
- Protocol
- HTTP + SSE · OpenAPI at /doc
- Providers
- 75+ via AI SDK + models.dev
- Clients
- TUI · desktop · web · IDE · CI · Slack
LineageThe name has changed hands once. The original opencode-ai/opencode was written in Go by Kujtim Hoxha; Charm hired its author and rebranded that line as Crush. Contributors Dax Raad and Adam of SST — who owned the opencode.ai domain — continued under the OpenCode name at sst/opencode, rewriting the core in TypeScript on Bun; the repo now lives at anomalyco/opencode. Two projects share one ancestry, and the one people mean today is this one.
Read it as
A power plant with many outlets
The engine generates in one place; anything with a plug — TUI, desktop, IDE, CI, Slack — draws from it. Add a client and the plant does not change.
The drawing, in one paragraph
One architectural decision generates everything else on this sheet: the harness is a server. Running the CLI starts a local HTTP service (default 127.0.0.1:4096) plus a terminal client that talks to it; the service publishes an OpenAPI 3.1 spec and streams every step of every session — message parts, tool starts and finishes, diffs, token counts — over a single /event Server-Sent-Events bus. A client is anything that subscribes. That is why one engine can serve a terminal, a desktop app, a live share page, an IDE, and a CI job without forking its logic, and why the rest of the eleven slots read like services: state in SQLite, permissions as policy, sub-agents as child sessions, verification as a language-server fleet wired into the loop.
the plant on the left, the outlets on the right · click to inspect
The examination — eleven slots, one harness
- Built in
- Ships in the core; works with no configuration.
- Via config or extension
- The slot is real but you fill it — config, extension, or convention.
- Deliberately omitted
- Left out on purpose, with a stated argument for the gap.
Rules come from AGENTS.md files; agents themselves are markdown — a file in .opencode/agents/ declares a persona with its own prompt, model, tools, and permission overrides. The primary pair, build and plan, differ exactly there: plan is the same engine with edit and bash turned down to ask.
Built in
AGENTS.md · agents as markdown
The model is handed material by ripgrep-backed grep, glob, line-ranged read, webfetch, and web search. The distinctive delivery channel is the language-server fleet: after an edit, LSP diagnostics flow back into the loop, so the model sees what it just broke without being asked to look.
Built in
ripgrep · glob · LSP diagnostics
Compaction is an explicit checkpoint system. When estimated tokens cross the context limit minus a buffer (20,000 by default), the session's own model writes a structured continuation summary — objective, active work, blockers, next moves — and future requests build from that checkpoint plus what followed. Lossy for the window, never for the record: durable history is kept beneath every checkpoint.
Built in
buffer 20k · keep 8k · checkpoints
Around fourteen built-ins — bash, edit, write, read, grep, glob, patch, web, todo, question, skill, lsp — each a TypeScript module with a Zod schema, and the schemas are served over the API so any client can render a call. MCP servers extend the set, local over stdio or remote over HTTP, with automatic OAuth including dynamic client registration.
Built in
Zod schemas over the API · MCP + OAuth
The boundary is policy, not sandbox. A permission block maps every tool to allow, ask, or deny — with wildcards, per-bash-command patterns, and per-agent overrides — and an ask surfaces as an approval prompt in whichever client is attached. Isolation itself is left to the operator; the harness runs where you run it.
Via config or extension
allow / ask / deny · per-agent overrides
Sessions, messages, parts, and permissions live server-side in SQLite (v1 used JSON files; v2 moved to Drizzle-managed SQLite with a migration path). Around every change the harness takes a git-based snapshot of the worktree, so undo and redo restore both the files and the conversation position together.
Built in
SQLite via Drizzle · git snapshots · /undo
The loop runs in the server and narrates itself: every step is broadcast on the event bus, approval gates pause it, and a question tool lets the model hand a decision back to the human mid-run. Because the contract is HTTP, the same run can be steered from a terminal today and a CI job tomorrow.
Built in
session loop · /event SSE bus
Delegation is session-shaped: the task tool or an @mention spawns a child session running the same loop under a restricted tool and permission set. Three specialists ship — general, read-only explore, and scout — and any user-defined markdown agent can be delegated to the same way.
Built in
child sessions · @mention · explore/scout
Reusable know-how has three registers: SKILL.md skills loaded on demand through a dedicated tool, custom slash commands, and plugins — JavaScript modules from a directory or npm that hook the lifecycle (before and after tool execution, file edits, session events) and can register new tools.
Built in
SKILL.md · plugins · lifecycle hooks
Receipts arrive continuously: the LSP fleet — twenty-eight-plus language servers, auto-downloaded — returns diagnostics after every edit, which is verification wired into the loop rather than bolted after it. And the event bus is the trace: a session shared as a live web page is observability handed to anyone with the link.
Built in
28+ LSPs · live session share
The harness itself does not learn; the configuration accretes. A failure becomes a permission pattern, a repeated workflow becomes an agent file or a plugin hook, a house rule becomes AGENTS.md — all of it markdown and TypeScript in the repo, versioned like the code it governs. Evolution is a commit.
Via config or extension
config as code · versioned rules
Where this design runs out of road
The trade is surface area. A server, an event bus, a database, a git snapshotter, a fleet of language servers, MCP with OAuth, a plugin API — each slot answered in the core means one more moving part, and when a run misbehaves you are debugging a small distributed system. The power plant serves every outlet; it also has to be operated like a plant.
02Side by sideThe comparison table — same eleven slots, opposite fills