anomalyco / anomalyco/opencode
beta: V1 plugins unloadable with no migration path, custom commands unreachable headless, no V2 plugin/API docs for agents
@rekram1-node is already working on this.
Since Sep 10, 2026.
- Dominant language
- TypeScript
- Stars
- 209k
- Forks
- 27.5k
- PR merge metrics
- PR metrics pending
Description
Summary
Beta-19271 hardening pass surfaced four independent defects plus a docs gap:
(1) all V1-style plugins fail to load under the V2 schema with no migration
path; (2) custom slash commands registered via command.transform cannot be
invoked through headless run (treated as plain text); (3) recall-scoring
footgun for context-hook authors (behavior note); (4) no V2 plugin API
migration guide or agent-oriented API docs exist, which is why (1)–(3) cost a
full hardening pass to diagnose instead of ten minutes with docs.
Environment
- opencode version: 0.0.0-beta-19271
- OS: Linux 6.17.0-1009-oracle (linux arm64)
- Terminal: Unavailable: headless service (systemd)
- Shell: /bin/bash
- Install/channel: beta
- Active plugins: oh-my-opencode-slim, conclave-v2 (local path),
magic-context-v2 (local path). Notes: a temporary redacted wire-logging
plugin was attached during diagnosis and removed;opencode-supabaseand
listfailures below reproduce from project-local config.
Reproduction
1. V1 plugins unloadable, no migration path
- Configure any of
@op1/goals,opencode2-goal-plugin@1.0.5,
@cortexkit/opencode-magic-context@0.41.2,opencode-supabase, or a
barelistentry inopencode.jsoncplugins. - Start the server.
- Every boot logs, e.g.:
Plugin must export a default definition with an id and an effect or setup function (cause: SchemaError … ["default"]["effect"] … ["default"]["setup"])
ormust default export an object with server(), or
Plugin export is not a function.
2. Custom commands unreachable headless
- Register a command via
ctx.command.transform(editor => editor.add({name: "ctx-status", …}))(loads fine, no errors). - Run
opencode2 run --format json "/ctx-status". - The model receives
/ctx-statusas plain user text ("Checking session
context…") — the handler never fires. No CLI/API path exists to invoke a
registered custom command outside the TUI palette.
3. Recall-scoring footgun (behavior note, local port)
recall(db, "<fixed generic query>", …) plus score-gated fallback
(hits.length>0 ? hits : pool) systematically excludes fresh, distinctive
observations whenever generic session-event rows match the fixed terms. A
planted unique marker (DB-verified, 3 rows from head) was never injected
while noise rows matched. Recency-first retrieval fixed it locally. Suggest
documenting retrieval guidance for context-hook authors.
4. Missing docs: V2 plugin migration guide + agent-oriented API reference
There is no published guide for migrating a V1 plugin (export default async (ctx) => … / {id, server} shapes) to the V2 Plugin.define +
effect/setup API, and no agent-oriented reference for the plugin
surface that coding agents actually need: full SessionHooks inventory
(prompt/context/model.request/http.request/http.response/retry) with
mutability and firing semantics per entry point (TUI vs run vs
exec vs subagent), the command.transform palette-vs-headless matrix,
and the session/tool/event domain method list. The only reason defects
(1)–(3) above required source-diving the bundled @opencode/plugin
.d.ts files is that this documentation does not exist. Request:
(a) a V1→V2 migration guide with before/after for each export shape,
(b) a hook/API reference written for agent implementers, not just humans
clicking the TUI.
Expected Behavior
- Either V1 export shapes keep working or the error names the exact migration
(Plugin.define+effect/setup) with a link. - A supported headless invocation path for registered custom commands
(e.g.runrecognizing leading-/or an explicit flag). - Guidance on recall/injection patterns that survive real session noise.
- Migration + API docs sufficient for an agent to port a plugin without
reverse-engineering bundled type declarations.
Actual Behavior
- SchemaError spam every boot; entire plugin categories (goals, memory,
supabase) dead on beta with no path forward. - Commands exist only in the TUI palette; automation cannot reach them.
- Naive fixed-query recall silently drops fresh context.
- No migration guide; API surface discoverable only via bundled
.d.ts.
Additional Context
- Frequency: 1 and 2 reproduce consistently (100+
listfailures, goals on
every boot until removed; command trial sessionses_f76382ce). - Workarounds: removed dead entries from production config (backups kept);
commands verified by code + DB-level handler tests only; recall fixed
locally via recency-first retrieval. - Related: #48319 (stale composite reasoning ids after restart) — same
hardening pass, filed separately.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.