OpenCode brands itself “the open source AI coding agent,” and the repository backs the claim with unusual breadth: it started as the agent from the SST team, it is now maintained under the anomalyco organization, and a single install command, curl -fsSL https://opencode.ai/install | bash, or npm i -g opencode-ai@latest, puts a full coding agent in your terminal. The code is MIT-licensed TypeScript on Bun, organized as a monorepo of dozens of packages that cover the terminal UI, the agent engine, a server, a generated SDK, an Electron desktop app, a plugin host, and more. The project moved from its original home to the anomalyco organization, and every badge and install formula in the README now points there, which is the address this tour uses.

Two design choices separate this codebase from the crowd. First, the agent is client-server by construction: the terminal UI talks to an HTTP server with server-sent events, the desktop app embeds the same server, and a generated TypeScript SDK wraps it all, so any surface gets identical behavior. Second, the model layer is deliberately vendor-neutral: provider and model metadata come from the community models.dev catalog, and a dedicated llm package implements the wire protocols of Anthropic, OpenAI, Google, Bedrock, Azure, GitHub Copilot, OpenRouter, xAI, and any OpenAI-compatible endpoint, so switching models is a flag, not a migration.

As always in this series, this is an educational tour of published source code. OpenCode reads your files, runs shell commands, and edits code with model guidance, and the project pairs that power with a permission engine, a read-only plan agent, and explicit approval flows for a reason. Run it on projects you own, read what it asks before it acts, and study how the guardrails are wired into the loop, because that is half of what a production agent really is.

OpenCode overview architecture diagram

OpenCode at a glance: CLI, terminal UI, desktop app, and SDK all meet an HTTP server that fronts one session engine, which streams from the provider layer and executes tools under a permission gate.

Reading the overview from left to right:

Why You Need This

The first reason is the client-server architecture. Most terminal coding agents bolt a UI onto an agent loop and call it done; OpenCode instead makes an HTTP server with an event stream the center of the system, and makes the terminal UI, the desktop app, and the SDK all clients of it. The consequences are practical: you can attach a second client to a running server, you can script sessions against the same API the TUI uses, and you can read one of the cleanest live examples of how to stream agent state over server-sent events. If you have ever wondered how to build an agent that more than one interface can drive, this repo is the reference.

The second reason is vendor neutrality done at the protocol level. The provider resolver reads its catalog from models.dev, the community-maintained model database, and the llm package implements each provider’s actual wire format, including Anthropic’s messages protocol and OpenAI’s chat and responses protocols, as ordinary code you can read. That design means model switching is a --model provider/name flag, custom endpoints are an OpenAI-compatible entry, and new providers are one file rather than a refactor. For anyone building multi-model tooling, this layer alone is worth a long study.

The third reason is the honesty of its safety model. The README documents two built-in agents: build, the default with full access, and plan, a read-only agent that denies file edits and asks permission before running shell commands, switchable with the Tab key. Underneath, a permission engine evaluates tool calls against configurable rules before they execute. This is a codebase that treats autonomy as something you dial in per project, and the mechanics of that dialing, from config files to approval prompts, are all in the open.

How It Works

OpenCode detailed architecture diagram

Inside OpenCode: the CLI and TUI over an HTTP server with SSE events, the session engine and its prompt loop, the tool registry under permission rules, the models.dev-backed provider layer, and the MCP, ACP, and plugin extension surfaces.

Understanding the Architecture

A CLI that boots a server. The yargs entrypoint at packages/opencode/src/index.ts dispatches commands; run.ts handles scripted prompts with flags for model, agent, JSON output format, session continuation, and attaching to an already-running server, while session.ts manages listing and deleting saved conversations. With no arguments, the binary launches the terminal UI. The run command starts a local server at packages/opencode/src/server/server.ts, which mounts the routes under packages/opencode/src/server/routes and publishes every state change as events through packages/opencode/src/server/event.ts.

A session engine with durable state. The session module at packages/opencode/src/session/session.ts is the orchestrator, and its v2 design, described in the repository’s own AGENTS.md, keeps durable prompt admission separate from model execution: an incoming prompt is admitted as a persistent record before a serialized runner promotes it into a model turn. The prompt loop at packages/opencode/src/session/prompt.ts assembles context through packages/opencode/src/session/system.ts, makes one explicit llm.stream call per provider turn, and folds results back in; compaction.ts summarizes overflowing history; the storage layer persists sessions so they can be listed, resumed, forked, or exported.

