Skip to content

feat(cli): make terminal theme detection skin-aware and readable in light mode#1187

Closed
peteromallet wants to merge 2 commits intoNousResearch:mainfrom
peteromallet:feat/theme-mode-cleanup
Closed

feat(cli): make terminal theme detection skin-aware and readable in light mode#1187
peteromallet wants to merge 2 commits intoNousResearch:mainfrom
peteromallet:feat/theme-mode-cleanup

Conversation

@peteromallet
Copy link
Contributor

@peteromallet peteromallet commented Mar 13, 2026

What does this PR do?

When I opened Hermes for the first time in a light terminal, a bunch of the CLI was still too light to read cleanly — not just the prompt/input area, but also banner/system text and other UI surfaces.

This makes the CLI theme handling more cohesive end-to-end:

  • detect whether the terminal is light or dark
  • choose defaults that stay readable across the whole interface
  • keep the look aligned with the existing skin/design system instead of just forcing everything to black
  • still let users override the result if they want

Related Issue

Fixes #

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 🔒 Security fix
  • 📝 Documentation update
  • ✅ Tests (adding or improving test coverage)
  • ♻️ Refactor (no behavior change)
  • 🎯 New skill (bundled or hub)

Changes Made

  • extend the existing skin system instead of bypassing it: theme handling now sits on top of skins rather than introducing a separate one-off light-mode path
  • add display.theme_mode with auto | light | dark
  • auto-detect terminal background using OSC 11, with COLORFGBG and macOS appearance fallbacks when needed
  • make theme mode fully skin-aware so colors come from the active skin instead of scattered hardcoded values
  • add/darken colors_light values across built-in skins so light-mode contrast stays readable without losing the Hermes look
  • update banner/system text rendering so the large logo, caduceus, status line, session labels, and related UI all follow the active skin/theme
  • stop hardcoding pale input/body text so prompt_toolkit can use terminal defaults where that is safer
  • make completion menu and other prompt_toolkit surfaces theme-aware in light/dark mode
  • move config writes to the canonical config helper so skin/theme settings are saved in one consistent place
  • update setup flow and cli-config.yaml.example to document the new display setting and light-mode overrides
  • add tests covering theme mode resolution, auto-detection fallbacks, and light-mode skin overrides

How to Test

  1. Start Hermes in a light terminal background and confirm the prompt/input text, banner text, session/status text, and menu surfaces are all readable on first launch.
  2. Run /skin theme auto, /skin theme light, and /skin theme dark and confirm the selected mode is reflected correctly.
  3. Switch between built-in skins and confirm the colors remain readable in both light and dark terminals.
  4. Confirm user overrides still win by setting display.theme_mode in config.

Screenshots / Logs

Before / after on Desktop:

Hermes CLI before and after light-mode theming

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: macOS with a light terminal theme

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — or N/A
  • I've updated cli-config.yaml.example if I added/changed config keys — or N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — or N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — or N/A
  • I've updated tool descriptions/schemas if I changed tool behavior — or N/A

Targeted tests related to this change passed:

  • python3 -m pytest tests/hermes_cli/test_skin_engine.py tests/hermes_cli/test_config.py tests/hermes_cli/test_setup.py tests/hermes_cli/test_set_config_value.py tests/test_cli_init.py tests/test_cli_loading_indicator.py tests/test_cli_model_command.py tests/test_cli_secret_capture.py -q
  • result: 103 passed

I also ran the full suite with python3 -m pytest tests/ -q.
It still does not go fully green in this local environment because 3 existing failures remain outside this change set:

  • tests/test_cli_provider_resolution.py::test_codex_provider_uses_config_model
  • tests/test_quick_commands.py::TestCLIQuickCommands::test_exec_command_runs_and_prints_output
  • tests/test_quick_commands.py::TestCLIQuickCommands::test_quick_command_takes_priority_over_skill_commands

I verified those same 3 failures reproduce on a clean origin/main worktree as well, and this branch does not touch the failing code paths, so they appear to be pre-existing and unrelated to this PR.

Let me know if you have any issues with the approach or want me to tighten up any of the theme defaults.

…ites

Add light/dark theme support with automatic terminal background detection
via OSC 11. Move save_config_value() to hermes_cli/config.py as the single
source of truth, replacing the raw yaml hack in skin_engine. Add public
get_theme_mode_setting() getter to avoid poking at private module state.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@peteromallet peteromallet changed the title feat(cli): auto-detect terminal theme for readable defaults feat(cli): make terminal theme detection skin-aware and readable in light mode Mar 13, 2026
@peteromallet peteromallet reopened this Mar 13, 2026
Remove hardcoded colors from cli.py and banner.py in favor of skin-aware
lookups. Convert banner ASCII art from module-level constants to dynamic
functions that read skin colors at call time. Remove stale detected_background
config caching that defeated auto-detection. Add COLORFGBG and macOS
appearance fallbacks for terminal background detection. Darken colors_light
values across all skins for proper contrast on light backgrounds. Make
input-area and completion menu styles theme-aware.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@peteromallet peteromallet force-pushed the feat/theme-mode-cleanup branch from b00735c to d3ad2e1 Compare March 13, 2026 17:49
teknium1 added a commit that referenced this pull request Mar 17, 2026
Add display.theme_mode setting (auto/light/dark) that makes the CLI
readable on light terminal backgrounds.

- Auto-detect terminal background via COLORFGBG, OSC 11, and macOS
  appearance (fallback chain in hermes_cli/colors.py)
- Add colors_light overrides to all 7 built-in skins with dark/readable
  colors for light backgrounds
- SkinConfig.get_color() now returns light overrides when theme is light
- get_prompt_toolkit_style_overrides() uses light bg colors for
  completion menus in light mode
- init_skin_from_config() reads display.theme_mode from config
- 7 new tests covering theme mode resolution, detection fallbacks,
  and light-mode skin overrides

Salvaged from PR #1187 by @peteromallet. Core design preserved;
adapted to current main (kept all existing helpers, tool_emojis,
convenience functions that were added after the PR branched).

Co-authored-by: Peter O'Mallet <peteromallet@users.noreply.github.com>
@teknium1
Copy link
Contributor

Salvaged onto current main — the core design is preserved, adapted to the current codebase (600 commits of drift). Your commit is co-authored.

What landed:

  • display.theme_mode setting (auto/light/dark) in config
  • Auto-detection via COLORFGBG → OSC 11 → macOS appearance fallback chain
  • colors_light overrides on all 7 built-in skins
  • SkinConfig.get_color() returns light overrides when theme is light
  • get_prompt_toolkit_style_overrides() uses light bg colors for completion menus
  • 7 new tests

Adapted for current main: kept all convenience helpers (get_active_prompt_symbol, get_active_goodbye, etc.), tool_emojis, and get_prompt_toolkit_style_overrides() that were added after your branch point. Thanks @peteromallet — great feature.

@teknium1 teknium1 closed this Mar 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants