Skip to content

tui: Add a per-assistant-message footer slot to the TUI plugin API #46268

Open

Description

@cavokz
  • I have searched for existing issues before filing this

This is a focused follow-up to #20504 and #24376, which were automatically closed after periods of inactivity. The request remains relevant, but this proposal is narrowed to a concrete API for the current TUI implementation.

The TUI currently exposes slots for the application, prompt, sidebar, and global footer, but not for an individual assistant message. The assistant metadata footer is rendered directly in packages/tui/src/routes/session/index.tsx.

This prevents plugins from attaching information to the response that produced it. Useful examples include:

  • Cache read/write counts and cache hit rate
  • Tokens per second
  • Provider latency
  • Per-response cost
  • Evaluation or debugging metadata
  • A collapsed + Turn details row that expands when clicked, similar to the existing + Thought reasoning control

Please add an additive per-assistant-message slot, for example:

assistant_message_footer: {
  session_id: string
  message_id: string
  message: AssistantMessage
  parts: readonly Part[]
  terminal: boolean
  last: boolean
}

The slot would be rendered after the assistant content and built-in metadata, inside the transcript scrollbox. The terminal flag would distinguish a completed response from intermediate assistant messages that end with tool calls. The last flag identifies the newest assistant message in the session, which may still be streaming, so plugins can render live footers.

The exact payload shape can be adjusted by maintainers. At minimum, the slot needs to identify the assistant message and its session. The default UI should remain unchanged when no plugin contributes content, and multiple plugins should be able to contribute in deterministic order.

This should not require a server or protocol change. The TUI already has the message, parts, token usage, cost, and completion state locally.

Prior related requests:

  • #20504 requested additional TUI slots, including locations around the assistant metadata and subagent footer.
  • #24376 proposed an assistant_metadata_right slot for throughput, cache statistics, cost, and provider latency.
  • #18969 requested persistent global footer items, which does not provide per-response association.
  • #5971 requested session-level custom sidebar panels.

This proposal makes the per-assistant-message case explicit and adds support for block-level, expandable plugin content rather than only inline metadata.

Activity

  1. cavokz commented on Sep 12, 2026

    @cavokz
    Author

    Hello, any chance to have this triaged and maybe the connected PR reviewed?

  2. changed the title [-][FEATURE]: Add a per-assistant-message footer slot to the TUI plugin API[/-] [+]tui: Add a per-assistant-message footer slot to the TUI plugin API[/+] on Sep 12, 2026
  3. leoscricca commented on Oct 28, 2026

    @leoscricca

    I built a read-aloud plugin that adds Play/Pause, Stop, seek, and speed controls beneath each completed answer, including answers in session history.

    Currently, I have to patch and rebuild OpenCode to put the controls there. An additive per-assistant-message TUI slot, with sessionID and messageID, would let plugins use the existing message data and render interactive, theme-aware controls without a custom build or server changes. For example:

    context.ui.slot({
      append: "session.message.footer", // illustrative name
      render: ({ sessionID, messageID }) => (
        <ReadAloudControls sessionID={sessionID} messageID={messageID} />
      ),
    })

    The slot should also work for historical messages and allow multiple plugins to contribute without replacing OpenCode's built-in metadata.

    Two OpenCode replies, each with its own read-aloud controls

    Example from a locally patched OpenCode TUI; the conversation and playback are simulated for this screenshot.

  4. opencodejr commented on Oct 28, 2026

    @opencodejr

    Thanks for the detailed and narrowly scoped proposal! You're asking for a per-assistant-message slot in the TUI plugin API, rendered after the built-in assistant metadata in the transcript, so plugins can show per-response information such as cache stats, throughput, latency, cost or an expandable "Turn details" row.

    I checked the current v2 code, and this can't be done as a plugin yet. The slot tree (SlotMap in packages/plugin/src/tui/context.ts) only has app, home.footer*, prompt.footer*, session.composer.top, session.panel and sidebar.*. The assistant metadata in packages/tui/src/routes/session/index.tsx isn't wrapped in a <Slot>, so plugins have nothing per message to attach to. One way to add it would be a new SlotMap entry keyed by sessionID/messageID, plus flags like your terminal/last. The existing before/append/after placements would then handle ordering between multiple plugins.

    Related issues:

    Maintainers will consider it.

  5. cavokz commented on Oct 28, 2026

    @cavokz
    Author

    For the record, #46562 is my intent to implement this new slot.

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