Skip to specification

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

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

10 parts · every selection is linkable
FIG. 1 — the harness as a server. The engine and its stores on the left; the /event bus in the middle; every client an outlet on the same circuit.

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.
  1. 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

  2. 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

  3. 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

  4. 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

  5. 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

  6. 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

  7. 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

  8. 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

  9. 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

  10. 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

  11. 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

Read from — every finding traces to one of these

UnitT01
Fills9 built in · 2 adapted · 0 omitted
Read againstThe Harness — eleven primitives