anomalyco / anomalyco/opencode

opencode attach discovers project-local tui.json but never invokes the plugin's tui() export

Open
#46,556 0 comments 0 reactions 1 assignee View on GitHub

@simonklee is already working on this.

Since Sep 1, 2026.

2.0
Dominant language
TypeScript
Stars
209k
Forks
27.5k
PR merge metrics
PR metrics pending

Description

Version: opencode-ai 1.18.25 (also reproduced on 1.18.21 — same behavior across both, not a fresh regression tied to a specific patch release)

Environment: opencode attach <url> (run from the host machine) vs. running opencode directly, both against the same already-running opencode web server process, on the same machine, same OpenCode version. In our setup that server happens to run inside a Docker container, but that's a deployment detail — attach-vs-direct-run is what differs here, not the server's hosting environment, and nothing in the reproduction depends on containerization.

Expected: a tui.json-declared plugin's tui(api) export runs when connecting via opencode attach, same as it does when running opencode directly against the same server.

Actual: tui.json is discovered and applied by attach — confirmed in the client-side log:

timestamp=2026-09-01T06:43:16.786Z level=INFO run=2874087d message="loading tui config" path=/home/kufi/Projects/kufis-ai-forge/.opencode/tui.json
timestamp=2026-09-01T06:43:16.798Z level=INFO run=2874087d message="applying tui config" path=/home/kufi/Projects/kufis-ai-forge/.opencode/tui.json order=2

but tui() is never invoked — verified with a plugin that only writes a result file on invocation; no file ever appears via attach, across three attempts with increasing wait times (20s / 20s / 55s, ruling out a timing/race issue), both with and without the plugin's local deps pre-cached. The identical plugin, identical tui.json, loads and runs correctly when the same OpenCode instance is driven via opencode directly instead of attach.

Repro: exact plugin used (project-local, declared in tui.json as "plugin": ["./plugins-tui-test/test-sidebar.tsx"]):

/** @jsxImportSource @opentui/solid */
import type { TuiPluginModule } from "@opencode-ai/plugin/tui"
import { writeFileSync } from "node:fs"

const RESULT_FILE = "/path/to/project/.opencode/plugins-tui-test/result.json"

const plugin: TuiPluginModule = {
  id: "invocation-probe",
  async tui(api) {
    try {
      api.slots.register({
        slots: { sidebar_content(_ctx, _props) { return <text>probe</text> } },
      })
      writeFileSync(RESULT_FILE, JSON.stringify({ invoked: true, registerOk: true }))
    } catch (error) {
      writeFileSync(RESULT_FILE, JSON.stringify({ invoked: true, registerOk: false, error: String(error) }))
    }
  },
}
export default plugin

The slots.register/JSX call isn't required to demonstrate the gap (only the file write matters) — kept as-is because it's the exact code that was run, not a simplified rewrite. Start the server (opencode web or equivalent), then compare opencode attach <url> --dir <project> against running opencode directly in that project directory — check for RESULT_FILE after each.

Note: not the same issue as #36525 (that's about opencode2 next-builds never invoking any TUI plugin at all, including local); this is specifically about attach behaving differently from direct invocation on the same stable (1.x) line — discovery works, invocation doesn't, only over attach.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.