Skip to main content

Server Mode

Quick Start

# Start the API server
opencode serve

# Start with web UI
opencode web

By default the server listens on http://127.0.0.1:4096.

tip

For production, bind to 0.0.0.0 and always set a server password via OPENCODE_SERVER_PASSWORD.

Configuration

Server settings are defined in the server section of opencode.json:

{
"server": {
"port": 4096,
"hostname": "0.0.0.0",
"mdns": true,
"mdnsDomain": "myproject.local",
"cors": ["http://localhost:5173"]
}
}

Options

OptionTypeDefaultDescription
portnumber4096TCP port for the HTTP server
hostnamestring"127.0.0.1"Interface to bind to. Use "0.0.0.0" for all interfaces
mdnsbooleanfalseEnable mDNS discovery on the local network
mdnsDomainstring"opencode.local"mDNS hostname for discovery
corsstring[][]Allowed CORS origins for browser-based clients

Authentication

Set the OPENCODE_SERVER_PASSWORD environment variable to require HTTP Basic authentication for all API requests:

export OPENCODE_SERVER_PASSWORD="my-secret-key"
opencode serve

When set, clients must include the Authorization header:

curl -u "opencode:my-secret-key" http://localhost:4096/api/status

API Endpoints

The headless server exposes a RESTful API:

MethodEndpointDescription
GET/api/statusServer health and configuration info
POST/api/chatSend a message and receive a response
POST/api/chat/streamSend a message and stream the response via SSE
GET/api/sessionsList active sessions
GET/api/sessions/:idGet session details and message history
DELETE/api/sessions/:idDelete a session
GET/api/modelsList available models
GET/api/providersList configured providers
GET/api/agentsList configured agents

Chat Example

curl -X POST http://localhost:4096/api/chat \
-H "Content-Type: application/json" \
-d '{
"message": "Write a Python script to parse a CSV file",
"sessionId": null,
"agent": "build",
"model": "anthropic/claude-sonnet-4"
}'

Streaming Chat Example

curl -X POST http://localhost:4096/api/chat/stream \
-H "Content-Type: application/json" \
-d '{
"message": "Explain how React hooks work",
"sessionId": null
}'

The streaming endpoint uses Server-Sent Events (SSE):

data: {"type":"text","content":"React hooks are functions that..."}
data: {"type":"text","content":" allow you to use state and..."}
data: {"type":"tool_start","tool":"read_file","args":{"path":"..."}}
data: {"type":"tool_end","tool":"read_file","result":"..."}
data: {"type":"done"}

WebSocket Communication

For real-time bidirectional communication, the server supports WebSocket connections at /ws. This is the protocol used by the TUI attach feature and web UI.

const ws = new WebSocket('ws://localhost:4096/ws');

ws.onopen = () => {
ws.send(JSON.stringify({
type: 'chat',
message: 'What is the capital of France?',
sessionId: null
}));
};

ws.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === 'text') {
console.log(data.content);
}
};

Attaching the TUI to a Remote Server

Connect your local terminal UI to a running OpenCode server:

opencode attach http://hostname:4096

If the server requires authentication:

OPENCODE_SERVER_PASSWORD="my-secret-key" opencode attach http://hostname:4096

Scripted Access

Run prompts non-interactively while attaching to a running server:

opencode run --attach http://localhost:4096 "Refactor the auth module to use JWT"

This sends the prompt through the server, streams the response to stdout, then exits. Combine with shell scripts for automation:

#!/bin/bash
result=$(opencode run --attach http://localhost:4096 "$1")
echo "$result" | grep -A5 '```' | head -20

mDNS Discovery

When mdns is enabled, OpenCode advertises itself on the local network. Other OpenCode instances and tools can discover the server automatically:

opencode attach opencode://myproject.local

This is especially useful in team environments where multiple developers share a build server or when running OpenCode on a workstation from a laptop.

CORS

When building web applications that communicate with the OpenCode server, list allowed origins in the cors array:

{
"server": {
"cors": ["http://localhost:5173", "https://my-app.example.com"]
}
}

The server responds with the appropriate Access-Control-Allow-Origin header for matching origins. Credentials (cookies, auth headers) are supported when the origin is explicitly listed.

tip

Use Docker for easy portability or systemd for tighter OS integration on Linux servers.

Docker Deployment

FROM node:20-alpine
RUN npm install -g opencode-ai
EXPOSE 4096
ENV OPENCODE_SERVER_PASSWORD="change-me"
CMD ["opencode", "serve"]
docker build -t opencode-server .
docker run -d -p 4096:4096 --name opencode opencode-server

Systemd Service

[Unit]
Description=OpenCode Server
After=network.target

[Service]
Type=simple
User=opencode
Environment=OPENCODE_SERVER_PASSWORD=change-me
ExecStart=/usr/bin/opencode serve
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target