Skip to main content
The opencode serve command runs a headless HTTP server that exposes an OpenAPI-compliant REST API. This architecture enables multiple clients (TUI, web, IDE plugins, custom integrations) to interact with the same OpenCode instance programmatically.

Architecture Overview

When you run opencode, it starts both:
  • Server: HTTP API server (Hono + Bun runtime) exposing OpenAPI 3.1 endpoints
  • TUI Client: Terminal interface that communicates with the server via HTTP
This separation allows:
  • Multiple simultaneous clients connecting to one server
  • Programmatic control via HTTP APIs
  • Real-time event streaming via Server-Sent Events (SSE)
  • Cross-platform compatibility (local, remote, containerized)
The TUI and server communicate over HTTP on localhost. When using proxies, you must bypass localhost and 127.0.0.1 to prevent routing loops.

Starting the Server

Standalone Mode

Run a dedicated server without the TUI:
opencode serve --port 4096 --hostname 127.0.0.1
--port
number
default:"4096"
Port to listen on. Use 0 to auto-assign a free port.
--hostname
string
default:"127.0.0.1"
Hostname/IP to bind to. Use 0.0.0.0 to accept connections from any interface (requires authentication).
--mdns
boolean
default:"false"
Enable mDNS (Bonjour) service discovery for local network clients.
--mdns-domain
string
default:"opencode.local"
Custom domain name for the mDNS service announcement.
--cors
string[]
default:"[]"
Additional CORS origins to allow. Can be specified multiple times.

Example with CORS

opencode serve \
  --port 4096 \
  --hostname 0.0.0.0 \
  --cors http://localhost:5173 \
  --cors https://app.example.com

Connect to Existing Server

When starting the TUI, specify connection details:
opencode --hostname 127.0.0.1 --port 4096
The TUI will connect to the existing server instead of starting a new one.

Authentication

HTTP Basic Auth

Protect your server with username/password authentication:
export OPENCODE_SERVER_USERNAME="admin"  # Optional, defaults to "opencode"
export OPENCODE_SERVER_PASSWORD="secure-password-123"
opencode serve --hostname 0.0.0.0
Always use authentication when binding to 0.0.0.0 or exposing the server beyond localhost.
Authentication applies to:
  • opencode serve (standalone server)
  • opencode web (web interface + server)
HTTP clients must include credentials:
curl -u admin:secure-password-123 http://localhost:4096/global/health

Authentication Flow

  1. Server reads OPENCODE_SERVER_PASSWORD at startup
  2. All requests (except OPTIONS preflight) require HTTP Basic Auth
  3. Username defaults to opencode or uses OPENCODE_SERVER_USERNAME
  4. Invalid credentials return 401 Unauthorized

OpenAPI Specification

The server publishes a complete OpenAPI 3.1 spec:
curl http://localhost:4096/doc
This returns an interactive Swagger UI for exploring endpoints.

Using the Spec

Use tools like openapi-generator or swagger-codegen to generate type-safe clients:
# Fetch the spec
curl http://localhost:4096/doc -H "Accept: application/json" > opencode-api.json

# Generate TypeScript client
openapi-generator-cli generate \
  -i opencode-api.json \
  -g typescript-axios \
  -o ./opencode-client
  1. Open Postman/Insomnia
  2. Import → OpenAPI URL
  3. Enter: http://localhost:4096/doc?format=json
  4. All endpoints will be available for testing
Use the spec for contract testing:
import { OpenAPIValidator } from 'express-openapi-validator';

const spec = await fetch('http://localhost:4096/doc?format=json').then(r => r.json());
// Use spec for validation in tests

Core API Endpoints

Health & Events

curl http://localhost:4096/global/health
healthy
boolean
Always true if server is running.
version
string
OpenCode version (e.g., 1.2.3).

Real-time Events (SSE)

curl -N http://localhost:4096/global/event
Server-Sent Events stream providing:
  • server.connected - Initial connection event
  • server.heartbeat - Keepalive every 10 seconds
  • All bus events (session lifecycle, file changes, etc.)
SSE connections include X-Accel-Buffering: no header to prevent proxy buffering issues.

Project Context

curl http://localhost:4096/project/current?directory=/path/to/project
Every request can include a directory parameter (query or header) to scope operations:
# Via query parameter
curl "http://localhost:4096/session?directory=/workspace/app"

