Server Mode
OpenCode can run as a headless HTTP server, enabling remote access, CI/CD integration, web-based UIs, and programmatic control. Two subcommands are available: serve for API-only mode and web for a built-in web interface.
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.
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
| Option | Type | Default | Description |
|---|---|---|---|
port | number | 4096 | TCP port for the HTTP server |
hostname | string | "127.0.0.1" | Interface to bind to. Use "0.0.0.0" for all interfaces |
mdns | boolean | false | Enable mDNS discovery on the local network |
mdnsDomain | string | "opencode.local" | mDNS hostname for discovery |
cors | string[] | [] | 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:
| Method | Endpoint | Description |
|---|---|---|
GET | /api/status | Server health and configuration info |
POST | /api/chat | Send a message and receive a response |
POST | /api/chat/stream | Send a message and stream the response via SSE |
GET | /api/sessions | List active sessions |
GET | /api/sessions/:id | Get session details and message history |
DELETE | /api/sessions/:id | Delete a session |
GET | /api/models | List available models |
GET | /api/providers | List configured providers |
GET | /api/agents | List 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.
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