OpenCode can run as a headless HTTP server or as an ACP (Agent Client Protocol) server for editor integration. Both modes share the same core services — the difference is the transport layer.
Start a REST API server compatible with the @opencode-ai/sdk/v2 TypeScript SDK:
opencode serve| Flag | Default | Description |
|---|---|---|
--port |
4096 |
Port to listen on |
--hostname |
127.0.0.1 |
Hostname to bind to |
--cors |
* |
Allowed CORS origin |
--cwd, -c |
current dir | Working directory |
--debug, -d |
false |
Enable debug logging |
Set the OPENCODE_SERVER_PASSWORD environment variable to require HTTP Basic Auth on all requests:
OPENCODE_SERVER_PASSWORD=mysecret opencode serveClients authenticate with any username and the password as the password field. When the variable is unset, authentication is disabled.
| Method | Path | Description |
|---|---|---|
| GET | /global/health |
Health check (returns {"healthy": true, "version": "..."}) |
| GET | /global/event |
Global SSE event stream |
| Method | Path | Description |
|---|---|---|
| GET | /session |
List all sessions |
| POST | /session |
Create a new session |
| GET | /session/status |
Get busy/idle status of all sessions |
| GET | /session/{sessionID} |
Get a session by ID |
| DELETE | /session/{sessionID} |
Delete a session |
| PATCH | /session/{sessionID} |
Update session title |
| POST | /session/{sessionID}/abort |
Cancel the active agent run |
| Method | Path | Description |
|---|---|---|
| GET | /session/{sessionID}/message |
List messages in a session |
| GET | /session/{sessionID}/message/{messageID} |
Get a specific message |
| POST | /session/{sessionID}/message |
Send a prompt (sync — waits for agent to complete) |
| POST | /session/{sessionID}/prompt_async |
Send a prompt (async — returns immediately) |
| POST | /session/{sessionID}/summarize |
Trigger session summarization |
| Method | Path | Description |
|---|---|---|
| GET | /event |
SSE event stream (per-project) |
Connect to /event or /global/event to receive real-time updates. Events are sent as data: {...}\n\n frames with a 30-second heartbeat.
Event types:
message.created,message.updated,message.deletedsession.created,session.updated,session.deletedpermission.asked
Each event payload has type and properties fields:
{"type": "message.updated", "properties": {"info": {...}, "parts": [...]}}| Method | Path | Description |
|---|---|---|
| GET | /config |
Get current config (active model) |
| GET | /config/providers |
List all providers and models |
| Method | Path | Description |
|---|---|---|
| POST | /permission/{requestID}/reply |
Grant or deny a permission request |
Request body: {"allow": true} or {"allow": false}
| Method | Path | Description |
|---|---|---|
| GET | /agent |
List all registered agents |
OpenWork is a desktop UI that can connect to our opencode fork via the HTTP REST API.
OpenWork can spawn and manage the opencode serve process automatically. Set the binary path and run:
OPENWORK_OPENCODE_BIN=/path/to/opencode pnpm devOpenWork will:
- Find a free port and spawn
opencode serve --hostname 127.0.0.1 --port <port> --cors "*" - Wait for the
opencode server listening on http://...stdout sentinel - Set up Basic Auth using auto-generated credentials via
OPENCODE_SERVER_PASSWORD - Proxy all
/opencode/*requests from the UI to the opencode server
Config: OpenWork spawns opencode with cwd set to its managed workdir inside Application Support. To use your existing .opencode.json, symlink it there:
# macOS (dev build)
ln -sf ~/.opencode.json \
~/Library/Application\ Support/com.differentai.openwork.dev/managed-opencode-workdir/.opencode.jsonStart your own server and point OpenWork to it:
# Terminal 1: start opencode
OPENCODE_SERVER_PASSWORD=mysecret opencode serve --port 4096
# Terminal 2: start OpenWork, pointing to your server
OPENWORK_OPENCODE_BASE_URL=http://127.0.0.1:4096 \
OPENWORK_OPENCODE_PASSWORD=mysecret \
pnpm devOr for the desktop app, set these env vars before launching:
| Variable | Description |
|---|---|
OPENWORK_OPENCODE_BASE_URL |
URL of your running opencode server |
OPENWORK_OPENCODE_PASSWORD |
Password for Basic Auth (matches OPENCODE_SERVER_PASSWORD) |
OPENWORK_OPENCODE_USERNAME |
Username for Basic Auth (optional, any value works) |
OPENWORK_OPENCODE_DIRECTORY |
Working directory for session scoping |
OPENWORK_OPENCODE_BIN |
Path to opencode binary (for managed mode) |
OPENWORK_MANAGED_OPENCODE_CWD |
Override cwd for managed opencode (CLI mode only) |
- MCP display: OpenWork reads MCP server config directly from the workspace
.opencode.jsonfile, looking for anmcpkey (dax format). Our fork usesmcpServers. MCP servers work at runtime but won't appear in OpenWork's MCP panel. - Session directory: OpenWork scopes sessions by directory using the
X-Opencode-Directoryheader. Sessions created via the TUI use the project directory; sessions created via OpenWork use the managed workspace directory. They appear as separate session lists.
Start an Agent Client Protocol server for editor integration:
opencode acpACP uses JSON-RPC 2.0 over stdio with newline-delimited JSON (NDJSON) framing. This is the protocol used by AionUI, Zed, JetBrains, and other ACP-compatible editors.
| Flag | Default | Description |
|---|---|---|
--cwd, -c |
current dir | Working directory |
--debug, -d |
false |
Enable debug logging |
Messages use newline-delimited JSON (NDJSON) — one JSON-RPC message per line:
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}
Messages MUST NOT contain embedded newlines. Each message is terminated by \n.
| Method | Description |
|---|---|
initialize |
Handshake — returns agent capabilities and info |
session/new |
Create a new session |
session/load |
Load an existing session (replays messages) |
session/list |
List available sessions |
session/close |
Close a session and cancel any active run |
session/resume |
Resume a previous session |
session/prompt |
Send a user prompt (blocks until agent completes) |
session/cancel |
Cancel an in-progress prompt (notification, no response) |
The server sends session/update notifications with real-time updates:
agent_message_chunk— text from the assistantagent_thought_chunk— reasoning/thinking contenttool_call— new tool call startedtool_call_update— tool call status change (pending/in_progress/completed/failed)permission_request— permission needed for a tool call
AionUI is a desktop app that auto-detects CLI agents on your system and connects via ACP.
Setup: Just have opencode on your PATH. AionUI will:
- Detect the
opencodebinary viawhich opencode - Spawn
opencode acpwith stdin/stdout wired for JSON-RPC - Send
initialize, thensession/newto start a conversation
No configuration needed — AionUI's built-in agent list includes OpenCode with acpArgs: ["acp"].
If opencode is installed somewhere not on PATH, set the binary path in AionUI's settings or add it to PATH:
# Add to ~/.zshrc or ~/.bashrc
export PATH="$PATH:/path/to/opencode/bin"Any ACP-compatible client can connect:
- Zed — ACP-compatible editor
- JetBrains IDEs with ACP plugin support
- Custom integrations — spawn
opencode acpand communicate via NDJSON on stdio
All logging goes to stderr to avoid corrupting the JSON-RPC protocol stream on stdout.