Develop
Build integrations and extend OpenCode with the SDK, server, plugins, and ecosystem.
SDK
Type-safe JS client for opencode server.
The opencode JS/TS SDK provides a type-safe client for interacting with the server. Use it to build integrations and control opencode programmatically.
Learn more about how the server works in Server. For examples, check out the projects built by the community in Ecosystem.
Install
Install the SDK from npm:
npm install @opencode-ai/sdkCreate client
Create an instance of opencode:
import { createOpencode } from "@opencode-ai/sdk"
const { client } = await createOpencode()This starts both a server and a client.
Options
| Option | Type | Description | Default |
|---|---|---|---|
hostname | string | Server hostname | 127.0.0.1 |
port | number | Server port | 4096 |
signal | AbortSignal | Abort signal for cancellation | undefined |
timeout | number | Timeout in ms for server start | 5000 |
config | Config | Configuration object | {} |
Config
You can pass a configuration object to customize behavior. The instance still picks up your opencode.json, but you can override or add configuration inline:
import { createOpencode } from "@opencode-ai/sdk"
const opencode = await createOpencode({
hostname: "127.0.0.1",
port: 4096,
config: {
model: "anthropic/claude-3-5-sonnet-20241022",
},
})
console.log(`Server running at ${opencode.server.url}`)
opencode.server.close()Client only
If you already have a running instance of opencode, you can create a client instance to connect to it:
import { createOpencodeClient } from "@opencode-ai/sdk"
const client = createOpencodeClient({
baseUrl: "http://localhost:4096",
})Options
| Option | Type | Description | Default |
|---|---|---|---|
baseUrl | string | URL of the server | http://localhost:4096 |
fetch | function | Custom fetch implementation | globalThis.fetch |
parseAs | string | Response parsing method | auto |
responseStyle | string | Return style: data or fields | fields |
throwOnError | boolean | Throw errors instead of return | false |
Types
The SDK includes TypeScript definitions for all API types. Import them directly:
import type { Session, Message, Part } from "@opencode-ai/sdk"All types are generated from the server's OpenAPI specification and available in the types file.
Errors
The SDK can throw errors that you can catch and handle:
try {
await client.session.get({ path: { id: "invalid-id" } })
} catch (error) {
console.error("Failed to get session:", (error as Error).message)
}Structured Output
You can request structured JSON output from the model by specifying a format with a JSON schema. The model will use a StructuredOutput tool to return validated JSON matching your schema.
Basic Usage
const result = await client.session.prompt({
path: { id: sessionId },
body: {
parts: [{ type: "text", text: "Research Anthropic and provide company info" }],
format: {
type: "json_schema",
schema: {
type: "object",
properties: {
company: { type: "string", description: "Company name" },
founded: { type: "number", description: "Year founded" },
products: {
type: "array",
items: { type: "string" },
description: "Main products",
},
},
required: ["company", "founded"],
},
},
},
})
// Access the structured output
console.log(result.data.info.structured_output)
// { company: "Anthropic", founded: 2021, products: ["Claude", "Claude API"] }Output Format Types
| Type | Description |
|---|---|
text | Default. Standard text response (no structured output) |
json_schema | Returns validated JSON matching the provided schema |
JSON Schema Format
When using type: 'json_schema', provide:
| Field | Type | Description |
|---|---|---|
type | 'json_schema' | Required. Specifies JSON schema mode |
schema | object | Required. JSON Schema object defining the output structure |
retryCount | number | Optional. Number of validation retries (default: 2) |
Error Handling
If the model fails to produce valid structured output after all retries, the response will include a StructuredOutputError:
if (result.data.info.error?.name === "StructuredOutputError") {
console.error("Failed to produce structured output:", result.data.info.error.message)
console.error("Attempts:", result.data.info.error.retries)
}Best Practices
- Provide clear descriptions in your schema properties to help the model understand what data to extract
- Use
requiredto specify which fields must be present - Keep schemas focused — complex nested schemas may be harder for the model to fill correctly
- Set appropriate
retryCount— increase for complex schemas, decrease for simple ones
APIs
The SDK exposes all server APIs through a type-safe client.
Global
| Method | Description | Response |
|---|---|---|
global.health() | Check server health and version | { healthy: true, version: string } |
const health = await client.global.health()
console.log(health.data.version)App
| Method | Description | Response |
|---|---|---|
app.log() | Write a log entry | boolean |
app.agents() | List all available agents | Agent[] |
// Write a log entry
await client.app.log({
body: {
service: "my-app",
level: "info",
message: "Operation completed",
},
})
// List available agents
const agents = await client.app.agents()Project
| Method | Description | Response |
|---|---|---|
project.list() | List all projects | Project[] |
project.current() | Get current project | Project |
// List all projects
const projects = await client.project.list()
// Get current project
const currentProject = await client.project.current()Path
| Method | Description | Response |
|---|---|---|
path.get() | Get current path | Path |
const pathInfo = await client.path.get()Config
| Method | Description | Response |
|---|---|---|
config.get() | Get config info | Config |
config.providers() | List providers and default models | { providers: Provider[], default: { [key: string]: string } } |
const config = await client.config.get()
const { providers, default: defaults } = await client.config.providers()Sessions
| Method | Description | Notes |
|---|---|---|
session.list() | List sessions | Returns Session[] |
session.get({ path }) | Get session | Returns Session |
session.children({ path }) | List child sessions | Returns Session[] |
session.create({ body }) | Create session | Returns Session |
session.delete({ path }) | Delete session | Returns boolean |
session.update({ path, body }) | Update session properties | Returns Session |
session.init({ path, body }) | Analyze app and create AGENTS.md | Returns boolean |
session.abort({ path }) | Abort a running session | Returns boolean |
session.share({ path }) | Share session | Returns Session |
session.unshare({ path }) | Unshare session | Returns Session |
session.summarize({ path, body }) | Summarize session | Returns boolean |
session.messages({ path }) | List messages in a session | Returns { info: Message, parts: Part[] }[] |
session.message({ path }) | Get message details | Returns { info: Message, parts: Part[] } |
session.prompt({ path, body }) | Send prompt message | body.noReply: true returns UserMessage (context only). Default returns AssistantMessage with AI response. Supports body.outputFormat for structured output |
session.command({ path, body }) | Send command to session | Returns { info: AssistantMessage, parts: Part[] } |
session.shell({ path, body }) | Run a shell command | Returns AssistantMessage |
session.revert({ path, body }) | Revert a message | Returns Session |
session.unrevert({ path }) | Restore reverted messages | Returns Session |
// Create and manage sessions
const session = await client.session.create({
body: { title: "My session" },
})
const sessions = await client.session.list()
// Send a prompt message
const result = await client.session.prompt({
path: { id: session.id },
body: {
model: { providerID: "anthropic", modelID: "claude-3-5-sonnet-20241022" },
parts: [{ type: "text", text: "Hello!" }],
},
})
// Inject context without triggering AI response (useful for plugins)
await client.session.prompt({
path: { id: session.id },
body: {
noReply: true,
parts: [{ type: "text", text: "You are a helpful assistant." }],
},
})Files
| Method | Description | Response |
|---|---|---|
find.text({ query }) | Search for text in files | Array of match objects with path, lines, line_number, absolute_offset, submatches |
find.files({ query }) | Find files and directories by name | string[] (paths) |
find.symbols({ query }) | Find workspace symbols | Symbol[] |
file.read({ query }) | Read a file | { type: "raw" | "patch", content: string } |
file.status({ query? }) | Get status for tracked files | File[] |
find.files supports a few optional query fields:
type:"file"or"directory"directory: override the project root for the searchlimit: max results (1–200)
// Search and read files
const textResults = await client.find.text({
query: { pattern: "function.*opencode" },
})
const files = await client.find.files({
query: { query: "*.ts", type: "file" },
})
const directories = await client.find.files({
query: { query: "packages", type: "directory", limit: 20 },
})
const content = await client.file.read({
query: { path: "src/index.ts" },
})TUI
| Method | Description | Response |
|---|---|---|
tui.appendPrompt({ body }) | Append text to the prompt | boolean |
tui.openHelp() | Open the help dialog | boolean |
tui.openSessions() | Open the session selector | boolean |
tui.openThemes() | Open the theme selector | boolean |
tui.openModels() | Open the model selector | boolean |
tui.submitPrompt() | Submit the current prompt | boolean |
tui.clearPrompt() | Clear the prompt | boolean |
tui.executeCommand({ body }) | Execute a command | boolean |
tui.showToast({ body }) | Show toast notification | boolean |
// Control TUI interface
await client.tui.appendPrompt({
body: { text: "Add this to prompt" },
})
await client.tui.showToast({
body: { message: "Task completed", variant: "success" },
})Auth
| Method | Description | Response |
|---|---|---|
auth.set({ ... }) | Set authentication credentials | boolean |
await client.auth.set({
path: { id: "anthropic" },
body: { type: "api", key: "your-api-key" },
})Events
| Method | Description | Response |
|---|---|---|
event.subscribe() | Server-sent events stream | Server-sent events stream |
// Listen to real-time events
const events = await client.event.subscribe()
for await (const event of events.stream) {
console.log("Event:", event.type, event.properties)
}Server
Interact with opencode server over HTTP.
The opencode serve command runs a headless HTTP server that exposes an OpenAPI endpoint that an opencode client can use.
Usage
opencode serve [--port <number>] [--hostname <string>] [--cors <origin>]Options
| Flag | Description | Default |
|---|---|---|
--port | Port to listen on | 4096 |
--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 | [] |
opencode serve --cors http://localhost:5173 --cors https://app.example.comAuthentication
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.
OPENCODE_SERVER_PASSWORD=your-password opencode serveHow it works
When you run opencode it starts a TUI and a server. The TUI is the client that talks to the server. The server exposes an OpenAPI 3.1 spec endpoint. This endpoint is also used to generate an SDK.
Use the opencode server to interact with opencode programmatically.
This architecture lets opencode support multiple clients and allows you to interact with opencode programmatically.
You can run opencode serve to start a standalone server. If you have the opencode TUI running, opencode serve will start a new server.
Connect to an existing server
When you start the TUI it randomly assigns a port and hostname. You can instead pass in the --hostname and --port flags. Then use this to connect to its server.
The /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 plugins.
Spec
The server publishes an OpenAPI 3.1 spec that can be viewed at, 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.
APIs
The opencode server exposes the following APIs.
Global
| Method | Endpoint | Description |
|---|---|---|
GET | /global/health | Get server health and version |
GET | /global/event | Get global events (SSE stream) |
Project
| Method | Endpoint | Description |
|---|---|---|
GET | /project | List all projects |
GET | /project/current | Get the current project |
Path & VCS
| Method | Endpoint | Description |
|---|---|---|
GET | /path | Get the current path |
GET | /vcs | Get VCS info for the current project |
Instance
| Method | Endpoint | Description |
|---|---|---|
POST | /instance/dispose | Dispose the current instance |
Config
| Method | Endpoint | Description |
|---|---|---|
GET | /config | Get config info |
PATCH | /config | Update config |
GET | /config/providers | List providers and default models |
Provider
| Method | Endpoint | Description |
|---|---|---|
GET | /provider | List all providers |
GET | /provider/auth | Get provider authentication methods |
POST | /provider/{id}/oauth/authorize | Authorize a provider using OAuth |
POST | /provider/{id}/oauth/callback | Handle OAuth callback |
Sessions
| Method | Endpoint | Description |
|---|---|---|
GET | /session | List all sessions |
POST | /session | Create a new session |
GET | /session/status | Get session status for all sessions |
GET | /session/:id | Get session details |
DELETE | /session/:id | Delete a session |
PATCH | /session/:id | Update session properties |
GET | /session/:id/children | Get child sessions |
GET | /session/:id/todo | Get todo list |
POST | /session/:id/init | Analyze app and create AGENTS.md |
POST | /session/:id/fork | Fork existing session |
POST | /session/:id/abort | Abort running session |
POST | /session/:id/share | Share a session |
DELETE | /session/:id/share | Unshare a session |
GET | /session/:id/diff | Get diff for session |
POST | /session/:id/summarize | Summarize session |
POST | /session/:id/revert | Revert a message |
POST | /session/:id/unrevert | Restore reverted messages |
POST | /session/:id/permissions/:permissionID | Respond to permission request |
Messages
| Method | Endpoint | Description |
|---|---|---|
GET | /session/:id/message | List messages in session |
POST | /session/:id/message | Send message and wait for response |
GET | /session/:id/message/:messageID | Get message details |
POST | /session/:id/prompt_async | Send message asynchronously |
POST | /session/:id/command | Execute slash command |
POST | /session/:id/shell | Run shell command |
Commands
| Method | Endpoint | Description |
|---|---|---|
GET | /command | List all commands |
Files
| Method | Endpoint | Description |
|---|---|---|
GET | /find?pattern=<pat> | Search for text in files |
GET | /find/file?query=<q> | Find files and directories by name |
GET | /find/symbol?query=<q> | Find workspace symbols |
GET | /file?path=<path> | List files and directories |
GET | /file/content?path=<p> | Read a file |
GET | /file/status | Get status for tracked files |
/find/file query parameters:
query(required) — search string (fuzzy match)type(optional) — limit results to"file"or"directory"directory(optional) — override the project root for the searchlimit(optional) — max results (1–200)dirs(optional) — legacy flag ("false"returns only files)
Tools (Experimental)
| Method | Endpoint | Description |
|---|---|---|
GET | /experimental/tool/ids | List all tool IDs |
GET | /experimental/tool?provider=<p>&model=<m> | List tools with JSON schemas |
LSP, Formatters & MCP
| Method | Endpoint | Description |
|---|---|---|
GET | /lsp | Get LSP server status |
GET | /formatter | Get formatter status |
GET | /mcp | Get MCP server status |
POST | /mcp | Add MCP server dynamically |
Agents
| Method | Endpoint | Description |
|---|---|---|
GET | /agent | List all available agents |
Logging
| Method | Endpoint | Description |
|---|---|---|
POST | /log | Write log entry |
TUI
| Method | Endpoint | Description |
|---|---|---|
POST | /tui/append-prompt | Append text to prompt |
POST | /tui/open-help | Open help dialog |
POST | /tui/open-sessions | Open session selector |
POST | /tui/open-themes | Open theme selector |
POST | /tui/open-models | Open model selector |
POST | /tui/submit-prompt | Submit current prompt |
POST | /tui/clear-prompt | Clear prompt |
POST | /tui/execute-command | Execute command |
POST | /tui/show-toast | Show toast |
GET | /tui/control/next | Wait for next control request |
POST | /tui/control/response | Respond to control request |
Auth
| Method | Endpoint | Description |
|---|---|---|
PUT | /auth/:id | Set authentication credentials |
Events
| Method | Endpoint | Description |
|---|---|---|
GET | /event | Server-sent events stream |
Docs
| Method | Endpoint | Description |
|---|---|---|
GET | /doc | OpenAPI 3.1 specification |
Plugins
Write your own plugins to extend OpenCode.
Plugins allow you to extend OpenCode by hooking into various events and customizing behavior. You can create plugins to add new features, integrate with external services, or modify OpenCode's default behavior.
Use a plugin
There are two ways to load plugins.
From local files
Place JavaScript or TypeScript files in the plugin directory.
.opencode/plugins/— Project-level plugins~/.config/opencode/plugins/— Global plugins
Files in these directories are automatically loaded at startup.
From npm
Specify npm packages in your config file.
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["opencode-helicone-session", "opencode-wakatime", "@my-org/custom-plugin"]
}Both regular and scoped npm packages are supported.
Browse available plugins in the Ecosystem.
How plugins are installed
npm plugins are installed automatically using Bun at startup. Packages and their dependencies are cached in ~/.cache/opencode/node_modules/.
Local plugins are loaded directly from the plugin directory. To use external packages, you must create a package.json within your config directory (see Dependencies), or publish the plugin to npm and add it to your config.
Load order
Plugins are loaded from all sources and all hooks run in sequence. The load order is:
- Global config (
~/.config/opencode/opencode.json) - Project config (
opencode.json) - Global plugin directory (
~/.config/opencode/plugins/) - Project plugin directory (
.opencode/plugins/)
Duplicate npm packages with the same name and version are loaded once. However, a local plugin and an npm plugin with similar names are both loaded separately.
Dependencies
Local plugins and custom tools can use external npm packages. Add a package.json to your config directory with the dependencies you need.
{
"dependencies": {
"shescape": "^2.1.0"
}
}OpenCode runs bun install at startup to install these. Your plugins and tools can then import them.
import { escape } from "shescape"
export const MyPlugin = async (ctx) => {
return {
"tool.execute.before": async (input, output) => {
if (input.tool === "bash") {
output.args.command = escape(output.args.command)
}
},
}
}Create a plugin
Basic structure
A plugin is a JavaScript/TypeScript module that exports one or more plugin functions. Each function receives a context object and returns a hooks object.
export const MyPlugin = async ({ project, client, $, directory, worktree }) => {
console.log("Plugin initialized!")
return {
// Hook implementations go here
}
}The plugin function receives:
project: The current project information.directory: The current working directory.worktree: The git worktree path.client: An opencode SDK client for interacting with the AI.$: Bun's shell API for executing commands.
TypeScript support
For TypeScript plugins, you can import types from the plugin package:
import type { Plugin } from "@opencode-ai/plugin"
export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree }) => {
return {
// Type-safe hook implementations
}
}Events
Plugins can subscribe to events as seen below in the Examples section. Here is a list of the different events available.
Command Events: command.executed
File Events: file.edited, file.watcher.updated
Installation Events: installation.updated
LSP Events: lsp.client.diagnostics, lsp.updated
Message Events: message.part.removed, message.part.updated, message.removed, message.updated
Permission Events: permission.asked, permission.replied
Server Events: server.connected
Session Events: session.created, session.compacted, session.deleted, session.diff, session.error, session.idle, session.status, session.updated
Todo Events: todo.updated
Shell Events: shell.env
Tool Events: tool.execute.after, tool.execute.before
TUI Events: tui.prompt.append, tui.command.execute, tui.toast.show
Examples
Send notifications
Send notifications when certain events occur:
export const NotificationPlugin = async ({ project, client, $, directory, worktree }) => {
return {
event: async ({ event }) => {
// Send notification on session completion
if (event.type === "session.idle") {
await $`osascript -e 'display notification "Session completed!" with title "opencode"'`
}
},
}
}We are using osascript to run AppleScript on macOS. Here we are using it to send notifications.
If you're using the OpenCode desktop app, it can send system notifications automatically when a response is ready or when a session errors.
.env protection
Prevent opencode from reading .env files:
export const EnvProtection = async ({ project, client, $, directory, worktree }) => {
return {
"tool.execute.before": async (input, output) => {
if (input.tool === "read" && output.args.filePath.includes(".env")) {
throw new Error("Do not read .env files")
}
},
}
}Inject environment variables
Inject environment variables into all shell execution (AI tools and user terminals):
export const InjectEnvPlugin = async () => {
return {
"shell.env": async (input, output) => {
output.env.MY_API_KEY = "secret"
output.env.PROJECT_ROOT = input.cwd
},
}
}Custom tools
Plugins can also add custom tools to opencode:
import { type Plugin, tool } from "@opencode-ai/plugin"
export const CustomToolsPlugin: Plugin = async (ctx) => {
return {
tool: {
mytool: tool({
description: "This is a custom tool",
args: {
foo: tool.schema.string(),
},
async execute(args, context) {
const { directory, worktree } = context
return `Hello ${args.foo} from ${directory} (worktree: ${worktree})`
},
}),
},
}
}The tool helper creates a custom tool that opencode can call. It takes a Zod schema function and returns a tool definition with:
description: What the tool doesargs: Zod schema for the tool's argumentsexecute: Function that runs when the tool is called
Your custom tools will be available to opencode alongside built-in tools.
If a plugin tool uses the same name as a built-in tool, the plugin tool takes precedence.
Logging
Use client.app.log() instead of console.log for structured logging:
export const MyPlugin = async ({ client }) => {
await client.app.log({
body: {
service: "my-plugin",
level: "info",
message: "Plugin initialized",
extra: { foo: "bar" },
},
})
}Levels: debug, info, warn, error. See SDK documentation for details.
Compaction hooks
Customize the context included when a session is compacted:
import type { Plugin } from "@opencode-ai/plugin"
export const CompactionPlugin: Plugin = async (ctx) => {
return {
"experimental.session.compacting": async (input, output) => {
// Inject additional context into the compaction prompt
output.context.push(`## Custom Context
Include any state that should persist across compaction:
- Current task status
- Important decisions made
- Files being actively worked on`)
},
}
}The experimental.session.compacting hook fires before the LLM generates a continuation summary. Use it to inject domain-specific context that the default compaction prompt would miss.
You can also replace the compaction prompt entirely by setting output.prompt:
import type { Plugin } from "@opencode-ai/plugin"
export const CustomCompactionPlugin: Plugin = async (ctx) => {
return {
"experimental.session.compacting": async (input, output) => {
// Replace the entire compaction prompt
output.prompt = `You are generating a continuation prompt for a multi-agent swarm session.
Summarize:
1. The current task and its status
2. Which files are being modified and by whom
3. Any blockers or dependencies between agents
4. The next steps to complete the work
Format as a structured prompt that a new agent can use to resume work.`
},
}
}When output.prompt is set, it completely replaces the default compaction prompt. The output.context array is ignored in this case.
Ecosystem
Projects and integrations built with OpenCode.
A collection of community projects built on OpenCode.
Want to add your OpenCode related project to this list? Submit a PR.
You can also check out awesome-opencode and opencode.cafe, a community that aggregates the ecosystem and community.
Plugins
| Name | Description |
|---|---|
| opencode-daytona | Automatically run OpenCode sessions in isolated Daytona sandboxes with git sync and live previews |
| opencode-helicone-session | Automatically inject Helicone session headers for request grouping |
| opencode-type-inject | Auto-inject TypeScript/Svelte types into file reads with lookup tools |
| opencode-openai-codex-auth | Use your ChatGPT Plus/Pro subscription instead of API credits |
| opencode-gemini-auth | Use your existing Gemini plan instead of API billing |
| opencode-antigravity-auth | Use Antigravity's free models instead of API billing |
| opencode-devcontainers | Multi-branch devcontainer isolation with shallow clones and auto-assigned ports |
| opencode-google-antigravity-auth | Google Antigravity OAuth Plugin, with support for Google Search |
| opencode-dynamic-context-pruning | Optimize token usage by pruning obsolete tool outputs |
| opencode-vibeguard | Redact secrets/PII into placeholders before LLM calls; restore locally |
| opencode-websearch-cited | Add native websearch support for supported providers with Google grounded style |
| opencode-pty | Enables AI agents to run background processes in a PTY, send interactive input |
| opencode-shell-strategy | Instructions for non-interactive shell commands — prevents hangs from TTY-dependent operations |
| opencode-wakatime | Track OpenCode usage with Wakatime |
| opencode-md-table-formatter | Clean up markdown tables produced by LLMs |
| opencode-morph-fast-apply | 10x faster code editing with Morph Fast Apply API and lazy edit markers |
| opencode-morph-plugin | Fast Apply editing, WarpGrep codebase search, and context compaction via Morph |
| oh-my-opencode | Background agents, pre-built LSP/AST/MCP tools, curated agents, Claude Code compatible |
| opencode-notificator | Desktop notifications and sound alerts for OpenCode sessions |
| opencode-notifier | Desktop notifications and sound alerts for permission, completion, and error events |
| opencode-zellij-namer | AI-powered automatic Zellij session naming based on OpenCode context |
| opencode-skillful | Allow OpenCode agents to lazy load prompts on demand with skill discovery and injection |
| opencode-supermemory | Persistent memory across sessions using Supermemory |
| @plannotator/opencode | Interactive plan review with visual annotation and private/offline sharing |
| @openspoon/subtask2 | Extend opencode /commands into a powerful orchestration system with granular flow control |
| opencode-scheduler | Schedule recurring jobs using launchd (Mac) or systemd (Linux) with cron syntax |
| opencode-conductor | Protocol-Driven Workflow: Context → Spec → Plan → Implement lifecycle |
| micode | Structured Brainstorm → Plan → Implement workflow with session continuity |
| octto | Interactive browser UI for AI brainstorming with multi-question forms |
| opencode-background-agents | Claude Code-style background agents with async delegation and context persistence |
| opencode-notify | Native OS notifications for OpenCode — know when tasks complete |
| opencode-workspace | Bundled multi-agent orchestration harness — 16 components, one install |
| opencode-worktree | Zero-friction git worktrees for OpenCode |
| opencode-sentry-monitor | Trace and debug your AI agents with Sentry AI Monitoring |
| opencode-firecrawl | Web scraping, crawling, and search via the Firecrawl CLI |
| opencode-jfrog-plugin | JFrog Plugin for seamless integration of Opencode users to JFrog platform |
| opencode-goal-plugin | Session-scoped /goal workflow that keeps objectives in context and auto-continues until complete |
Projects
| Name | Description |
|---|---|
| kimaki | Discord bot to control OpenCode sessions, built on the SDK |
| opencode.nvim | Neovim plugin for editor-aware prompts, built on the API |
| portal | Mobile-first web UI for OpenCode over Tailscale/VPN |
| opencode plugin template | Template for building OpenCode plugins |
| opencode.nvim | Neovim frontend for opencode — a terminal-based AI coding agent |
| ai-sdk-provider-opencode-sdk | Vercel AI SDK provider for using OpenCode via @opencode-ai/sdk |
| OpenChamber | Web / Desktop App and VS Code Extension for OpenCode |
| OpenCode-Obsidian | Obsidian plugin that embeds OpenCode in Obsidian's UI |
| OpenWork | An open-source alternative to Claude Cowork, powered by OpenCode |
| ocx | OpenCode extension manager with portable, isolated profiles |
| CodeNomad | Desktop, Web, Mobile and Remote Client App for OpenCode |
Agents
| Name | Description |
|---|---|
| Agentic | Modular AI agents and commands for structured development |
| opencode-agents | Configs, prompts, agents, and plugins for enhanced workflows |