Repository sits at the OpenCode config root rather than inside skills/ or
plugins/. OpenCode scans exactly those two subdirectories, and a .git
directory inside either one is picked up as a plugin and fails to load:
loading plugin id=.../plugins/.git entrypoint=.../plugins/.git/index
failed to load plugin ... AggregateError: 2 errors building .../plugins/.git/index
The watcher.ignore config option does not help: it only suppresses filesystem
update events, not plugin discovery, and the "-" disable prefix only applies to
plugins listed in opencode.json(c), not auto-discovered ones.
.gitignore admits only skills/ and plugins/ (plus itself). Personal config
(opencode.jsonc, cli.json, service.json) and node_modules stay local.
skills/opencode-plugins V2-only plugin authoring reference and 7 templates,
transcribed from the V2 docs with the URL on every file
plugins/searxng-search searxng_search tool over a self-hosted SearXNG JSON API
3.1 KiB
Publishing a plugin package
package.json here is strict JSON with no comments, because Node, bun, npm,
and every bundler parse it with a strict parser. Copy it as-is and delete the
entrypoints you do not implement. Guidance lives in this file rather than in
comments inside the manifest.
Source: https://opencode.ai/v2/docs/build/plugins (Publish)
Entrypoints
{
"name": "opencode-acme-plugin",
"version": "1.0.0",
"type": "module",
"exports": {
".": "./src/index.ts",
"./rpc": "./src/rpc.ts",
"./tui": "./src/tui.tsx"
},
"dependencies": {
"@opencode/plugin": "latest"
}
}
| Export | Needed for | Documented on |
|---|---|---|
. |
a server plugin | https://opencode.ai/v2/docs/build/plugins |
./rpc |
publishing a shared RPC contract others can import without loading your implementation. The docs call this export optional. | https://opencode.ai/v2/docs/build/plugins |
./tui |
the TUI plugin. Exporting it makes the CLI load the plugin automatically when the package is listed in opencode.json(c). Do not also add the package to cli.json — the CLI gets the active plugin list from the server. |
https://opencode.ai/v2/docs/build/plugins/cli/ and https://opencode.ai/v2/docs/cli/plugins |
Effect plugin
The documented manifest puts effect in peerDependencies, not
dependencies:
{
"dependencies": { "@opencode/plugin": "latest" },
"peerDependencies": { "effect": ">=4.0.0-rc.112" }
}
Do not bundle effect. OpenCode provides effect, effect/*, and
@opencode/plugin at runtime and redirects imports — including from your
node_modules — to the host instance, so fibers, loggers, and Schema parsers
share one runtime copy. If you bundle, mark effect and effect/* external.
The same Effect page also says to install effect and @opencode/plugin as
peer/dev dependencies for local type-checking:
bun add --peer @opencode/plugin effect
Plugins always execute against the host release's effect. Using APIs or module
paths from another effect major (such as Effect 3) is not supported. Only
public effect subpaths are provided; importing an internal module fails to
load with an error naming the path. The compiled OpenCode binary omits the
Scalar/Swagger UI assets used by Effect's HTTP API doc pages, so serving those
from a plugin shows a notice.
TUI plugin rendering JSX
{
"peerDependencies": {
"@opentui/core": ">=0.5.8",
"@opentui/solid": ">=0.5.8",
"solid-js": ">=1.9.0"
}
}
From https://opencode.ai/v2/docs/build/plugins/cli/. Confirm the version floors against that page before publishing; they are the kind of value that goes stale.
Testing before publishing
Test the installed package, not only a workspace-linked copy:
bun pm pack
bun add ./opencode-acme-plugin-1.0.0.tgz
Use versions compatible with the OpenCode release you target — check with
opencode --version. If a release changes the plugin API, publish a compatible
update rather than leaving an old contract in place.