Skip to content

[Bug]: Zed dark themes: /skin default is rendered as light-mode colors because Hermes trusts inherited COLORFGBG #61536

Description

@willvieira

Bug Description

Duplicate search performed:

repo:NousResearch/hermes-agent Zed COLORFGBG => 0 exact matches
repo:NousResearch/hermes-agent ZED_TERM => no matching bug; unrelated #14907
repo:NousResearch/hermes-agent "COLORFGBG=0;15" => related closed PRs #49096, #16835, #13103
repo:NousResearch/hermes-agent "light mode" "COLORFGBG" => related #49082, #49097, #50350, #47210, #60990

Closest related work is general terminal light/dark detection and Apple Terminal / Ghostty behavior. I did not find an exact Zed + inherited COLORFGBG + default skin remapping issue.

Bug Description

When Hermes runs inside Zed's integrated terminal using a dark Zed theme, the default skin can render with light-mode remapped colors even though the terminal background is dark.

The problem is not the default skin palette itself. Hermes' light/dark detector trusts COLORFGBG=0;15 as a light-background signal. In Zed, that value can be inherited from the terminal/shell environment that launched Zed, rather than reflecting Zed's actual integrated terminal theme.

Observed Zed child environment:

TERM_PROGRAM=zed
ZED_TERM=true
COLORFGBG=0;15
COLORTERM=truecolor

With that environment, Hermes detects light mode and remaps default skin colors:

detect_light_mode=True
#FFF8DC -> #1A1A1A
#FFD700 -> #9A6B00

On Zed dark themes this produces light-mode colors on a dark editor terminal, making the skin look wrong or low contrast.

This does not appear to be specific to One Dark. Additional detector-level checks show the problem follows the inherited Zed terminal environment, not the selected dark theme:

Zed dark-theme matrix, inherited COLORFGBG=0;15, pre-guard behavior
One Dark: old_detector_light=True
Ayu Dark: old_detector_light=True
Catppuccin Macchiato: old_detector_light=True
Dracula: old_detector_light=True
Gruvbox Dark: old_detector_light=True
Solarized Dark: old_detector_light=True

The same theme matrix against the proposed Zed guard keeps all of those cases dark and preserves the original default skin colors:

Zed dark-theme matrix, inherited COLORFGBG only
One Dark: detect_light_mode=False #FFF8DC->#FFF8DC #FFD700->#FFD700
Ayu Dark: detect_light_mode=False #FFF8DC->#FFF8DC #FFD700->#FFD700
Catppuccin Macchiato: detect_light_mode=False #FFF8DC->#FFF8DC #FFD700->#FFD700
Dracula: detect_light_mode=False #FFF8DC->#FFF8DC #FFD700->#FFD700
Gruvbox Dark: detect_light_mode=False #FFF8DC->#FFF8DC #FFD700->#FFD700
Solarized Dark: detect_light_mode=False #FFF8DC->#FFF8DC #FFD700->#FFD700

Control check: the same COLORFGBG=0;15 without Zed markers still detects light, so this is specifically about Zed's inherited/unreliable COLORFGBG, not about removing COLORFGBG support globally:

plain terminal env: detect_light_mode=True #FFF8DC->#1A1A1A #FFD700->#9A6B00

Environment

  • OS: macOS
  • Hermes commit tested: 8e734810d on main
  • Hermes version: Hermes Agent v0.18.2 (2026.7.7.2) · upstream 8e734810
  • Python: Hermes runtime Python 3.11.15
  • Editor: Zed 1.10.0+stable.318.111c4082fd38215c31fa87803ece7695f898a94e
  • Zed theme: reproduced conceptually across multiple dark themes; originally observed with One Dark
  • Shell: zsh
  • Terminal env observed in Hermes/Zed child process:
TERM_PROGRAM=zed
ZED_TERM=true
TERM=xterm-256color
COLORFGBG=0;15
COLORTERM=truecolor

Related Issues / PRs

No exact issue was found for Zed + inherited COLORFGBG + skin remapping.

Related light/dark detection work:

Steps to Reproduce

  1. Launch Zed from a shell/session whose environment includes COLORFGBG=0;15.
  2. Use a dark Zed theme, such as One Dark, Ayu Dark, Catppuccin Macchiato, Dracula, Gruvbox Dark, or Solarized Dark.
  3. Open Zed's integrated terminal.
  4. Run Hermes in the integrated terminal.
  5. Set the default skin:
