statusLine renders 24-bit ANSI colors quantized to 256-color palette when running inside tmux, even though the terminal and tmux both support truecolor

Status Open
Reported on v2.1.220
Maintainer reply None cached
Activity 0 comments · opened Jul 27, 2026

Environment

  • Claude Code version: 2.1.220
  • OS: Arch Linux, kernel 7.0.12-arch1-1
  • Terminal: kitty 0.48.0
  • Multiplexer: tmux 3.7b
  • TERM inside tmux pane: tmux-256color
  • COLORTERM inside tmux pane: truecolor (confirmed present, not stripped)
  • tmux config: default-terminal "tmux-256color", terminal-overrides ',*:RGB'
  • tmux info / client_termfeatures for the attached kitty client explicitly list RGB as a negotiated feature

Summary

A custom statusLine command that emits raw 24-bit ANSI truecolor escape codes (e.g. \033[38;2;214;93;14m) renders with pixel-perfect accurate colors when Claude Code is run directly in kitty, but renders visibly washed-out/desaturated colors when the identical session is run inside a tmux pane. The colors are not merely "duller" — they land exactly on the standard xterm 256-color 6×6×6 cube grid (channel values restricted to 0/95/135/175/215/255), which is the unmistakable signature of 24-bit RGB being quantized down to an indexed 256-color palette.

Reproduction

  1. Configure a statusLine command (~/.claude/settings.json) that outputs raw \033[38;2;r;g;bm / \033[48;2;r;g;bm truecolor escape sequences.
  2. Run claude directly in kitty. Screenshot the statusline.
  3. Run claude inside a tmux pane (same kitty window, same tmux config as above). Screenshot the statusline.
  4. Compare pixel colors between the two screenshots.

Evidence

Sampled pixel RGB values from screenshots of the same statusline segments:

| Segment | Configured truecolor value | Rendered outside tmux | Rendered inside tmux (via Claude Code) |
|---|---|---|---|
| orange | (214, 93, 14) | (214, 93, 14) ✅ | (215, 135, 0) ❌ |
| yellow | (215, 153, 33) | (215, 153, 33) ✅ | (215, 175, 95) ❌ |
| aqua/teal | (104, 157, 106) / (69, 133, 136) | exact match ✅ | (135, 175, 135) / (95, 175, 175) ❌ |
| gray | (102, 92, 84) / (60, 56, 54) | exact match ✅ | (135, 135, 135) / (95, 95, 95) ❌ |

Every "inside tmux" value falls exactly on the xterm 256-color cube's fixed channel levels (0, 95, 135, 175, 215, 255) — not just close to it, but exact.

Isolating the cause: it's not tmux or kitty

To rule out tmux/kitty as the culprit, the same raw ANSI codes were tested by bypassing Claude Code entirely, typed directly into the same live tmux pane:

  • printf '\033[48;2;214;93;14m \033[0m' run directly in the tmux shell → rendered pixel-perfect (214, 93, 14).
  • The exact statusLine script's raw stdout (bash statusline.sh) run directly in the tmux shell (not via Claude Code) → rendered pixel-perfect truecolor for every segment.

This proves tmux and kitty both correctly pass through and render 24-bit color end-to-end, including inside this exact pane, with this exact config. The quantization only occurs when Claude Code itself renders the statusLine command's output.

Expected behavior

Claude Code should either:

  • Pass the statusLine command's raw stdout through unmodified (it's already valid ANSI), or
  • If it does its own capability detection, correctly honor COLORTERM=truecolor rather than assuming 256-color support from TERM=tmux-256color alone.

Actual behavior

Claude Code appears to detect terminal color capability (likely via TERM) and downsamples/quantizes the statusLine's ANSI truecolor codes to a 256-color-safe palette when it believes it's inside a "256color" terminal — even when COLORTERM=truecolor is correctly set and the terminal/multiplexer chain has been independently verified to support and correctly render true 24-bit color.

Additional notes

  • The statusline.md docs only say "use ANSI escape codes... terminal must support them" with no detail on capability detection or COLORTERM handling.
  • Happy to provide the full statusline script and settings.json, plus the original screenshots and pixel-sampling scripts used to produce the table above, on request.

View original on GitHub ↗