# Via header
curl -H "X-Opencode-Directory: /workspace/app" http://localhost:4096/session

Sessions

Create and manage AI conversation sessions:
curl -X POST http://localhost:4096/session \
  -H "Content-Type: application/json" \
  -d '{"title": "Add user authentication"}'
title
string
Session title. Auto-generated if omitted.
parentID
string
Parent session ID for creating branched conversations.

Send Messages

curl -X POST http://localhost:4096/session/abc123/message \
  -H "Content-Type: application/json" \
  -d '{
    "parts": [
      {"type": "text", "text": "Create a login form"}
    ]
  }'
parts
Part[]
required
Array of message parts (text, images, files).
model
string
Override model (format: provider/model, e.g., openai/gpt-4.1).
agent
string
Agent to use (e.g., task, research).
noReply
boolean
Send message without waiting for AI response.

Async Messaging

For fire-and-forget messages, use the async endpoint:
curl -X POST http://localhost:4096/session/abc123/prompt_async \
  -H "Content-Type: application/json" \
  -d '{"parts": [{"type": "text", "text": "Fix the bug"}]}'
# Returns: 204 No Content immediately
Monitor progress via event stream (GET /event).

TUI Control API

Programmatically control the TUI (used by IDE plugins):
curl -X POST http://localhost:4096/tui/append-prompt \
  -H "Content-Type: application/json" \
  -d '{"text": "Add error handling"}'
Available TUI endpoints:
  • /tui/append-prompt - Add text to prompt input
  • /tui/submit-prompt - Submit current prompt
  • /tui/clear-prompt - Clear prompt input
  • /tui/open-sessions - Open session selector
  • /tui/open-models - Open model selector
  • /tui/show-toast - Display notification
  • /tui/execute-command - Run slash command

Advanced Features

File Operations

curl "http://localhost:4096/find?pattern=async%20function"

LSP & Formatters

# LSP server status
curl http://localhost:4096/lsp

# Formatter status
curl http://localhost:4096/formatter

# MCP server status
curl http://localhost:4096/mcp

Session Sharing

curl -X POST http://localhost:4096/session/abc123/share
curl -X DELETE http://localhost:4096/session/abc123/share

Error Handling

The server returns structured errors:
{
  "success": false,
  "errors": [
    {
      "field": "parts",
      "message": "Required"
    }
  ],
  "data": null
}
All errors follow the NamedError pattern with:
  • name - Error class name
  • message - Human-readable description
  • data - Contextual error details

Server Implementation Details

Technology Stack

  • Runtime: Bun (high-performance JavaScript runtime)
  • Framework: Hono (lightweight HTTP framework)
  • WebSockets: Native Bun websocket support
  • SSE: Hono streaming utilities
  • Validation: Zod schemas with hono-openapi

CORS Policy

Default allowed origins:
  • http://localhost:* (any port)
  • http://127.0.0.1:* (any port)
  • tauri://localhost (Tauri desktop apps)
  • https://*.opencode.ai (official web clients)
  • Custom origins via --cors flag

Request Lifecycle

  1. CORS preflight - OPTIONS requests bypass auth
  2. Authentication - HTTP Basic Auth if OPENCODE_SERVER_PASSWORD is set
  3. Logging - Request method and path logged (except /log endpoint)
  4. Instance resolution - Extract directory from query/header, load project instance
  5. Route handler - Execute endpoint logic
  6. Error handling - Convert exceptions to structured JSON responses
  7. Response - JSON or SSE stream

Performance Characteristics

  • Idle timeout: Disabled (connections can stay open indefinitely)
  • SSE heartbeat: 10-second intervals
  • Port fallback: If --port 0, tries 4096 first, then random
  • Graceful shutdown: Unpublishes mDNS before stopping

Use Cases

Custom Clients

Build custom UI clients (mobile apps, web dashboards) using the HTTP API.

CI/CD Integration

Automate code review, testing, and documentation generation in pipelines.

IDE Plugins

Create editor extensions that communicate with OpenCode server.

Remote Development

Run OpenCode server on remote machines, connect from local clients.

Next Steps

Network Configuration

Configure proxies, certificates, and mDNS discovery.

Session Sharing

Learn about sharing sessions and collaboration features.

JavaScript SDK

Use the official TypeScript/JavaScript SDK for type-safe API access.

Troubleshooting

Diagnose and fix common server issues.