Skip to content

getTerminalBackgroundColor() always returns "dark" due to double color normalization #22615

Closed

Description

@lucoffe

getTerminalBackgroundColor() always returns "dark" due to double color normalization

Affected versions

v1.4.4 through v1.4.6 (introduced by #22297)

Description

The refactoring in #22297 moved getTerminalBackgroundColor() from an inline function in app.tsx to Terminal.getTerminalBackgroundColor() in terminal.ts. The new implementation uses RGBA.fromInts() to parse the terminal's background color, but the mode() helper still divides by 255 — a leftover from the old code where r, g, b were raw 0–255 integers.

RGBA.fromInts() already normalizes to the 0.0–1.0 range internally:

// @opentui/core RGBA.ts
static fromInts(r: number, g: number, b: number, a: number = 255) {
    return new RGBA(new Float32Array([r / 255, g / 255, b / 255, a / 255]))
}

But mode() divides by 255 again:

// packages/opencode/src/cli/cmd/tui/util/terminal.ts
function mode(bg: RGBA | null): "dark" | "light" {
    if (!bg) return "dark"
    const luminance = (0.299 * bg.r + 0.587 * bg.g + 0.114 * bg.b) / 255
    //                                                               ^^^
    return luminance > 0.5 ? "light" : "dark"
}

The maximum possible luminance (for pure white #ffffff) is 1.0 / 255 ≈ 0.004, which can never exceed 0.5. The function returns "dark" for every terminal background color.

Impact

Any theme with dark/light variants (gruvbox, catppuccin, nord, etc.) always selects the dark palette, even on a light terminal. The system theme is unaffected because it works directly with raw RGBA values and never calls mode().

Steps to reproduce

  1. Use a terminal with a light background
  2. Set theme to gruvbox (or any theme with light/dark variants)
  3. Run opencode on v1.4.4+
  4. Observe the dark variant is selected instead of light

Fix

Remove the / 255 from the luminance calculation in mode():

function mode(bg: RGBA | null): "dark" | "light" {
    if (!bg) return "dark"
    const luminance = 0.299 * bg.r + 0.587 * bg.g + 0.114 * bg.b
    return luminance > 0.5 ? "light" : "dark"
}

Activity

  1. added
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    on Apr 15, 2026
  2. lucoffe commented on Apr 15, 2026

    @lucoffe
    Author

    Related: #20926 — the inverse of this bug. In v1.3.13 the detection was stuck on light; #22297 refactored the detection logic to fix that, but introduced the double-normalization which now makes it stuck on dark.

  3. added a commit that references this issue on Apr 15, 2026
    3ca83ed
  4. flybayer commented on Apr 17, 2026

    @flybayer

    i could downgrade to 1.4.3 to get around this, but now i have this problem even on those older versions

  5. lucoffe commented on Apr 17, 2026

    @lucoffe
    Author

    You can still clone and cherry-pick this. But gosh this is annoying, hopefully it'll get fixed soon in a release

  6. lucoffe commented on Apr 21, 2026

    @lucoffe
    Author

    Closing this: the code this PR fixes was removed in v1.14.19 by #23188, which replaced the custom getTerminalBackgroundColor() / mode() helper with renderer.waitForThemeMode() from @opentui/core. The double normalization bug no longer exists because the entire code path was deleted, not because someone fixed the / 255. Note that the new detection approach has its own set of issues for some users (see #20926), but that's a different problem.

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

Metadata

Metadata

Assignees

Labels

coreAnything pertaining to core functionality of the application (opencode server stuff)

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions