feat(opencode): TUI sidebar plugin showing active Plannotator session URL - #1386
Open
expnn wants to merge 1 commit into
Open
feat(opencode): TUI sidebar plugin showing active Plannotator session URL#1386expnn wants to merge 1 commit into
expnn wants to merge 1 commit into
Conversation
expnn
force-pushed
the
tui-sidebar-plugin
branch
9 times, most recently
from
August 25, 2026 07:49
9865955 to
75fcf4f
Compare
… URL
- New TUI plugin face (apps/opencode-plugin/tui.tsx, exported via "./tui")
registers a sidebar_content slot that displays the current Plannotator
session URL in the opencode sidebar, matching the built-in section styling
(bold title via <b> inside <text>, fg={theme.text}).
- Server plugin (commands.ts) writes the full URL to a session-url file
(~/.plannotator/opencode-session-url) on ready and clears it on session
end. The TUI plugin polls this file every 2s.
- TUI rendering uses ONLY @opentui/solid's direct API (createElement,
insertNode, setProp, insert) — no solid-js imports, avoiding dual
solid-js instance conflicts with the host runtime.
- Host resolution (shared via session-url.ts getServerHostname) mirrors
@expnn/opencode-server-info: extracts the opencode server's hostname
from client.client.getConfig().baseUrl; port comes from plannotator's
URL. Both the TUI sidebar and the toast notification use http://{host}:{port}.
- Toast notification retained via client.tui.showToast; stderr "session
ready" overlay suppressed by skipping handleServerReady in onReady.
- Build: tsup + esbuild-plugin-solid (universal generate, moduleName
@opentui/solid), external only @opentui/solid + solid-js.
- Module-level timer guard (activeTimer) limits to one setInterval per
process; cleared on sidebar re-mount to prevent accumulation.
expnn
force-pushed
the
tui-sidebar-plugin
branch
from
August 25, 2026 09:44
75fcf4f to
5a094a9
Compare
expnn
marked this pull request as ready for review
August 25, 2026 13:33
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a TUI plugin face to the OpenCode plugin that displays the active Plannotator session URL in the opencode sidebar.
Problem
When running Plannotator on a remote server (via SSH), the session URL is only shown as a stderr overlay that breaks the TUI. Users need a persistent, copyable URL in the sidebar.
Result
Solution
tui.tsx, exported via"./tui"): registers asidebar_contentslot that displays the URL. Uses only@opentui/solid's direct API (createElement,insertNode,setProp,insert).~/.plannotator/opencode-session-url(JSONL format:{"url":"...","sid":"<session_id>"}) on ready; TUI plugin polls every 2s and filters bysession_idfor multi-instance correctness.getServerHostname(api.client, api.state)extracts the opencode server's hostname fromapi.client.client.getConfig().baseUrl, with fallbacks toOPENCODE_HOSTenv var andstate.config.server.hostname.ctx.serverUrl(the opencode server's actual listen URL) threaded throughindex.ts→embedded.ts→commands.ts→resolveToastHost(serverUrl). Separate from the TUI's hostname resolution.withStderrSuppressed(() => handleServerReady(...))wrapshandleReviewServerReady/handleAnnotateServerReadycalls — preserves browser opening + ready-file, suppresses only the stderr overlay that corrupts layout of the TUI.client.tui.showToastwith "(URL also in sidebar)" hint.session_id;clearSessionUrl(url)removes only the matching URL's line (keeps other sessions intact).activeTimerlimits to onesetIntervalper process; cleared on sidebar re-mount.Testing
bun test apps/opencode-plugin/— 118 pass, 0 faildist/tui.jsbuilt with tsup, verified zerosolid-jsimportsFiles
tui.tsx(new)sidebar_contentslot,getServerHostname(TUI-only),insert-based URL display, no solid-jssession-url.ts(new)writeSessionUrl(url, sid),clearSessionUrl(url),readSessionUrl(sid)— multi-instance safetsup.tui.config.ts(new)@opentui/solid+solid-jstsconfig.json(new)commands.tswithStderrSuppressedwrapper,resolveToastHost+showPlannotatorToast,sessionIdhoisted,writeSessionUrl/clearSessionUrlhooks in 3onReadycallbacksembedded.tsserverUrl?: URLin deps typeindex.tsserverUrl: ctx.serverUrlthreaded to depscommands.test.tsPLANNOTATOR_DATA_DIRsandboxpackage.json"./tui"export, deps (@opentui/solid,solid-js), devDeps (tsup,esbuild-plugin-solid), build script appends tsuppackage-boundary.test.ts./tuiexport assertion