Skip to content

feat(cli): Apple_Terminal truecolor downgrade to ANSI 256#271

Merged
emal-avala merged 1 commit into
mainfrom
feat/apple-terminal-color-downgrade
May 4, 2026
Merged

feat(cli): Apple_Terminal truecolor downgrade to ANSI 256#271
emal-avala merged 1 commit into
mainfrom
feat/apple-terminal-color-downgrade

Conversation

@emal-avala
Copy link
Copy Markdown
Member

Summary

  • Apple Terminal mishandles 24-bit color escape sequences; today every theme that emits Color::Rgb renders corrupted output for those users. Add a single color_emit choke-point that detects the terminal at startup and quantizes RGB to ANSI 256 when needed (or to the 16-color palette when NO_COLOR is set).
  • The Theme struct 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.
  • Detection chain: AGENT_CODE_COLOR_MODE user override → NO_COLORTERM_PROGRAM=Apple_TerminalTERM=screen-256color/tmux-256colorCOLORTERM=truecolor/24bit → default to truecolor. New module ships zero new dependencies (crossterm already speaks ANSI 256 via Color::AnsiValue).

Test plan

  • cargo check --all-targets
  • cargo test --all-targets — all tests pass except 3 pre-existing bwrap-permission failures in sandbox_integration that also fail on a clean main checkout (unrelated to this change)
  • cargo clippy --all-targets -- -D warnings
  • cargo fmt --all -- --check
  • 24 new unit tests covering the quantizer (black → 16, white → 231, mid-grey → ramp, pure red → 196, pure blue → 21, asymmetric near-grey → cube), the detector (Apple Terminal, NO_COLOR overrides, explicit override beats both, screen/tmux-256color, COLORTERM truecolor/24bit), and the SGR formatter (truecolor \\x1b[38;2;…m, ansi256 \\x1b[38;5;…m, ansi16 named codes for fg + bg)
  • Smoke-test on real Apple Terminal during release QA (per roadmap §8.15.2 acceptance criterion)

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}.
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment on lines +165 to +167
let adapt = |c: Color| super::color_emit::adapt(mode, c);
Theme {
accent: adapt(theme.accent),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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 👍 / 👎.

@emal-avala emal-avala merged commit efb3d6b into main May 4, 2026
14 checks passed
@emal-avala emal-avala deleted the feat/apple-terminal-color-downgrade branch May 4, 2026 22:44
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.

1 participant