anomalyco / anomalyco/opencode
tui: JSX syntax in plugin .tsx files breaks npm-installed plugins (bun-injected @opentui/solid/jsx-dev-runtime import can't resolve)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 209k
- Forks
- 27.5k
- PR merge metrics
- PR metrics pending
Description
Summary
A TUI plugin installed via opencode plugin <npm-package> --global silently fails to load when its .tsx source uses JSX syntax. The @opentui/solid/jsx-dev-runtime specifier that is injected by bun's native JSX transform is resolved natively relative to the plugin file (bypassing the runtime-plugin rewrite loader), and npm-installed plugins live under ~/.cache/opencode/packages/<pkg>@<ver>/node_modules/<pkg>/, which has no upward @opentui to resolve against. Result: Cannot find package '@opentui/solid', consumed as a silent no-op (no sidebar, no plugin entry) — that's #41574's diagnostic gap in action.
Root cause (debugged)
Running the plugin outside the dev overlay (~/.cache/opencode/packages/...):
- Loading the npm
./tuientry with JSX present →IMPORT FAILED: Cannot find package '@opentui/solid'. - The REWRITE-LOADER in the runtime-plugin support fires for the file itself, but not for the dev-runtime import bun injects, because that injection happens in the native transform after rewriting (or is resolved by a code path that ignores plugin resolvers).
- Removing every JSX expression and importing
jsxDEVexplicitly from"@opentui/solid/jsx-dev-runtime"makes the same file import cleanly from the identical cache location: the explicit import is a runtime specifier → rewritten to the correct virtual module. Confirmed in 1.18.31's install-store layout.
So the bug is specifically: JSX syntax in plugin sources is unsupported for npm-installed plugins, while repo/dev-overlay plugins work because their location happens to resolve upward into the app's node_modules.
The same failure likely underlies parts of #33884 (npm-spec plugins silently failing) and the "render once / never updates" #48883 path.
Repro
opencode plugin opencode-token-min --global(usesexports["./tui"], verified on 1.18.31).- The installed copy at
~/.cache/opencode/packages/opencode-token-min@<ver>/node_modules/opencode-token-min/tui/token-min.tsxcontains<box>/<text>JSX. - Start a TUI session → no sidebar from the plugin; nothing in logs.
- Import the file through the runtime-plugin support from that path →
Cannot find package '@opentui/solid'.
Suggested fixes (any one)
- Run the plugin-rewrite loader after the native TSX transform so injected dev-runtime specifiers are also rewritten.
- Make the rewrite loader catch specifier rewrites for injected imports (resolve
@opentui/...against the host runtime). - If neither is feasible, at least surface the load failure in logs (#41574) instead of failing silently.
Workaround (no runtime change needed)
Keep plugin sources JSX-free: import { jsxDEV } from "@opentui/solid/jsx-dev-runtime" and build elements with jsxDEV("box", { children: [...] }). Added to opencode-token-min v1.0.2.
Context: related #27447, #48883, #33884, #41574, #39986.
Debugging performed by the opencode agent (Big Pickle), supervised by tmiland.
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.
Research direction
Reproduce with the npm-installed opencode-token-min package and its tui/token-min.tsx entry, then inspect the runtime-plugin support around the rewrite loader and native TSX transform. Done means a JSX-containing plugin loads from ~/.cache/opencode/packages and renders its sidebar; if loading still fails, the error should be visible in logs rather than becoming a silent no-op.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- bun, typescript
- Domain
- cli, devtools
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100