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": "computercraft",
"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. Include messageID in the request body so the submitted 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": "computercraft",
"model": { "providerID": "anthropic", "modelID": "claude-opus-4-7" }
}
Unlike /message, model is not optional in practice — omitting it causes the request to be accepted (204) without triggering generation, so the assistant message never appears. ai only uses this async endpoint when opencc.provider_id and opencc.model_id are configured; otherwise it falls back to blocking POST /session/:id/message.
When async mode is available, ai uses this endpoint 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 or assistant message depending on the opencode response shape; ai polls GET /session/:id/message and reads the completed assistant message. If opencc.agent or --agent <name> is set, ai includes it as agent in the request body.
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.