Skip to content

TUI plugins get a theme snapshot, so the sidebar doesn't recolor on theme/mode change #63305

Closed

Description

@sidevesh

Description

context.theme in the TUI plugin API returns host.themes.currentTokens(), which is the theme resolved at that moment. The built-in sidebar plugins (context, mcp, limit, todo) and the diff viewer read props.context.theme once at setup, so they keep the old colors after a theme or light/dark change. Easy to see with a theme that has both modes: switch macOS appearance and the sidebar's "Context" heading stays #eeeeee on a light background while everything else updates.

OpenCode version

2.2.7

Steps to reproduce

Use a theme with dark and light variants, open a session with the sidebar visible, switch macOS between dark and light.

Operating System

macOS

Terminal

iTerm2

Activity

  1. opencodejr commented on Nov 11, 2026

    @opencodejr
    Contributor

    Thanks for the clear report. I could reproduce this on 2.2.7, and it still happens on the latest dev (611cee9).

    What I did:

    1. Used the built-in opencode theme in dark mode, with two (disabled) MCP servers configured so the sidebar's MCP section shows.
    2. Opened a session with the sidebar visible.
    3. Switched to light mode with the theme.switch_mode command.

    What happened: the rest of the UI turned light, but the sidebar's MCP heading and server names kept their dark-mode near-white color and became nearly invisible. The recording and screenshots below show this, and the script below reproduces it.

    I couldn't get the Context section to show here because the simulated model reports no token usage, so it isn't in the recording. Its code (and the Limit and Todo sections') reads props.context.theme once at setup in the same way as MCP, which matches what you describe.

    Related: #40023 reported the same stale sidebar colors on an earlier build and was closed for inactivity without a fix.

    recording.mp4

    Screenshot

    Screenshot

    Reproduction script (drive.ts)
    // Repro for #63305: built-in sidebar plugin sections (here: MCP) keep the old
    // theme colors after switching between light and dark mode.
    import { Effect, Stream } from "effect"
    import { Llm, OpenCodeDriver } from "opencode-drive"
    
    export default OpenCodeDriver.use(
      {
        ...(process.env.OC_DEV ? { opencode: { dev: process.env.OC_DEV } } : {}),
        tui: { recording: true, keypressOverlay: true, viewport: { cols: 160, rows: 40 } },
        // Two MCP servers so the sidebar's MCP section renders (both disabled, so no error toast covers it).
        config: {
          mcp: {
            alpha: { type: "local", command: ["false"], enabled: false },
            beta: { type: "local", command: ["false"], enabled: false },
          },
        } as any,
        tuiConfig: {
          theme: { name: "opencode", mode: "dark" },
          keybinds: { "theme.switch_mode": "f7" },
        },
      },
      ({ ui, llm }) =>
        Effect.gen(function* () {
          yield* llm.serve(() => Stream.make(Llm.text("Hello.")))
          yield* ui.submit("hi")
          yield* ui.waitFor("MCP")
          yield* ui.waitFor("Hello.")
          yield* Effect.sleep(1500)
          yield* ui.screenshot("1-dark")
          // Toggle light/dark (theme.switch_mode bound to F7)
          yield* ui.press("f7")
          yield* Effect.sleep(2000)
          yield* ui.screenshot("2-after-switch-to-light")
          yield* ui.press("f7")
          yield* Effect.sleep(2000)
          yield* ui.screenshot("3-after-switch-back-to-dark")
        }),
    )

    Run it with opencode-drive: opencode-drive run ./drive.ts. It drives opencode from your PATH; set OC_DEV to the path of an OpenCode checkout to run that from source instead.

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions