Version OpenCode skills and plugins
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
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
# Templates
|
||||
|
||||
Starter files transcribed from the OpenCode V2 doc pages. **Copy one and fill in
|
||||
the blanks** rather than writing a plugin from scratch.
|
||||
|
||||
| Template | Use for | Source doc |
|
||||
| -------- | ------- | ---------- |
|
||||
| `promise-plugin.ts` | Server plugin, Promise flavor (default) | <https://opencode.ai/v2/docs/build/plugins> |
|
||||
| `effect-plugin.ts` | Server plugin, Effect-native | <https://opencode.ai/v2/docs/build/plugins/effect/> |
|
||||
| `rpc.ts` | RPC contract, Promise flavor (copy to `src/rpc.ts`) | <https://opencode.ai/v2/docs/build/plugins/rpc/> |
|
||||
| `rpc-implementation.ts` | RPC registration + calls, Promise | <https://opencode.ai/v2/docs/build/plugins/rpc/> |
|
||||
| `rpc-effect.ts` | RPC contract, Effect flavor | <https://opencode.ai/v2/docs/build/plugins/effect/rpc/> |
|
||||
| `rpc-implementation-effect.ts` | RPC registration + calls, Effect | <https://opencode.ai/v2/docs/build/plugins/effect/rpc/> |
|
||||
| `tui-plugin.tsx` | TUI / CLI plugin | <https://opencode.ai/v2/docs/build/plugins/cli/> |
|
||||
| `opencode-plugin-config.jsonc` | `plugins` in `opencode.json(c)` | <https://opencode.ai/v2/docs/plugins> |
|
||||
| `package.json` | Publishing a plugin package (strict JSON) | <https://opencode.ai/v2/docs/build/plugins> |
|
||||
| `package-json.md` | Publishing guidance, peer deps, entrypoints | build/plugins, build/plugins/effect, build/plugins/cli |
|
||||
| `README.md` | This index | — |
|
||||
|
||||
`package.json` is strict JSON with no comments, because Node, bun, npm, and
|
||||
bundlers parse it with a strict parser. Publishing guidance therefore lives in
|
||||
`package-json.md` rather than inside the manifest.
|
||||
|
||||
The two RPC template pairs are **not** interchangeable: same contract shape,
|
||||
different schema dialect, handler signature, and registration entrypoint. See the
|
||||
Promise-vs-Effect table in `../references/rpc.md`.
|
||||
|
||||
## Before you write code
|
||||
|
||||
1. Check the version: `opencode --version`, `opencode api get /api/info`.
|
||||
2. Pick the flavor. Default to Promise. Effect only if the project already uses
|
||||
Effect. TUI is a separate export. RPC is a contract plus a registration.
|
||||
3. Open the source doc in the table above and keep it open.
|
||||
4. Copy the template. Delete the sections you do not need.
|
||||
5. Verify every field name against that page. Do not guess.
|
||||
|
||||
## Rules the templates encode
|
||||
|
||||
These are the constraints the pages state, not stylistic preferences. Note which
|
||||
are type-level rather than documented runtime failures.
|
||||
|
||||
- A `transform` callback is typed `(editor) => void` in both flavors — no
|
||||
Promise, no Effect.
|
||||
- Tool `update` preserves name and namespace. **Assign** a new schema or options
|
||||
object to replace one rather than mutating nested values. In-place edits inside
|
||||
an `update` callback are fine — that is what the mutable draft is for.
|
||||
- `reload()` replays transforms. It does **not** rerun `setup` / `effect`.
|
||||
- Captured inputs are not watched. Load external data before the sync callback,
|
||||
then call `reload()` when it changes.
|
||||
- Use the **effective** tool name — including its namespace — for `update` and
|
||||
`remove` (`example_greeting`, not `greeting`). Only `add` creates a tool.
|
||||
- A `context` hook covers the agent loop only. Register each request kind you
|
||||
actually need.
|
||||
- Result shape is **per operation, not per flavor**: `storage.get` returns a
|
||||
value, `model.list()` is enveloped. Copy the page's example for the call you
|
||||
use.
|
||||
- Effect plugins use `effect`, not `setup`. The two flavors do not have the same
|
||||
context members or the same hook set.
|
||||
- Relative plugin paths in config resolve from the **config file**, not the
|
||||
working directory.
|
||||
- Registering an event subscription without tearing it down leaks it.
|
||||
`forkScoped` handles this in Effect; `AbortController` in Promise.
|
||||
- `package.json` must be strict JSON — `//` comments there break `bun`, `npm`,
|
||||
and every bundler. `opencode.jsonc` may use them.
|
||||
|
||||
## Anything not in a template
|
||||
|
||||
The pages carry more detail than fits here. When you need something not in these
|
||||
files, go to the source doc rather than improvising:
|
||||
|
||||
- Every `Agent.Info`, `Provider.Info`, `Model.Info`, `Session.Info`,
|
||||
`Tool.Content`, `Mcp.Server`, `Skill.Info`, `Vcs.Info`, `Reference.Info`,
|
||||
`Integration.Info`, `Connection.Info`, `Form.Answer`, `Command.Info`,
|
||||
`Plugin.Info`, `WebSearch.*`, `Worktree*` shape:
|
||||
<https://opencode.ai/v2/docs/api>
|
||||
- The exact contract of the running server: `/openapi.json` on that server.
|
||||
- Hook event fields: the `Reference` code block at the end of each section on
|
||||
the relevant page.
|
||||
Reference in New Issue
Block a user