anomalyco / anomalyco/opencode

tui: theme token rename in 2.0.9 silently breaks plugin text colors

Open
#49,922 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
209k
Forks
27.5k
PR merge metrics
PR metrics pending

Description

Summary

OpenCode 2.0.9 renamed the resolved text theme tokens (text.subduedtext.muted, text.feedback.<kind>.defaulttext.feedback.<kind>.base) without keeping aliases. TUI plugins that look up the old names get undefined, and their text falls back to the terminal's default foreground — every plugin-rendered cell (e.g. footer statusline segments) loses its muted/info/error colors on 2.0.9.

Environment

  • opencode version: 2.0.9
  • OS: Linux 6.18.33.2-microsoft-standard-WSL2 (linux x64)
  • Terminal: TERM_PROGRAM=vscode, TERM=xterm-256color, COLORTERM=truecolor
  • Shell: /usr/bin/zsh
  • Install/channel: latest (global bun install)
  • Active plugins: none needed for the reproduction below

Reproduction

Minimal probe plugin, no credentials or session required.

~/.config/opencode/plugins/token-probe/index.ts:

import { Plugin } from "@opencode/plugin"

export default Plugin.define({ id: "token-probe", setup() {} })

~/.config/opencode/plugins/token-probe/tui.tsx:

/** @jsxImportSource @opentui/solid */
import { Plugin, usePlugin } from "@opencode/plugin/tui"

function Probe() {
  const ctx = usePlugin()
  return (
    <box flexDirection="row">
      <text fg={ctx.theme.text.subdued}>subdued </text>
      <text fg={ctx.theme.text.muted}>muted</text>
    </box>
  )
}

export default Plugin.define({
  id: "token-probe.tui",
  setup(context) {
    const unregister = context.ui.slot({ append: "prompt.footer.status", render: () => <Probe /> })
    return () => unregister()
  },
})
  1. Open opencode in a terminal.
  2. Capture the footer with ANSI, e.g. tmux capture-pane -e on the pane.

Expected Behavior

Both cells render with theme colors (both tokens should resolve to the same muted color), or the rename is surfaced as a breaking plugin API change.

Actual Behavior

On 2.0.9 only the new name resolves; the old name is undefined and fg={undefined} renders the terminal default color:

subdued ^[[38;2;255;255;255mmuted^[[38;2;128;128;128m
   ^ white (no token)      ^ theme muted

ctx.theme.text.muted / ctx.theme.text.feedback.error.base exist, text.subdued / feedback.error.default do not. Comparing the published packages confirms the rename: @opencode/theme@2.0.8 defines text.default / text.subdued and feedback.*.default; 2.0.9 defines text.base / text.muted and feedback.*.base.

Same effect with a real published plugin (opencode-go-statusline@0.3.1, tmux capture-pane -e):

  • 2.0.8: Weekly 74% emitted as \x1b[38;2;86;182;194m (info color)
  • 2.0.9: the same segment emitted as \x1b[38;2;255;255;255m

Additional Context

  • Broke three independently published plugins the same way (OpenCode Go, GitHub Copilot, and Kimi For Coding statuslines); all are read-only consumers of ctx.theme.
  • Downstream compatibility fix that reads both names, with live before/after captures: lnwu/opencode-statusline-plugins#50 — repo: https://github.com/lnwu/opencode-statusline-plugins
  • Suggestion: keep subdued / default as aliases in the resolved theme, or document the rename as a breaking change.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the published @opencode/theme token definitions and the TUI plugin ctx.theme lookup, then run the minimal token-probe reproduction from the issue. Done means the old token names resolve compatibly as aliases, or the rename is explicitly surfaced and documented as a breaking plugin API change.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
api, cli
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.