Install
$ agentstack add skill-timmy6942025-opencode-builder-skill-opencode-server ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
OpenCode Server
> 📚 Official Docs: For the latest information, always refer to the official documentation: > https://opencode.ai/docs/server/
OpenCode exposes a headless HTTP server that implements a full REST API and publishes an OpenAPI 3.1 specification. The TUI is a client that talks to this server. The server enables multiple clients (TUI, web, IDE plugins, custom integrations) to control OpenCode programmatically.
Usage
Start a standalone HTTP server:
opencode serve [--port ] [--hostname ] [--mdns] [--mdns-domain ] [--cors ]
Flags
| Flag | Description | Default | |------|-------------|---------| | --port | Port to listen on | 0 (random available port) | | --hostname | Hostname to listen on | 127.0.0.1 | | --mdns | Enable mDNS discovery | false | | --mdns-domain | Custom domain name for mDNS service | opencode.local | | --cors | Additional browser origins to allow (repeatable) | [] |
The --cors flag can be passed multiple times:
opencode serve --cors http://localhost:5173 --cors https://app.example.com
When you run opencode normally (without serve), it starts both a TUI and an internal server. The TUI is the client that talks to this server. Running opencode serve starts a standalone headless server without launching the TUI.
Authentication
Protect the server with HTTP basic auth using environment variables:
| Variable | Description | Default | |----------|-------------|---------| | OPENCODE_SERVER_PASSWORD | Password for HTTP basic auth | (none — unauthenticated) | | OPENCODE_SERVER_USERNAME | Username for HTTP basic auth | opencode |
OPENCODE_SERVER_PASSWORD=your-password opencode serve
Authentication applies to both opencode serve and opencode web. If OPENCODE_SERVER_PASSWORD is not set, the server is unsecured — acceptable for local use, but should be set for network access.
Architecture
The architecture separates the TUI (client) from the server:
- Server — Headless HTTP process that exposes the full OpenCode API.
- TUI — A client that connects to the server and renders the terminal UI.
- Web — A browser-based client that connects to the server.
- SDK — A type-safe JavaScript/TypeScript client generated from the server's OpenAPI spec.
The server publishes an OpenAPI 3.1 specification at /doc. The SDK (@opencode-ai/sdk) is generated from this spec, providing fully typed request/response objects for every endpoint.
This separation allows multiple clients to attach simultaneously — a terminal TUI, a browser tab, and custom integrations can all share the same sessions and state.
Connect to an Existing Server
When you start the TUI, it randomly assigns a port and hostname. You can instead pass --hostname and --port flags to control the binding:
opencode --hostname 127.0.0.1 --port 4096
Then connect other clients to the same server:
# Connect the TUI to an existing server
opencode attach http://localhost:4096
# Or use the SDK
import { createOpencodeClient } from "@opencode-ai/sdk"
const client = createOpencodeClient({ baseUrl: "http://localhost:4096" })
TUI Endpoint for IDE Plugins
The /tui endpoint allows IDE plugins to drive the TUI through the server — prefill prompts, submit prompts, execute commands, open dialogs, and show notifications. This is the primary integration point for OpenCode IDE plugins.
OpenAPI Spec
The server publishes an OpenAPI 3.1 spec at:
http://:/doc
For example: http://localhost:4096/doc
Use the spec to:
- Generate clients in any language
- Inspect request/response types in a Swagger explorer
- Build custom integrations with full type safety
API Reference
All endpoints are relative to http://:.
Global
| Method | Path | Description | Response | |--------|------|-------------|----------| | GET | /global/health | Get server health and version | { healthy: true, version: string } | | GET | /global/event | Get global events as SSE stream | Event stream |
GET /global/health
Returns server health status and version string. Useful for health checks and monitoring.
{ "healthy": true, "version": "1.0.0" }
GET /global/event
Server-Sent Events stream of global events. First event is server.connected, then bus events stream continuously.
Project
| Method | Path | Description | Response | |--------|------|-------------|----------| | GET | /project | List all projects | Project[] | | GET | /project/current | Get the current project | Project |
The Project type contains project metadata including name, path, and configuration information.
Path & VCS
| Method | Path | Description | Response | |--------|------|-------------|----------| | GET | /path | Get the current path | Path | | GET | /vcs | Get VCS info for the current project | VcsInfo |
/path returns the current working directory and project root. /vcs returns version control system information (branch, status, etc.).
Instance
| Method | Path | Description | Response | |--------|------|-------------|----------| | POST | /instance/dispose | Dispose the current instance | boolean |
Shuts down the current OpenCode instance. Use with caution — this terminates the server process.
Config
| Method | Path | Description | Response | |--------|------|-------------|----------| | GET | /config | Get config info | Config | | PATCH | /config | Update config | Config | | GET | /config/providers | List providers and default models | { providers: Provider[], default: { [key: string]: string } } |
GET /config
Returns the full configuration object for the current instance.
PATCH /config
Partially updates the configuration. Only the provided fields are modified; omitted fields remain unchanged.
GET /config/providers
Returns all configured providers and their default model mappings. The default map keys are provider IDs and values are model IDs.
Provider
| Method | Path | Description | Response | |--------|------|-------------|----------| | GET | /provider | List all providers | { all: Provider[], default: {...}, connected: string[] } | | GET | /provider/auth | Get provider authentication methods | { [providerID: string]: ProviderAuthMethod[] } | | POST | /provider/{id}/oauth/authorize | Authorize a provider using OAuth | ProviderAuthAuthorization | | POST | /provider/{id}/oauth/callback | Handle OAuth callback for a provider | boolean |
GET /provider
Returns:
all— All configured providersdefault— Default model for each providerconnected— List of connected (authenticated) provider IDs
GET /provider/auth
Returns available authentication methods for each provider. Useful for building OAuth flows in custom clients.
POST /provider/{id}/oauth/authorize
Initiates an OAuth authorization flow for the specified provider. Returns authorization URL and state.
POST /provider/{id}/oauth/callback
Handles the OAuth callback after the user authorizes. Returns true if authentication succeeded.
Sessions
| Method | Path | Description | Response | |--------|------|-------------|----------| | GET | /session | List all sessions | Session[] | | POST | /session | Create a new session | Session | | GET | /session/status | Get session status for all sessions | { [sessionID: string]: SessionStatus } | | GET | /session/:id | Get session details | Session | | DELETE | /session/:id | Delete a session and all its data | boolean | | PATCH | /session/:id | Update session properties | Session | | GET | /session/:id/children | Get a session's child sessions | Session[] | | GET | /session/:id/todo | Get the todo list for a session | Todo[] | | POST | /session/:id/init | Analyze app and create AGENTS.md | boolean | | POST | /session/:id/fork | Fork an existing session at a message | Session | | POST | /session/:id/abort | Abort a running session | boolean | | POST | /session/:id/share | Share a session | Session | | DELETE | /session/:id/share | Unshare a session | Session | | GET | /session/:id/diff | Get the diff for this session | FileDiff[] | | POST | /session/:id/summarize | Summarize the session | boolean | | POST | /session/:id/revert | Revert a message | boolean | | POST | /session/:id/unrevert | Restore all reverted messages | boolean | | POST | /session/:id/permissions/:permissionID | Respond to a permission request | boolean |
POST /session
Create a new session. Body:
{
"parentID": "optional-parent-session-id",
"title": "Optional session title"
}
Returns the created Session object.
PATCH /session/:id
Update session properties. Body:
{
"title": "New title"
}
POST /session/:id/init
Analyze the application and generate an AGENTS.md file. Body:
{
"messageID": "message-to-respond-to",
"providerID": "anthropic",
"modelID": "claude-3-5-sonnet-20241022"
}
POST /session/:id/fork
Fork an existing session, optionally at a specific message. Body:
{
"messageID": "optional-message-id-to-fork-at"
}
Returns a new Session object that is a copy of the original.
POST /session/:id/share
Makes the session publicly accessible. Returns the updated session with sharing metadata.
DELETE /session/:id/share
Revokes public sharing for the session.
GET /session/:id/diff
Get file changes for the session. Optional query parameter messageID to get diff up to a specific message.
Returns FileDiff[] — an array of file diffs showing added, removed, and modified content.
POST /session/:id/summarize
Generate a summary of the session. Body:
{
"providerID": "anthropic",
"modelID": "claude-3-5-sonnet-20241022"
}
POST /session/:id/revert
Revert a specific message (and optionally a specific part within it). Body:
{
"messageID": "message-to-revert",
"partID": "optional-specific-part"
}
POST /session/:id/unrevert
Restores all reverted messages in the session. No body required.
POST /session/:id/permissions/:permissionID
Respond to a pending permission request. Body:
{
"response": "allow",
"remember": true
}
Messages
| Method | Path | Description | Response | |--------|------|-------------|----------| | GET | /session/:id/message | List messages in a session | { info: Message, parts: Part[] }[] | | POST | /session/:id/message | Send a message and wait for response | { info: Message, parts: Part[] } | | GET | /session/:id/message/:messageID | Get message details | { info: Message, parts: Part[] } | | POST | /session/:id/prompt_async | Send a message asynchronously (no wait) | 204 No Content | | POST | /session/:id/command | Execute a slash command | { info: Message, parts: Part[] } | | POST | /session/:id/shell | Run a shell command | { info: Message, parts: Part[] } | | DELETE | /session/:id/message/:messageID | Delete a specific message | boolean | | DELETE | /session/:id/message/:messageID/part/:partID | Delete a specific message part | boolean | | PATCH | /session/:id/message/:messageID/part/:partID | Update a specific message part | Part |
GET /session/:id/message
List messages in a session. Optional query parameter limit to restrict the number of messages returned.
Each message contains:
info— TheMessageobject (role, content, metadata)parts— Array ofPartobjects (text chunks, tool calls, tool results)
POST /session/:id/message
Send a message and wait for the AI response. Body:
{
"messageID": "optional-message-id",
"model": { "providerID": "anthropic", "modelID": "claude-3-5-sonnet-20241022" },
"agent": "optional-agent-name",
"noReply": false,
"system": "optional-system-prompt",
"tools": ["optional-tool-whitelist"],
"parts": [
{ "type": "text", "text": "Hello!" }
]
}
noReply: true— Injects context without triggering an AI response (returns a UserMessage)model— Optionally override the model for this messageagent— Optionally specify an agenttools— Optionally restrict which tools the model can useparts— Message content parts (text, images, etc.)
POST /session/:id/prompt_async
Same body as /session/:id/message but returns immediately with 204 No Content. The response is processed asynchronously; listen to events to know when it completes.
POST /session/:id/command
Execute a slash command. Body:
{
"messageID": "optional-message-id",
"agent": "optional-agent",
"model": { "providerID": "...", "modelID": "..." },
"command": "/compact",
"arguments": "optional arguments string"
}
POST /session/:id/shell
Run a shell command within the session context. Body:
{
"agent": "optional-agent",
"model": { "providerID": "...", "modelID": "..." },
"command": "ls -la"
}
Returns the assistant message with tool call results.
DELETE /session/:id/message/:messageID
Delete a specific message from a session. This permanently removes the message and all its parts.
DELETE /session/:id/message/:messageID/part/:partID
Delete a specific part within a message. Removes only the specified part (e.g., a single tool call or text chunk).
PATCH /session/:id/message/:messageID/part/:partID
Update a specific message part. Body:
{
"text": "Updated text content"
}
Allows modifying the content of a specific part within a message.
Commands
| Method | Path | Description | Response | |--------|------|-------------|----------| | GET | /command | List all available commands | Command[] |
Returns all registered slash commands (e.g., /compact, /init, /clear).
Files
| Method | Path | Description | Response | |--------|------|-------------|----------| | GET | /find?pattern= | Search for text in files | Match objects | | GET | /find/file?query= | Find files and directories by name | string[] | | GET | /find/symbol?query= | Find workspace symbols | Symbol[] | | GET | /file?path= | List files and directories | FileNode[] | | GET | /file/content?path= | Read a file | FileContent | | GET | /file/status | Get status for tracked files | File[] |
GET /find?pattern=
Search for text in files using a regex pattern. Returns an array of match objects:
[
{
"path": "src/index.ts",
"lines": ["matching line content"],
"line_number": 42,
"absolute_offset": 1234,
"submatches": [{ "match": "matched text", "start": 0, "end": 12 }]
}
]
GET /find/file?query=
Find files and directories by name using fuzzy matching.
Query Parameters:
| Parameter | Required | Description | |-----------|----------|-------------| | query | Yes | Search string (fuzzy match) | | type | No | Limit to "file" or "directory" | | directory | No | Override the project root for the search | | limit | No | Max results (1–200) | | dirs | No | Legacy flag ("false" returns only files) |
Returns string[] — array of matching file/directory paths.
GET /find/symbol?query=
Find workspace symbols (functions, classes, variables, etc.).
GET /file?path=
List files and directories at the given path. Returns FileNode[] with file metadata.
GET /file/content?path=
Read the content of a file. Returns FileContent with the file's raw content.
GET /file/status
Get status for all tracked (VCS-tracked) files. Returns File[] with file status information.
Tools (Experimental)
| Method
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: Timmy6942025
- Source: Timmy6942025/opencode-builder-skill
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.