Skip to content

fix(colors): readable defaults on light terminals via HERMES_THEME + COLORFGBG - #9808

Closed
skyc1e wants to merge 1 commit into
NousResearch:mainfrom
skyc1e:fix/colors-light-terminal
Closed

fix(colors): readable defaults on light terminals via HERMES_THEME + COLORFGBG#9808
skyc1e wants to merge 1 commit into
NousResearch:mainfrom
skyc1e:fix/colors-light-terminal

Conversation

@skyc1e

@skyc1e skyc1e commented Apr 14, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #8526 — on light-theme terminals (reported against macOS Terminal.app's default profile), hermes renders yellow-on-white and dim-on-white text that's effectively unreadable. The reporter's screenshot shows the interactive chat, but the problem applies to every CLI surface (status, doctor, setup menus, cron list, etc.) because they all funnel through hermes_cli/colors.py::color().

Fix

Small, call-site-free theme layer in hermes_cli/colors.py:

  • HERMES_THEME=light|dark — explicit opt-in override.
  • HERMES_THEME=auto (or unset) — conservative background auto-detection via COLORFGBG. Only bg ∈ {7, 15} is treated as light; 0–6, 8 are treated as dark; anything else (including the literal default some terminals emit) falls through and keeps today's behavior, so no one who's currently happy gets new visuals by accident.
  • NO_COLOR is honored first, identical to before — no theme configuration can override it.

In light mode, color() remaps exactly two codes:

Code Light remap Rationale
YELLOW (33) MAGENTA (35) High contrast on white; still reads as "warning-ish"
DIM (2) "" (unset) Terminal's default foreground is already readable on a light background

Red, green, cyan, blue, magenta, and bold are untouched so existing semantic meaning (error = red, ok = green, info = cyan) is preserved.

Scope is intentionally narrow:

  • One file for the behavior change (hermes_cli/colors.py, ~70 lines added) plus tests/hermes_cli/test_colors.py.
  • No call-site rewrites. Every existing color(text, Colors.YELLOW) / Colors.DIM usage (~200 across 14 modules) picks up the new behavior automatically.
  • No new dependencies.
  • No Rich/UI theming — out of scope; those live outside this helper.

Test plan

New tests/hermes_cli/test_colors.py covers:

  • NO_COLOR still wins over any theme configuration (including HERMES_THEME=light).
  • HERMES_THEME=light|dark takes priority over COLORFGBG; case-insensitive, tolerates surrounding whitespace.
  • HERMES_THEME=auto (and unset) fall through to COLORFGBG detection.
  • COLORFGBG parsing: uses the trailing segment; handles 2- and 3-segment forms (rxvt uses fg;?;bg); default segment returns None.
  • Light mode remaps YELLOW → MAGENTA and drops DIM; dark mode and the default (no-env) path preserve both.
  • Light mode leaves red/green/blue/cyan/magenta/bold untouched.
  • Combined codes (e.g. BOLD + YELLOW) remap only the yellow.
  • I wasn't able to run the full pytest suite locally from this sandbox (no usable Python available), so the tests above are my best-effort; happy to iterate if CI catches anything.

Notes

  • Reporter opted in to submit a PR themselves; posting this so they can see it early, but happy to defer if they'd prefer to take it.
  • No public API or signature changes.
  • If maintainers would prefer a different light-mode swap for YELLOW (e.g. BLUE instead of MAGENTA), that's a one-line change in _LIGHT_REMAP.

…COLORFGBG

When hermes runs in a light-theme terminal (e.g. the default macOS
Terminal.app profile), yellow text renders near-invisible against white
and dim text loses nearly all contrast. Issue NousResearch#8526 reports this for
the interactive chat, but it applies to every CLI surface that routes
through `hermes_cli.colors.color()` — status, doctor, setup menus, etc.

Introduce a small, call-site-free theme layer in `hermes_cli/colors.py`:

* `HERMES_THEME=light|dark` is an explicit override.
* `HERMES_THEME=auto` (or unset) falls back to COLORFGBG-based
  background detection. The heuristic is conservative: bg indices
  7 and 15 → light; 0-6 and 8 → dark; anything else (including the
  literal "default") falls through and we keep today's behavior.
* `NO_COLOR` still wins over every code path — honored first, exactly
  as before.

In light mode, `color()` remaps:

* YELLOW → MAGENTA (readable on white; still reads as "warning-ish")
* DIM → "" (the terminal's default foreground is already readable on
  a light background)

Red, green, cyan, blue, magenta, and bold are left untouched so the
existing semantic meaning (error=red, ok=green, info=cyan) is
preserved. No call sites change; no new dependencies; Rich/UI theming
is out of scope.

Closes NousResearch#8526
@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/cli CLI entry point, hermes_cli/, setup wizard labels Apr 26, 2026
@teknium1

Copy link
Copy Markdown
Contributor

Closing as superseded by #17113.

Triage notes (medium confidence):
Merged PRs #13103, #17113, #17695, #26137 already implement light-terminal auto-detection via COLORFGBG/HERMES_TUI_THEME in cli.py and tui; #17113 in particular delivered the auto-detect feature this PR proposes for hermes_cli/colors.py.

Thanks for the contribution — the underlying problem this PR addresses has been resolved by the linked PR on current main. If you believe this was closed in error, please comment and we'll reopen.

(Bulk-closed during a CLI PR triage sweep.)

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

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard P3 Low — cosmetic, nice to have type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: [color] default color is broken, when launching hermes via terminal, not being readable

3 participants