You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[FEATURE]: Plugin API for custom status bar widgets #23539
I have searched existing issues and confirmed this feature hasn't been suggested before
Note: Similar requests exist (#8619 ui.statusLine hook, #18969 ui.footer hook). This issue consolidates and extends those ideas with a concrete proposed API for status bar widgets.
Summary
Allow plugins to register custom widgets in the TUI status bar area, enabling use cases like terminal pets, pomodoro timers, build status indicators, etc.
Motivation
OpenCode's plugin system is powerful for backend logic (event hooks, custom tools, env injection), but there is currently no way for plugins to render custom UI elements in the TUI.
A common use case is displaying persistent status information — for example:
The Bubble Tea framework (used by OpenCode's TUI) supports composable models, so this could potentially be implemented as a composable component in the status bar area.
Several users in the community have expressed interest in customizing the TUI appearance and adding persistent UI elements.
Reacted by Dimfred, Guillaume Dupin, Mikhail Domanoski, Rodrigo "Albo" Arce and must-vanilla
changed the title [-]Feature Request: Plugin API for custom status bar widgets[/-][+][FEATURE]: Plugin API for custom status bar widgets[/+]on Apr 20, 2026
Thank you for updating the issue! It now meets our contributing guidelines — the title has the [FEATURE]: prefix, the verification checkbox is checked, and the request includes clear motivation and a concrete proposed API. The needs:compliance label has been removed.
Adding a concrete use case to support this request: code intelligence provider status in the right panel.
The problem
When a developer uses an MCP-based static analysis tool like gograph, opencode has no visibility into whether the tool's index is fresh. The agent silently queries a stale graph and produces wrong results — and the developer has no way to know without leaving opencode.
LSP servers already solve this for language servers: their status appears in the right panel. The same treatment is missing for tools that build local indexes outside of LSP.
Concrete use case
gograph is a Go AST analysis tool that already ships as a working MCP server (gograph mcp). When configured in opencode.json, all its tools are available to the LLM. The missing piece is a freshness indicator visible in the TUI:
Code Intelligence
gograph ready 75 files · 622 symbols · built 4m ago
If the graph is stale:
gograph STALE 3 source files changed since last build
Proposed minimal contract
A provider exposes a small JSON payload (via stdout, a local socket, or a named pipe — whatever fits the plugin model):
The panel row is driven entirely by this payload — no opencode-side special-casing per tool.
Why this strengthens the existing status bar widget request
A generic "register a status bar widget" API is powerful but abstract. A code intelligence provider interface gives it a concrete, motivating use case with an immediate reference implementation ready to ship. The gograph side of this is a single gograph status --serve subcommand — minimal surface area.
Happy to collaborate on the design if there is appetite for this direction.
Tested on 1.18.3 binary: local plugin's tui export gets invoked, but ctx only contains server-side fields (client/project/directory/$/serverUrl/worktree/experimental_workspace). api.slots is undefined. The TuiPluginRuntime exists internally (createLegacyTuiPluginHost is exported), but external plugins can't reach it. Is TUI slot injection for external plugins planned?
The TuiPluginRuntime module is compiled in, exporting init/dispose/list/installPlugin/addPlugin/activatePlugin/deactivatePlugin/createLegacyTuiPluginHost
What doesn't work
Local plugins in ~/.config/opencode/plugins/*.ts(x) can export a tui function and it gets invoked — but the api argument only contains server-side fields:
api keys: $, client, directory, experimental_workspace, project, serverUrl, worktree
api.slots is undefined. api.ui, api.desktop, api.unsafe — all undefined.
Tried env flags OPENCODE_EXPERIMENTAL, OPENCODE_EXPERIMENTAL_EVENT_SYSTEM, OPENCODE_EXPERIMENTAL_WORKSPACES — none of them unlock slot access for external plugins.
Ask
Is enabling TUI slot injection for external plugins on the roadmap? The internal feature-plugins/sidebar/*.tsx pattern (api.slots.register({ order, slots: { sidebar_content() { ... } } })) is exactly what we'd need. Even a single experimental flag to expose api.slots to local plugins would unlock this entire class of use cases (custom status indicators, skill usage tracking, session metrics, etc.) without changing the architecture.
Happy to help test any experimental build that exposes this.
Design approval request for a compact configurable status display, building on the existing footer and prompt metadata rather than adding another widget system:
Default full-TUI fields: active agent, effective provider/model and supported variant; session directory plus branch/worktree; text state idle, busy or disconnected. At narrow widths, retain state and agent, abbreviate model and truncate the path from the left; details remain available through the existing status/model dialogs.
Selection details should name the source (agent default, saved preference or explicit selection). While generating, distinguish the executing turn from pending next-turn settings. Read both from application state, not polling. Switching/reconnecting sessions must discard stale display state.
Optional fields: context usage with the applicable limit, turn/session tokens and cost with explicit scope, pending permissions and actionable diagnostics. Unknown values stay unknown; estimates are labelled. Users can choose optional fields or disable the bar in tui.json. No color-only information or new dependency is needed.
Current extension points include home_footer, prompt metadata and the session Footer. #38015 and #40412 cover related variant visibility; #48797 covers inline footer extensions. Model-precedence repairs such as #47076 should remain separate from layout work.
Would the core team approve this scope, including settings ownership and the narrow-width fallback, before implementation? This is a request for review, not an assumption that the open feature issue grants approval.
Additional evidence from isolated browser/provider testing: switching from Beta/high to Alpha/low during a held provider request changes the composer immediately, while the captured running request correctly remains Beta/high. The next request uses Alpha/low. Also, selecting Default under an agent configured high displays Default while the provider receives reasoning_effort=high. These reinforce the proposed executing-versus-next-turn distinction and an accessible explanation of inherited defaults; I have not changed those semantics.
For anyone landing here: TUI plugins can already render into the prompt rows through the session_prompt_right slot (registered with api.slots.register from @opencode-ai/plugin/tui). opencode-session-title is a ~50-line example that shows the session title there. On narrow terminals that row currently wraps mid-word once a plugin adds content; #53062 fixes the layout so slot content truncates instead, which may matter for the compact display @fobiat described.
This is implemented in v2 through the TUI plugin slot API: plugins can render reactive widgets in the prompt status row, home footer status area, and sidebar footer using app.slot(...). To upgrade, run npm i -g @opencode/cli@latest; existing v1 plugins need to use the v2 plugin API. If you still see this on v2, please open a new issue with the details.
Activity
github-actions commentedon Apr 20, 2026
This issue doesn't fully meet our contributing guidelines.
What needs to be fixed:
[FEATURE]:(e.g.,[FEATURE]: Plugin API for custom status bar widgets)Please edit this issue to address the above within 2 hours, or it will be automatically closed.
This issue might be a duplicate of existing issues. Please check:
tui.statusLinehooktui.footer.itemsplugin hook for persistent status display — directly requests plugin-injected footer/status items with ordering and stylingIf you believe this was flagged incorrectly, please let a maintainer know.
[-]Feature Request: Plugin API for custom status bar widgets[/-][+][FEATURE]: Plugin API for custom status bar widgets[/+]github-actions commentedon Apr 20, 2026
Thank you for updating the issue! It now meets our contributing guidelines — the title has the
[FEATURE]:prefix, the verification checkbox is checked, and the request includes clear motivation and a concrete proposed API. Theneeds:compliancelabel has been removed.ozgurcd commentedon Jun 6, 2026
Adding a concrete use case to support this request: code intelligence provider status in the right panel.
The problem
When a developer uses an MCP-based static analysis tool like gograph, opencode has no visibility into whether the tool's index is fresh. The agent silently queries a stale graph and produces wrong results — and the developer has no way to know without leaving opencode.
LSP servers already solve this for language servers: their status appears in the right panel. The same treatment is missing for tools that build local indexes outside of LSP.
Concrete use case
gograph is a Go AST analysis tool that already ships as a working MCP server (
gograph mcp). When configured inopencode.json, all its tools are available to the LLM. The missing piece is a freshness indicator visible in the TUI:If the graph is stale:
Proposed minimal contract
A provider exposes a small JSON payload (via stdout, a local socket, or a named pipe — whatever fits the plugin model):
{ "name": "gograph", "kind": "code-intelligence", "status": "ready | stale | building | error", "details": { "indexed_files": 75, "symbols": 622, "last_built": "2026-06-06T15:00:00Z", "stale_files": 0 } }The panel row is driven entirely by this payload — no opencode-side special-casing per tool.
Why this strengthens the existing status bar widget request
A generic "register a status bar widget" API is powerful but abstract. A code intelligence provider interface gives it a concrete, motivating use case with an immediate reference implementation ready to ship. The gograph side of this is a single
gograph status --servesubcommand — minimal surface area.Happy to collaborate on the design if there is appetite for this direction.
Hona commentedon Jul 17, 2026
Maybe one day!
But I made an unofficial desktop extension SDK called
ocdxwiht some sample plugins like VERTICAL TABShttps://github.com/Hona/opencode-desktop-extensions
2102014 commentedon Jul 20, 2026
Tested on 1.18.3 binary: local plugin's tui export gets invoked, but ctx only contains server-side fields (client/project/directory/$/serverUrl/worktree/experimental_workspace). api.slots is undefined. The TuiPluginRuntime exists internally (createLegacyTuiPluginHost is exported), but external plugins can't reach it. Is TUI slot injection for external plugins planned?
2102014 commentedon Jul 21, 2026
Following up on this with hard evidence from testing on opencode v1.18.3 (Windows x64 binary).
What works
The TUI slot system exists internally — confirmed by extracting strings from opencode.exe:
What doesn't work
Local plugins in ~/.config/opencode/plugins/*.ts(x) can export a tui function and it gets invoked — but the api argument only contains server-side fields:
api keys: $, client, directory, experimental_workspace, project, serverUrl, worktree
api.slots is undefined. api.ui, api.desktop, api.unsafe — all undefined.
Tried env flags OPENCODE_EXPERIMENTAL, OPENCODE_EXPERIMENTAL_EVENT_SYSTEM, OPENCODE_EXPERIMENTAL_WORKSPACES — none of them unlock slot access for external plugins.
Ask
Is enabling TUI slot injection for external plugins on the roadmap? The internal feature-plugins/sidebar/*.tsx pattern (api.slots.register({ order, slots: { sidebar_content() { ... } } })) is exactly what we'd need. Even a single experimental flag to expose api.slots to local plugins would unlock this entire class of use cases (custom status indicators, skill usage tracking, session metrics, etc.) without changing the architecture.
Happy to help test any experimental build that exposes this.
fobiat commentedon Sep 17, 2026
Design approval request for a compact configurable status display, building on the existing footer and prompt metadata rather than adding another widget system:
Default full-TUI fields: active agent, effective provider/model and supported variant; session directory plus branch/worktree; text state
idle,busyordisconnected. At narrow widths, retain state and agent, abbreviate model and truncate the path from the left; details remain available through the existing status/model dialogs.Selection details should name the source (agent default, saved preference or explicit selection). While generating, distinguish the executing turn from pending next-turn settings. Read both from application state, not polling. Switching/reconnecting sessions must discard stale display state.
Optional fields: context usage with the applicable limit, turn/session tokens and cost with explicit scope, pending permissions and actionable diagnostics. Unknown values stay unknown; estimates are labelled. Users can choose optional fields or disable the bar in
tui.json. No color-only information or new dependency is needed.Current extension points include
home_footer, prompt metadata and the session Footer. #38015 and #40412 cover related variant visibility; #48797 covers inline footer extensions. Model-precedence repairs such as #47076 should remain separate from layout work.Would the core team approve this scope, including settings ownership and the narrow-width fallback, before implementation? This is a request for review, not an assumption that the open feature issue grants approval.
fobiat commentedon Sep 17, 2026
Additional evidence from isolated browser/provider testing: switching from Beta/high to Alpha/low during a held provider request changes the composer immediately, while the captured running request correctly remains Beta/high. The next request uses Alpha/low. Also, selecting Default under an agent configured high displays Default while the provider receives reasoning_effort=high. These reinforce the proposed executing-versus-next-turn distinction and an accessible explanation of inherited defaults; I have not changed those semantics.
moritzWa commentedon Oct 4, 2026
For anyone landing here: TUI plugins can already render into the prompt rows through the
session_prompt_rightslot (registered withapi.slots.registerfrom@opencode-ai/plugin/tui). opencode-session-title is a ~50-line example that shows the session title there. On narrow terminals that row currently wraps mid-word once a plugin adds content; #53062 fixes the layout so slot content truncates instead, which may matter for the compact display @fobiat described.neriousy commentedon Oct 19, 2026
This is implemented in v2 through the TUI plugin slot API: plugins can render reactive widgets in the prompt status row, home footer status area, and sidebar footer using
app.slot(...). To upgrade, runnpm i -g @opencode/cli@latest; existing v1 plugins need to use the v2 plugin API. If you still see this on v2, please open a new issue with the details.