5.2 KiB
opencode serve — HTTP API reference
Minimal reference for the endpoints used by libai.lua. Full spec served at GET /doc when the server is running.
Running the server
opencode serve \
--hostname 127.0.0.1 \
--port 4096
With Basic Auth (recommended):
OPENCODE_SERVER_PASSWORD=secret opencode serve \
--hostname 127.0.0.1 \
--port 4096
Default username is opencode. Override with OPENCODE_SERVER_USERNAME.
Authentication
All requests must include Authorization: Basic <base64(username:password)> when the server was started with a password. No auth header is needed if no password is set.
Authorization: Basic base64("opencode:secret")
Endpoints
GET /global/health
Health check. Returns 200 when the server is up.
GET /session
List all sessions for the current project.
Response 200:
[
{ "id": "ses_abc123", "title": "my session", "time": { "created": 1234567890, "updated": 1234567890 } }
]
POST /session
Create a new session.
Request body:
{ "title": "optional title", "parentID": "optional" }
Response 200:
{ "id": "ses_abc123", "title": "my session" }
POST /session/:id/message
Send a message and wait for the AI reply (blocking). Returns when the assistant has finished responding.
Request body:
{
"parts": [
{ "type": "text", "text": "your prompt here" }
],
"model": { "providerID": "anthropic", "modelID": "claude-opus-4-7" }
}
model is optional — omit to use the server's configured default.
Response 200:
{
"info": { "id": "msg_xyz", "sessionID": "ses_abc123", "role": "assistant" },
"parts": [
{ "type": "text", "text": "the reply" }
]
}
Parts can include non-text types (tool-call, step-start, etc.) — collect all type == "text" entries to reconstruct the reply.
Errors:
401— wrong credentials404— session not found (may have been deleted or server restarted)504— AI took too long
GET /session/:id/message/:messageID
Get a message by ID. ai uses this to poll async prompts until the assistant message has text parts and completion metadata.
Response 200:
{
"info": { "id": "msg_xyz", "sessionID": "ses_abc123", "role": "assistant", "time": { "completed": 1234567890 } },
"parts": [
{ "type": "text", "text": "the reply" }
]
}
DELETE /session/:id
Delete a session.
POST /session/:id/abort
Abort a running generation.
POST /session/:id/prompt_async
Fire-and-forget variant. Returns 204 immediately. Include messageID in the request body to make the assistant response addressable by GET /session/:id/message/:messageID.
ai uses this endpoint by default to avoid 504 failures from the blocking /message endpoint when the LLM takes longer than one HTTP request timeout.
GET /global/event (SSE)
Server-Sent Events stream. Delivers all server bus events in real time. Useful for async workflows or watching a session from outside the TUI.
opencode attach
opencode attach opens the TUI and connects it to an already-running opencode serve instance. Both the TUI and any HTTP clients operate on the same session state.
opencode attach http://127.0.0.1:4096
opencode attach http://127.0.0.1:4096 --session ses_abc123
To send messages to the session currently open in the TUI, set opencc.session_id in CC to the session ID shown in the TUI, then run ai:
set opencc.session_id ses_abc123
TUI control
When a TUI is attached, these endpoints drive that TUI programmatically. They operate on the attached TUI prompt/dialog state, not on a specific /session/:id.
| Method | Path | Effect | Body |
|---|---|---|---|
POST |
/tui/append-prompt |
Append text to the prompt | { "text": "..." } |
POST |
/tui/submit-prompt |
Submit the current prompt | none |
POST |
/tui/clear-prompt |
Clear the prompt | none |
POST |
/tui/open-help |
Open the help dialog | none |
POST |
/tui/open-sessions |
Open the session selector | none |
POST |
/tui/open-themes |
Open the theme selector | none |
POST |
/tui/open-models |
Open the model selector | none |
POST |
/tui/execute-command |
Execute a TUI command | { "command": "prompt.submit" } |
POST |
/tui/show-toast |
Show a notification | { "message": "...", "variant": "info" } |
GET |
/tui/control/next |
Wait for the next TUI control request | none |
POST |
/tui/control/response |
Respond to a TUI control request | response body |
/tui/show-toast also accepts optional title and duration fields. variant is one of info, success, warning, or error.
Example: prefill and submit the attached TUI prompt:
curl -X POST http://127.0.0.1:4096/tui/append-prompt \
-H 'Content-Type: application/json' \
-d '{"text":"reply with exactly: pong"}'
curl -X POST http://127.0.0.1:4096/tui/submit-prompt
POST /tui/publish also exists as a lower-level endpoint for publishing TUI events such as tui.prompt.append, tui.command.execute, and tui.toast.show. Prefer the specific endpoints above unless you need that raw event surface.