TUI: follow the active Omarchy theme with a live accent overlay

Merged
JE
2mo ago
+1045-37

First of a three-PR stack (this → setup+bar → toasts), split so each piece reviews and merges on its own. The full design record lands with the setup PR as docs/omarchy.md.

What

The TUI already adapts to terminal retints because it styles with ANSI-16. This lays an accent overlay on top, read from the active Omarchy theme (~/.local/state/omarchy/current/theme/ — a rendered hey.toml if the theme provides one, colors.toml otherwise; HEY_THEME= points anywhere; NO_COLOR opts out), and restyles live after omarchy theme set via an fsnotify watch. The watch sits on current/'s parent because omarchy-theme-set swaps the whole theme/ directory with an atomic mv — a watch inside it would die with the old inode.

Two keys are gated by measurement rather than trusted blindly, because a theme's accent is a UI tint that does not always work as a text highlight:

  • accent is used only when it is visibly distinct from the emphasis foreground (kanagawa's accent is its foreground) and at least as readable on the background as the theme's bright blue (osaka-jade's jade is dimmer than its mint). Otherwise the cursor row keeps ANSI bright blue — the theme's own, since that is what the terminal's ANSI 12 already renders.
  • selection tints the cursor row only when the chosen accent reads on it at ≥ 4.5:1; rose-pine and miasma get an untinted accent row rather than mud.

When the accent is rejected the fallback is plain ANSI bright blue, not the theme's hex, so the highlight always matches the palette the surrounding text renders in. That matters in foot: a running foot window keeps the ANSI palette it opened with until a new window opens. Judge a theme in a fresh window.

Trust boundary (from review): a file the user points at explicitly via HEY_THEME is trusted as written and bypasses both gates; files derived from the Omarchy state dir stay gated, because post-render the TUI cannot tell a hand-written value from a machine-derived one. On a live switch to a mode-less theme the terminal is re-queried for its background rather than assuming the previous mode.

Verified live across theme switches (tokyo-night, kanagawa, osaka-jade, rose-pine, miasma measurements set the two gates above). Cached viewports are re-rendered rather than recolored because Kitty inline-image placeholders encode image IDs as foreground colors.