Agents as first-class profiles. packages/opencode/src/agent/agent.ts defines the built-in build and plan agents and loads custom ones from project config, each carrying its own model, prompt, and permission posture. The task tool at packages/opencode/src/tool/task.ts spawns subagents, including the general-purpose search agent the README says you can invoke with @general, so heavy work happens in scoped child sessions instead of derailing the main thread.

A tool registry with a leash. Built-in tools live as individual files under packages/opencode/src/tool, covering shell execution, file editing, reading, glob and grep search, web fetching, and more, all registered in packages/opencode/src/tool/registry.ts. Before execution, the permission engine’s evaluate logic at packages/opencode/src/permission/evaluate.ts checks the call against the configured rules, and edit tools consult the LSP bridge at packages/opencode/src/lsp for diagnostics and the formatter bridge at packages/opencode/src/format to keep changes clean. MCP servers from packages/opencode/src/mcp/index.ts register remote tools into the same registry, and plugins add their own hooks from outside the process.

Models without lock-in. The provider resolver at packages/opencode/src/provider/provider.ts reads provider and model metadata from the models.dev catalog in packages/core/src/models-dev.ts, resolves credentials from config or plugin auth hooks, and hands a concrete request to the llm core at packages/llm/src/llm.ts. That core picks a wire protocol from packages/llm/src/protocols, which includes Anthropic messages, OpenAI chat, OpenAI responses, and Google’s format, then routes to the provider implementation such as anthropic.ts or openai.ts in packages/llm/src/providers. Editors integrate through the ACP service at packages/opencode/src/acp/service.ts, and the whole dependency direction, from schema through core and protocol to server, is spelled out in AGENTS.md as the monorepo’s architectural rule.

Advantages

  • Client-server by design. Terminal UI, desktop app, and SDK are all clients of one HTTP server, so every surface behaves identically and remote attachment comes free.
  • No vendor lock-in. The models.dev catalog plus per-provider wire protocol implementations make switching or mixing models a one-flag operation.
  • Safety you can configure. The read-only plan agent, per-agent permission rules, and explicit approval flows let you dial autonomy per project.
  • Session durability. Prompts are admitted as persistent records before execution, so sessions survive, resume, fork, and export cleanly.
  • Extension surfaces everywhere. MCP servers, ACP editors, and a plugin host with tool and auth hooks cover the standard integration points.
  • A real SDK. The TypeScript client is generated from the server’s OpenAPI spec, keeping API consumers in sync automatically.

Benefits

  • Readable reference architecture. The split into schema, core, protocol, server, and client packages is documented as an explicit dependency rule you can learn from.
  • Bun-fast, TypeScript-familiar. The stack runs on Bun with standard TypeScript, so most web developers can trace the whole system in an afternoon.
  • Terminal-native performance. The TUI is a GPU-rendered SolidJS app that stays responsive while streaming model output and tool activity.
  • Multi-surface from one codebase. The Electron desktop app and the terminal reuse the same engine, showing how to ship two products from one core.
  • Community catalog. Relying on models.dev ties the tool to a living database of providers rather than a hardcoded list that goes stale.
  • License and provenance. MIT-licensed code under the anomalyco organization, with every install path and badge pointing at the current home.

Usage

Install with the one-line script or a package manager:

curl -fsSL https://opencode.ai/install | bash
npm i -g opencode-ai@latest

Start the interactive terminal UI in your project directory:

opencode

Give a one-shot prompt with a chosen model and agent, or ask for raw JSON events for scripting:

opencode run "Explain the failure in tests/auth.spec.ts"
opencode run -m anthropic/claude-sonnet-4-5 --agent plan "Review the auth module and list risks"
opencode run --format json "List all TODO comments"

Continue an earlier session, or attach to a server that is already running:

opencode run -c "Now apply the fix you suggested"
opencode run --attach http://localhost:4096 "Check the logs"

Manage providers and credentials, list models, and inspect agents:

opencode auth login
opencode auth list
opencode models
opencode agent list

Add an MCP server, manage saved sessions, or run the server standalone:

opencode mcp add docs --url https://example.com/mcp
opencode mcp list
opencode session list
opencode serve

Conclusion

OpenCode is the rare agent codebase where the architecture is the feature: an HTTP server with an event stream sits at the center, every interface is a client of it, sessions are durable by design, and the model layer treats vendors as swappable protocol implementations rather than identity. Read it to learn how to structure a client-server agent, how to implement multi-provider streaming without lock-in, or how to make permissions a configurable property of agents rather than a hardcoded afterthought. Then run it, because a coding agent this open deserves to be studied with your hands on the keyboard.

Links:

Watch PyShine on YouTube

Contents