/skin default
  1. Observe that Hermes applies light-mode remapped colors even though the Zed terminal theme is dark.

A minimal detector repro from the Hermes repo:

TERM_PROGRAM=zed ZED_TERM=true COLORFGBG='0;15' HERMES_TUI_THEME= HERMES_TUI_BACKGROUND= \
  python - <<'PY'
import os
import cli
cli._LIGHT_MODE_CACHE = None
print(cli._detect_light_mode())
print(cli._maybe_remap_for_light_mode('#FFF8DC'))
print(cli._maybe_remap_for_light_mode('#FFD700'))
PY

Current upstream output without the proposed Zed guard:

True
#1A1A1A
#9A6B00

Expected Behavior

Hermes should not infer a light background from inherited COLORFGBG inside Zed's integrated terminal.

For Zed:

  • explicit user overrides should still win:
    • HERMES_LIGHT
    • HERMES_TUI_LIGHT
    • HERMES_TUI_THEME
    • HERMES_TUI_BACKGROUND
  • inherited COLORFGBG should be ignored or treated as unreliable when TERM_PROGRAM=zed or ZED_TERM=true
  • if no explicit signal is present, Hermes should fall through to the next detection path or default dark

Expected minimal repro output:

False
#FFF8DC
#FFD700

Actual Behavior

Hermes treats COLORFGBG=0;15 as authoritative even when running in Zed, detects a light terminal, and remaps dark-theme skin colors for light backgrounds.

Relevant code:

  • cli.py::_detect_light_mode() trusts COLORFGBG before fallback/default-dark behavior
  • cli.py::_maybe_remap_for_light_mode() then remaps default skin colors through _LIGHT_MODE_REMAP
  • ui-tui/src/theme.ts::detectLightMode() has the same COLORFGBG trust rule for the TypeScript TUI path

Affected Component

CLI (interactive chat)

Messaging Platform (if gateway-related)

N/A (CLI only)

Debug Report

NA

Operating System

macOS 26.5.1

Python Version

3.11.15

Hermes Version

0.18.2

Additional Logs / Traceback (optional)

Root Cause Analysis (optional)

No response

Proposed Fix (optional)

Add a small Zed guard to the light/dark detection logic.

Python CLI direction:

def _is_zed_terminal() -> bool:
    return (
        (os.environ.get("TERM_PROGRAM") or "").strip().lower() == "zed"
        or (os.environ.get("ZED_TERM") or "").strip().lower() in {"1", "true", "yes", "on"}
    )

Then in _detect_light_mode(), keep explicit overrides first, but skip the COLORFGBG branch when _is_zed_terminal() is true:

cfgbg = (os.environ.get("COLORFGBG") or "").strip()
if cfgbg and not _is_zed_terminal():
    ...

Mirror the same behavior in ui-tui/src/theme.ts::detectLightMode().

Local validation of the proposed guard:

uv run pytest tests/cli/test_cli_light_mode.py -q -o 'addopts='
23 passed in 0.34s

npm test -- src/__tests__/theme.test.ts
31 passed in 126ms

Suggested regression tests:

Python:

  • tests/cli/test_cli_light_mode.py
  • TERM_PROGRAM=zed, COLORFGBG=0;15 => dark
  • ZED_TERM=true, COLORFGBG=0;15 => dark
  • ZED_TERM=true, COLORFGBG=0;15, HERMES_TUI_THEME=light => light
  • ZED_TERM=true, COLORFGBG=0;15, HERMES_TUI_BACKGROUND=#ffffff => light

TypeScript:

  • ui-tui/src/__tests__/theme.test.ts
  • same cases for detectLightMode()

Workaround

Set an explicit theme override in Zed terminals:

if [[ -n "$ZED_TERM" || "$TERM_PROGRAM" == "zed" ]]; then
  export HERMES_TUI_THEME="${HERMES_TUI_THEME:-dark}"
fi

This works locally but should not be necessary once Hermes treats Zed's inherited COLORFGBG as unreliable.

Are you willing to submit a PR for this?

  • I'd like to fix this myself and submit a PR

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Low — cosmetic, nice to havebugcomp/tuiTerminal UI (ui-tui/ + tui_gateway/)type/bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions