Overview
Plugins modify OpenCode’s behavior and add new features. A plugin is one package with a server part, a TUI part, a GUI part, or any combination.
import { Plugin } from "@opencode/plugin"
export default Plugin.define({
id: "example",
async setup(ctx) {
await ctx.storage.set("loaded", true)
},
})Migrating an existing OpenCode 1 plugin? Follow the V1 plugin migration guide.
Parts
Each part is an export of the package. Every part’s SDK comes from the one @opencode/plugin dependency.
{
"name": "opencode-acme-plugin",
"version": "1.0.0",
"type": "module",
"exports": {
".": "./src/index.ts",
"./tui": "./src/tui.tsx",
"./gui-experimental": "./dist/gui-experimental.cjs",
"./rpc": "./src/rpc.ts"
},
"files": ["src", "dist"],
"dependencies": {
"@opencode/plugin": "latest"
}
}- Server (
.or./server) runs in the OpenCode server with@opencode/plugin. It adds tools, hooks, integrations, commands, and agents. See Server, or Effect plugins for the Effect API. - TUI (
./tui) runs in the terminal UI with@opencode/plugin/tui. See TUI. - GUI (
./gui-experimental) runs itssetupin every OpenCode Desktop window and itsmainin the desktop app’s main process, with@opencode/plugin/gui. See GUI. - RPC (
./rpc) is a typed contract that the server part implements and the other parts and clients call. See RPC.
The plugin’s id comes from its server part’s Plugin.define. A package with a GUI part and no server part takes its
package name (or a local directory’s name) as its id. A TUI part declares its own id; a GUI part declares none and
takes the plugin’s.
Load
Plugins under .opencode/plugins/ load automatically, like the local example above. To load published packages or
plugin directories from other locations, add them to plugins in opencode.json(c):
{
"$schema": "https://opencode.ai/config.json",
"plugins": [
"opencode-acme-plugin",
"opencode-acme-plugin@1.2.0",
"@acme/opencode-plugin",
"./plugins/local",
"../shared/plugin",
"/absolute/path/plugin",
"file:///home/me/plugins/local",
{
"package": "@acme/opencode-plugin",
"options": {
"agent": "reviewer",
"strict": true,
},
},
],
}- One entry loads every part. The TUI loads the TUI parts of the plugins its server loads, and OpenCode Desktop loads
the GUI parts of the plugins in your global
opencode.json(c). - A package with only a TUI part goes in
cli.jsoninstead. - A local plugin directory with a
package.jsonnameandexportsloads its parts through them, like the published package. Without them, it uses file names at its root:server(elseindex),tui, andrpcwith a.ts,.tsx, or.jsextension, andgui-experimental.cjs(or.js). - See Configure plugins for more loading and configuration options.
Publish
A published plugin is an npm package with the package.json above. Its parts use the same default exports as a local
plugin.
npm publish
- Export
./rpcwhen other plugins and clients should import your RPC contract without loading your implementation. - Build the GUI bundle before you publish, and include it through
files. See Build the bundle. - Use versions compatible with the OpenCode release you target, and test the installed package, not only a workspace-linked copy. Publish a compatible plugin update when you adopt a newer API contract.
Add tools, hooks, integrations, commands, and agents in the OpenCode server.
Add commands, routes, slots, and Markdown renderers to the terminal UI.
Add panels, commands, settings pages, and native integrations to OpenCode Desktop.
Expose typed methods and events from the server part to the other parts and to clients.