anomalyco / anomalyco/opencode
tui: plugins no longer load after cli.json config migration (nightly next channel)
@simonklee is already working on this.
Since Aug 12, 2026.
- Dominant language
- TypeScript
- Stars
- 209k
- Forks
- 27.5k
- PR merge metrics
- PR metrics pending
Description
Summary
TUI plugins stopped loading in the next nightly channel after builds that migrated TUI config into cli.json. Plugin entries in tui.json (string/tuple form) and cli.json ({package, options} form) are both ignored — the TUI runtime never attempts to load them. Adding the same plugin to the server config (opencode.jsonc plugins) makes the server load it as a server plugin and crash with TypeError: undefined is not an object (evaluating 'context.storage.memory') because TUI-only context capabilities do not exist server-side.
Environment
- opencode version:
0.0.0-next-17297(also reproduced on0.0.0-next-17296) - OS: Linux Fedora 43,
7.1.7-100.fc43.x86_64 - Terminal: tmux (
TERM=xterm-256color, truecolor) - Shell: fish
- Install/channel:
next(npm global install of@opencode-ai/cli) - Active plugins: local TUI plugin
/home/samarth/repos/live-token-info/src/index.tsx(id: live-token-meter, usescontext.storage.memoryandcontext.ui.slot("prompt.footer.end")); previously also@renjfk/opencode-voice
Reproduction
-
Create a local TUI plugin module:
index.tsxwith/** @jsxImportSource @opentui/solid */,import { Plugin } from "@opencode-ai/plugin/tui", andPlugin.define({ id, setup(ctx) { ctx.storage.memory(...); ctx.ui.slot("prompt.footer.end", ...) } }). -
Add it to
~/.config/opencode/tui.jsonas a tuple:"plugin": [ ["/path/to/plugin.tsx", { "charsPerToken": 4, "showTotals": true }] ](Same form used by the working
.opencode/tui.jsonexample for thetui-smokefixture in this repo.) -
Restart the TUI (
opencode2). -
The plugin does not load. No entry appears in
~/.local/state/opencode/plugin-meta.jsonand no client-side log messages are emitted. -
Alternative: add the same plugin to
~/.config/opencode/opencode.jsoncas"plugins": [{ "package": "/path/to/plugin.tsx", "options": {...} }]and restart. The server log shows:msg="loading plugin" id=/path/to/plugin.tsx entrypoint="/path/to/plugin.tsx?mtime=..." message="failed to load plugin" plugin.id=live-token-meter cause="Cause([Die(TypeError: undefined is not an object (evaluating 'context.storage.memory'))])"
Expected Behavior
TUI-kind plugins load in the TUI client with the TUI plugin context (storage, ui, theme, data), either from client config entries (tui.json tuples / cli.json {package, options}) or through server-side kind detection that routes them to the client without executing setup with a server context.
Actual Behavior
- The TUI runtime ignores all client-config plugin entries (no attempts recorded in
plugin-meta.jsonor logs) since thecli.jsonmigration appeared innext-17098(server log:migrated cli configon 2026-08-10). - Server-config entries load the module as a server plugin and crash in
setuponcontext.storage.memorybeing undefined. - Timeline confirmation: TUI plugin
@renjfk/opencode-voiceloaded successfully 46 times until thenext-17055era (last load 2026-08-09) and never again after the migration landed; thetui-smoke.tsxfixture loaded once on 2026-07-02 and has not re-loaded since.
Additional Context
Config used for reproduction:
// ~/.config/opencode/tui.json
"plugin": [
["/home/samarth/repos/live-token-info/src/index.tsx", { "charsPerToken": 4, "showTotals": true }]
]
// ~/.config/opencode/cli.json (rewritten each start by the built-in migration)
"plugins": [
{ "package": "/home/samarth/repos/live-token-info/src/index.tsx", "options": { "charsPerToken": 4, "showTotals": true } }
]
- Stable channel 1.18.16 still contains the legacy client-side flow (
loading tui config/skipping invalid tui configmessage strings) and does not exhibit the regression. The nightly binary (next-17297) no longer contains those strings, which matches the client runtime no longer reading client config. - Consistently reproducible across roughly 10 client restarts.
- No workaround found; the server-config entry must be removed to stop the crash on every start. The plugin itself is unaffected (module imports fine; the failure happens inside
setupwith a server context).
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.