Skip to content

[FEATURE]: Plugin API for custom status bar widgets #23539

Closed

Description

@excess122

Feature Request

Verification

  • 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:

  • A terminal pet that reacts to coding activity
  • Build/test status indicators
  • Pomodoro/focus timers
  • Custom metrics (lines written, commits today, etc.)

Proposed API

export const MyPlugin: Plugin = async (ctx) => {
  return {
    "tui.statusbar.widget": {
      id: "my-widget",
      position: "right",
      render: () => "pet Lv.5 | streak: 7d",
      interval: 5000,
    },
  }
}

Alternatives Considered

  • Running a separate terminal program in a split pane (works but feels disconnected)
  • Modifying OpenCode source directly (not maintainable)

Additional Context

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.

Activity

  1. added
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on Apr 20, 2026
  2. github-actions commented on Apr 20, 2026

    @github-actions
    Contributor

    This issue doesn't fully meet our contributing guidelines.

    What needs to be fixed:

    • The title should start with [FEATURE]: (e.g., [FEATURE]: Plugin API for custom status bar widgets)
    • The feature request template requires a verification checkbox confirming the feature hasn't been suggested before — this is missing

    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:

    If you believe this was flagged incorrectly, please let a maintainer know.

  3. changed the title [-]Feature Request: Plugin API for custom status bar widgets[/-] [+][FEATURE]: Plugin API for custom status bar widgets[/+] on Apr 20, 2026
  4. github-actions commented on Apr 20, 2026

    @github-actions
    Contributor

    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.

  5. removed
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on May 3, 2026
  6. ozgurcd commented on Jun 6, 2026

    @ozgurcd

    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):

    {
      "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 --serve subcommand — minimal surface area.

    Happy to collaborate on the design if there is appetite for this direction.

  7. Hona commented on Jul 17, 2026

    @Hona
    Member

    Maybe one day!

    But I made an unofficial desktop extension SDK called ocdx wiht some sample plugins like VERTICAL TABS

    https://github.com/Hona/opencode-desktop-extensions

  8. 2102014 commented on Jul 20, 2026

    @2102014

    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?

  9. 2102014 commented on Jul 21, 2026

    @2102014

    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:

    • Slot names: sidebar_content, sidebar_title, sidebar_footer, home_footer, home_bottom, home_prompt, session_prompt, session_prompt_right, app, app_bottom, home_logo
    • Built-in feature plugin IDs: internal:sidebar-mcp, internal:sidebar-lsp, internal:sidebar-todo, internal:sidebar-context, internal:sidebar-files, internal:sidebar-footer, internal:home-footer, internal:home-tips
    • 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.

  10. fobiat commented on Sep 17, 2026

    @fobiat

    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.

  11. fobiat commented on Sep 17, 2026

    @fobiat

    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.

  12. moritzWa commented on Oct 4, 2026

    @moritzWa

    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.

  13. neriousy commented on Oct 19, 2026

    @neriousy
    Member

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions