6.4 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
Local/dev uses opencode's default port 4096:
opencode serve \
--hostname 127.0.0.1 \
--port 4096
Public production uses port 4242; see public-ports.md:
opencode serve \
--hostname 0.0.0.0 \
--port 4242
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.
Optional query parameters used by ai:
directory— scope results to an opencode project directory.
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" }
],
"agent": "atm10-expert",
"model": { "providerID": "anthropic", "modelID": "claude-opus-4-7" }
}
agent and model are optional — omit them to use the server's configured defaults.
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. Opencode validates caller-provided message IDs; use IDs starting with msg.
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 and starts generation in the background. Include messageID in the request body so the submitted user message can be matched to the later assistant response. Opencode validates caller-provided message IDs; use IDs starting with msg.
Request body:
{
"messageID": "msg_xyz",
"parts": [
{ "type": "text", "text": "your prompt here" }
],
"agent": "atm10-expert",
"model": { "providerID": "anthropic", "modelID": "claude-opus-4-7" }
}
agent and model are optional. Omit model to use the server/session default model, or include it to force a specific provider/model for this prompt.
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. The submitted messageID identifies the user message; ai polls GET /session/:id/message and reads the completed assistant message after it. If opencc.agent or --agent <name> is set, ai includes it as agent in the request body. If generation fails in the background, opencode records the failure on the assistant message or session event stream; ai surfaces assistant message errors while polling.
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.