|
| 1 | +--- |
| 2 | +title: Server |
| 3 | +description: Interact with opencode server over HTTP. |
| 4 | +--- |
| 5 | + |
| 6 | +import config from "../../../config.mjs"; |
| 7 | +export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts`; |
| 8 | + |
| 9 | +The `opencode serve` command runs a headless HTTP server that exposes an OpenAPI endpoint that an opencode client can use. |
| 10 | + |
| 11 | +--- |
| 12 | + |
| 13 | +### Usage |
| 14 | + |
| 15 | +```bash |
| 16 | +opencode serve [--port <number>] [--hostname <string>] [--cors <origin>] |
| 17 | +``` |
| 18 | + |
| 19 | +#### Options |
| 20 | + |
| 21 | +| Flag | Description | Default | |
| 22 | +| --------------- | ----------------------------------- | ---------------- | |
| 23 | +| `--port` | Port to listen on | `4096` | |
| 24 | +| `--hostname` | Hostname to listen on | `127.0.0.1` | |
| 25 | +| `--mdns` | Enable mDNS discovery | `false` | |
| 26 | +| `--mdns-domain` | Custom domain name for mDNS service | `opencode.local` | |
| 27 | +| `--cors` | Additional browser origins to allow | `[]` | |
| 28 | + |
| 29 | +`--cors` can be passed multiple times: |
| 30 | + |
| 31 | +```bash |
| 32 | +opencode serve --cors http://localhost:5173 --cors https://app.example.com |
| 33 | +``` |
| 34 | + |
| 35 | +--- |
| 36 | + |
| 37 | +### Authentication |
| 38 | + |
| 39 | +Set `OPENCODE_SERVER_PASSWORD` to protect the server with HTTP basic auth. The username defaults to `opencode`, or set `OPENCODE_SERVER_USERNAME` to override it. This applies to both `opencode serve` and `opencode web`. |
| 40 | + |
| 41 | +```bash |
| 42 | +OPENCODE_SERVER_PASSWORD=your-password opencode serve |
| 43 | +``` |
| 44 | + |
| 45 | +--- |
| 46 | + |
| 47 | +### How it works |
| 48 | + |
| 49 | +When you run `opencode` it starts a TUI and a server. Where the TUI is the |
| 50 | +client that talks to the server. The server exposes an OpenAPI 3.1 spec |
| 51 | +endpoint. This endpoint is also used to generate an [SDK](/docs/sdk). |
| 52 | + |
| 53 | +:::tip |
| 54 | +Use the opencode server to interact with opencode programmatically. |
| 55 | +::: |
| 56 | + |
| 57 | +This architecture lets opencode support multiple clients and allows you to interact with opencode programmatically. |
| 58 | + |
| 59 | +You can run `opencode serve` to start a standalone server. If you have the |
| 60 | +opencode TUI running, `opencode serve` will start a new server. |
| 61 | + |
| 62 | +--- |
| 63 | + |
| 64 | +#### Connect to an existing server |
| 65 | + |
| 66 | +When you start the TUI it randomly assigns a port and hostname. You can instead pass in the `--hostname` and `--port` [flags](/docs/cli). Then use this to connect to its server. |
| 67 | + |
| 68 | +The [`/tui`](#tui) endpoint can be used to drive the TUI through the server. For example, you can prefill or run a prompt. This setup is used by the OpenCode [IDE](/docs/ide) plugins. |
| 69 | + |
| 70 | +--- |
| 71 | + |
| 72 | +## Spec |
| 73 | + |
| 74 | +The server publishes an OpenAPI 3.1 spec that can be viewed at: |
| 75 | + |
| 76 | +``` |
| 77 | +http://<hostname>:<port>/doc |
| 78 | +``` |
| 79 | + |
| 80 | +For example, `http://localhost:4096/doc`. Use the spec to generate clients or inspect request and response types. Or view it in a Swagger explorer. |
| 81 | + |
| 82 | +--- |
| 83 | + |
| 84 | +## APIs |
| 85 | + |
| 86 | +The opencode server exposes the following APIs. |
| 87 | + |
| 88 | +--- |
| 89 | + |
| 90 | +### Global |
| 91 | + |
| 92 | +| Method | Path | Description | Response | |
| 93 | +| ------ | ---------------- | ------------------------------ | ------------------------------------ | |
| 94 | +| `GET` | `/global/health` | Get server health and version | `{ healthy: true, version: string }` | |
| 95 | +| `GET` | `/global/event` | Get global events (SSE stream) | Event stream | |
| 96 | + |
| 97 | +--- |
| 98 | + |
| 99 | +### Project |
| 100 | + |
| 101 | +| Method | Path | Description | Response | |
| 102 | +| ------ | ------------------ | ----------------------- | --------------------------------------------- | |
| 103 | +| `GET` | `/project` | List all projects | <a href={typesUrl}><code>Project[]</code></a> | |
| 104 | +| `GET` | `/project/current` | Get the current project | <a href={typesUrl}><code>Project</code></a> | |
| 105 | + |
| 106 | +--- |
| 107 | + |
| 108 | +### Path & VCS |
| 109 | + |
| 110 | +| Method | Path | Description | Response | |
| 111 | +| ------ | ------- | ------------------------------------ | ------------------------------------------- | |
| 112 | +| `GET` | `/path` | Get the current path | <a href={typesUrl}><code>Path</code></a> | |
| 113 | +| `GET` | `/vcs` | Get VCS info for the current project | <a href={typesUrl}><code>VcsInfo</code></a> | |
| 114 | + |
| 115 | +--- |
| 116 | + |
| 117 | +### Instance |
| 118 | + |
| 119 | +| Method | Path | Description | Response | |
| 120 | +| ------ | ------------------- | ---------------------------- | --------- | |
| 121 | +| `POST` | `/instance/dispose` | Dispose the current instance | `boolean` | |
| 122 | + |
| 123 | +--- |
| 124 | + |
| 125 | +### Config |
| 126 | + |
| 127 | +| Method | Path | Description | Response | |
| 128 | +| ------- | ------------------- | --------------------------------- | ---------------------------------------------------------------------------------------- | |
| 129 | +| `GET` | `/config` | Get config info | <a href={typesUrl}><code>Config</code></a> | |
| 130 | +| `PATCH` | `/config` | Update config | <a href={typesUrl}><code>Config</code></a> | |
| 131 | +| `GET` | `/config/providers` | List providers and default models | `{ providers: `<a href={typesUrl}>Provider[]</a>`, default: { [key: string]: string } }` | |
| 132 | + |
| 133 | +--- |
| 134 | + |
| 135 | +### Provider |
| 136 | + |
| 137 | +| Method | Path | Description | Response | |
| 138 | +| ------ | -------------------------------- | ------------------------------------ | ----------------------------------------------------------------------------------- | |
| 139 | +| `GET` | `/provider` | List all providers | `{ all: `<a href={typesUrl}>Provider[]</a>`, default: {...}, connected: string[] }` | |
| 140 | +| `GET` | `/provider/auth` | Get provider authentication methods | `{ [providerID: string]: `<a href={typesUrl}>ProviderAuthMethod[]</a>` }` | |
| 141 | +| `POST` | `/provider/{id}/oauth/authorize` | Authorize a provider using OAuth | <a href={typesUrl}><code>ProviderAuthAuthorization</code></a> | |
| 142 | +| `POST` | `/provider/{id}/oauth/callback` | Handle OAuth callback for a provider | `boolean` | |
| 143 | + |
| 144 | +--- |
| 145 | + |
| 146 | +### Sessions |
| 147 | + |
| 148 | +| Method | Path | Description | Notes | |
| 149 | +| -------- | ---------------------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------- | |
| 150 | +| `GET` | `/session` | List all sessions | Returns <a href={typesUrl}><code>Session[]</code></a> | |
| 151 | +| `POST` | `/session` | Create a new session | body: `{ parentID?, title? }`, returns <a href={typesUrl}><code>Session</code></a> | |
| 152 | +| `GET` | `/session/status` | Get session status for all sessions | Returns `{ [sessionID: string]: `<a href={typesUrl}>SessionStatus</a>` }` | |
| 153 | +| `GET` | `/session/:id` | Get session details | Returns <a href={typesUrl}><code>Session</code></a> | |
| 154 | +| `DELETE` | `/session/:id` | Delete a session and all its data | Returns `boolean` | |
| 155 | +| `PATCH` | `/session/:id` | Update session properties | body: `{ title? }`, returns <a href={typesUrl}><code>Session</code></a> | |
| 156 | +| `GET` | `/session/:id/children` | Get a session's child sessions | Returns <a href={typesUrl}><code>Session[]</code></a> | |
| 157 | +| `GET` | `/session/:id/todo` | Get the todo list for a session | Returns <a href={typesUrl}><code>Todo[]</code></a> | |
| 158 | +| `POST` | `/session/:id/init` | Analyze app and create `AGENTS.md` | body: `{ messageID, providerID, modelID }`, returns `boolean` | |
| 159 | +| `POST` | `/session/:id/fork` | Fork an existing session at a message | body: `{ messageID? }`, returns <a href={typesUrl}><code>Session</code></a> | |
| 160 | +| `POST` | `/session/:id/abort` | Abort a running session | Returns `boolean` | |
| 161 | +| `POST` | `/session/:id/share` | Share a session | Returns <a href={typesUrl}><code>Session</code></a> | |
| 162 | +| `DELETE` | `/session/:id/share` | Unshare a session | Returns <a href={typesUrl}><code>Session</code></a> | |
| 163 | +| `GET` | `/session/:id/diff` | Get the diff for this session | query: `messageID?`, returns <a href={typesUrl}><code>FileDiff[]</code></a> | |
| 164 | +| `POST` | `/session/:id/summarize` | Summarize the session | body: `{ providerID, modelID }`, returns `boolean` | |
| 165 | +| `POST` | `/session/:id/revert` | Revert a message | body: `{ messageID, partID? }`, returns `boolean` | |
| 166 | +| `POST` | `/session/:id/unrevert` | Restore all reverted messages | Returns `boolean` | |
| 167 | +| `POST` | `/session/:id/permissions/:permissionID` | Respond to a permission request | body: `{ response, remember? }`, returns `boolean` | |
| 168 | + |
| 169 | +--- |
| 170 | + |
| 171 | +### Messages |
| 172 | + |
| 173 | +| Method | Path | Description | Notes | |
| 174 | +| ------ | --------------------------------- | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | |
| 175 | +| `GET` | `/session/:id/message` | List messages in a session | query: `limit?`, returns `{ info: `<a href={typesUrl}>Message</a>`, parts: `<a href={typesUrl}>Part[]</a>`}[]` | |
| 176 | +| `POST` | `/session/:id/message` | Send a message and wait for response | body: `{ messageID?, model?, agent?, noReply?, system?, tools?, parts }`, returns `{ info: `<a href={typesUrl}>Message</a>`, parts: `<a href={typesUrl}>Part[]</a>`}` | |
| 177 | +| `GET` | `/session/:id/message/:messageID` | Get message details | Returns `{ info: `<a href={typesUrl}>Message</a>`, parts: `<a href={typesUrl}>Part[]</a>`}` | |
| 178 | +| `POST` | `/session/:id/prompt_async` | Send a message asynchronously (no wait) | body: same as `/session/:id/message`, returns `204 No Content` | |
| 179 | +| `POST` | `/session/:id/command` | Execute a slash command | body: `{ messageID?, agent?, model?, command, arguments }`, returns `{ info: `<a href={typesUrl}>Message</a>`, parts: `<a href={typesUrl}>Part[]</a>`}` | |
| 180 | +| `POST` | `/session/:id/shell` | Run a shell command | body: `{ agent, model?, command }`, returns `{ info: `<a href={typesUrl}>Message</a>`, parts: `<a href={typesUrl}>Part[]</a>`}` | |
| 181 | + |
| 182 | +--- |
| 183 | + |
| 184 | +### Commands |
| 185 | + |
| 186 | +| Method | Path | Description | Response | |
| 187 | +| ------ | ---------- | ----------------- | --------------------------------------------- | |
| 188 | +| `GET` | `/command` | List all commands | <a href={typesUrl}><code>Command[]</code></a> | |
| 189 | + |
| 190 | +--- |
| 191 | + |
| 192 | +### Files |
| 193 | + |
| 194 | +| Method | Path | Description | Response | |
| 195 | +| ------ | ------------------------ | ---------------------------------- | ------------------------------------------------------------------------------------------- | |
| 196 | +| `GET` | `/find?pattern=<pat>` | Search for text in files | Array of match objects with `path`, `lines`, `line_number`, `absolute_offset`, `submatches` | |
| 197 | +| `GET` | `/find/file?query=<q>` | Find files and directories by name | `string[]` (paths) | |
| 198 | +| `GET` | `/find/symbol?query=<q>` | Find workspace symbols | <a href={typesUrl}><code>Symbol[]</code></a> | |
| 199 | +| `GET` | `/file?path=<path>` | List files and directories | <a href={typesUrl}><code>FileNode[]</code></a> | |
| 200 | +| `GET` | `/file/content?path=<p>` | Read a file | <a href={typesUrl}><code>FileContent</code></a> | |
| 201 | +| `GET` | `/file/status` | Get status for tracked files | <a href={typesUrl}><code>File[]</code></a> | |
| 202 | + |
| 203 | +#### `/find/file` query parameters |
| 204 | + |
| 205 | +- `query` (required) — search string (fuzzy match) |
| 206 | +- `type` (optional) — limit results to `"file"` or `"directory"` |
| 207 | +- `directory` (optional) — override the project root for the search |
| 208 | +- `limit` (optional) — max results (1–200) |
| 209 | +- `dirs` (optional) — legacy flag (`"false"` returns only files) |
| 210 | + |
| 211 | +--- |
| 212 | + |
| 213 | +### Tools (Experimental) |
| 214 | + |
| 215 | +| Method | Path | Description | Response | |
| 216 | +| ------ | ------------------------------------------- | ---------------------------------------- | -------------------------------------------- | |
| 217 | +| `GET` | `/experimental/tool/ids` | List all tool IDs | <a href={typesUrl}><code>ToolIDs</code></a> | |
| 218 | +| `GET` | `/experimental/tool?provider=<p>&model=<m>` | List tools with JSON schemas for a model | <a href={typesUrl}><code>ToolList</code></a> | |
| 219 | + |
| 220 | +--- |
| 221 | + |
| 222 | +### LSP, Formatters & MCP |
| 223 | + |
| 224 | +| Method | Path | Description | Response | |
| 225 | +| ------ | ------------ | -------------------------- | -------------------------------------------------------- | |
| 226 | +| `GET` | `/lsp` | Get LSP server status | <a href={typesUrl}><code>LSPStatus[]</code></a> | |
| 227 | +| `GET` | `/formatter` | Get formatter status | <a href={typesUrl}><code>FormatterStatus[]</code></a> | |
| 228 | +| `GET` | `/mcp` | Get MCP server status | `{ [name: string]: `<a href={typesUrl}>MCPStatus</a>` }` | |
| 229 | +| `POST` | `/mcp` | Add MCP server dynamically | body: `{ name, config }`, returns MCP status object | |
| 230 | + |
| 231 | +--- |
| 232 | + |
| 233 | +### Agents |
| 234 | + |
| 235 | +| Method | Path | Description | Response | |
| 236 | +| ------ | -------- | ------------------------- | ------------------------------------------- | |
| 237 | +| `GET` | `/agent` | List all available agents | <a href={typesUrl}><code>Agent[]</code></a> | |
| 238 | + |
| 239 | +--- |
| 240 | + |
| 241 | +### Logging |
| 242 | + |
| 243 | +| Method | Path | Description | Response | |
| 244 | +| ------ | ------ | ------------------------------------------------------------ | --------- | |
| 245 | +| `POST` | `/log` | Write log entry. Body: `{ service, level, message, extra? }` | `boolean` | |
| 246 | + |
| 247 | +--- |
| 248 | + |
| 249 | +### TUI |
| 250 | + |
| 251 | +| Method | Path | Description | Response | |
| 252 | +| ------ | ----------------------- | ------------------------------------------- | ---------------------- | |
| 253 | +| `POST` | `/tui/append-prompt` | Append text to the prompt | `boolean` | |
| 254 | +| `POST` | `/tui/open-help` | Open the help dialog | `boolean` | |
| 255 | +| `POST` | `/tui/open-sessions` | Open the session selector | `boolean` | |
| 256 | +| `POST` | `/tui/open-themes` | Open the theme selector | `boolean` | |
| 257 | +| `POST` | `/tui/open-models` | Open the model selector | `boolean` | |
| 258 | +| `POST` | `/tui/submit-prompt` | Submit the current prompt | `boolean` | |
| 259 | +| `POST` | `/tui/clear-prompt` | Clear the prompt | `boolean` | |
| 260 | +| `POST` | `/tui/execute-command` | Execute a command (`{ command }`) | `boolean` | |
| 261 | +| `POST` | `/tui/show-toast` | Show toast (`{ title?, message, variant }`) | `boolean` | |
| 262 | +| `GET` | `/tui/control/next` | Wait for the next control request | Control request object | |
| 263 | +| `POST` | `/tui/control/response` | Respond to a control request (`{ body }`) | `boolean` | |
| 264 | + |
| 265 | +--- |
| 266 | + |
| 267 | +### Auth |
| 268 | + |
| 269 | +| Method | Path | Description | Response | |
| 270 | +| ------ | ----------- | --------------------------------------------------------------- | --------- | |
| 271 | +| `PUT` | `/auth/:id` | Set authentication credentials. Body must match provider schema | `boolean` | |
| 272 | + |
| 273 | +--- |
| 274 | + |
| 275 | +### Events |
| 276 | + |
| 277 | +| Method | Path | Description | Response | |
| 278 | +| ------ | -------- | ----------------------------------------------------------------------------- | ------------------------- | |
| 279 | +| `GET` | `/event` | Server-sent events stream. First event is `server.connected`, then bus events | Server-sent events stream | |
| 280 | + |
| 281 | +--- |
| 282 | + |
| 283 | +### Docs |
| 284 | + |
| 285 | +| Method | Path | Description | Response | |
| 286 | +| ------ | ------ | ------------------------- | --------------------------- | |
| 287 | +| `GET` | `/doc` | OpenAPI 3.1 specification | HTML page with OpenAPI spec | |
0 commit comments