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.
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
| 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.
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