feat(cli): Apple_Terminal truecolor downgrade to ANSI 256#271
Conversation
Apple Terminal mishandles 24-bit color escape sequences and renders
corrupted output for any theme that emits Color::Rgb. Detect the
terminal at startup and route every theme color through a 6×6×6 cube
+ greyscale ramp quantizer when the active terminal is known to lack
truecolor support.
The Theme palette stays in RGB; only the emit-time conversion changes,
so terminals that handle truecolor are unaffected. Detection considers
NO_COLOR, TERM_PROGRAM=Apple_Terminal, screen/tmux 256color terminfo,
and the COLORTERM=truecolor advertisement. Users can override with
AGENT_CODE_COLOR_MODE={truecolor,ansi256,ansi16}.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8c11b875d5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| let adapt = |c: Color| super::color_emit::adapt(mode, c); | ||
| Theme { | ||
| accent: adapt(theme.accent), |
There was a problem hiding this comment.
Preserve ANSI256 colors when adapting theme for TUI
Adapting every theme slot through color_emit::adapt in current() converts RGB colors to Color::AnsiValue whenever emit mode is Ansi256 (Apple Terminal / tmux-256color path), but the TUI bridge in crates/cli/src/ui/tui.rs (theme_to_ratatui) does not handle AnsiValue and falls through to _ => Color::Reset. This means most themed colors are silently reset in the ratatui view for the exact terminals this change targets, causing a visible regression in tool/status styling. Please either map AnsiValue(n) to ratatui::style::Color::Indexed(n) in the bridge or avoid emitting AnsiValue for TUI consumers.
Useful? React with 👍 / 👎.
Summary
Color::Rgbrenders corrupted output for those users. Add a singlecolor_emitchoke-point that detects the terminal at startup and quantizes RGB to ANSI 256 when needed (or to the 16-color palette whenNO_COLORis set).Themestruct keeps its full RGB palette unchanged; only the emit-time conversion is downgraded, so terminals that speak truecolor are unaffected.theme::current()adapts every slot through the active emit mode so all consumers (TUI, markdown renderer, prompt, syntax highlighting) get the right output without per-callsite changes.AGENT_CODE_COLOR_MODEuser override →NO_COLOR→TERM_PROGRAM=Apple_Terminal→TERM=screen-256color/tmux-256color→COLORTERM=truecolor/24bit→ default to truecolor. New module ships zero new dependencies (crossterm already speaks ANSI 256 viaColor::AnsiValue).Test plan
cargo check --all-targetscargo test --all-targets— all tests pass except 3 pre-existing bwrap-permission failures insandbox_integrationthat also fail on a clean main checkout (unrelated to this change)cargo clippy --all-targets -- -D warningscargo fmt --all -- --check\\x1b[38;2;…m, ansi256\\x1b[38;5;…m, ansi16 named codes for fg + bg)