[BUG] Logo and "Thinking" animation colors are dull/washed-out inside tmux

Status Open
Reported on v2.1.77
Maintainer reply None cached
Activity 10 comments · opened Mar 17, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

When running Claude Code inside tmux, the logo and "Thinking" animation text appear dull/washed-out compared to running Claude Code directly in the terminal. All other colors in tmux work correctly, and Claude Code's own text output (syntax highlighting, markdown, etc.) appears fine - only the branding UI elements (logo, thinking animation) are affected.

What Should Happen?

Logo and "Thinking" animation should have the same vibrant colors inside tmux as when running directly in the terminal.

Error Messages/Logs

Steps to Reproduce

  1. Open iTerm2
  2. Run claude - observe vibrant logo colors
  3. Open tmux inside iTerm2
  4. Run claude - observe dull/muted logo and "Thinking" animation colors

Claude Model

None

Is this a regression?

Yes, this worked in a previous version

Last Working Version

_No response_

Claude Code Version

2.1.77 (Claude Code)

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

iTerm2

Additional Information

Environment

  • Claude Code version: 2.1.77
  • OS: macOS (Darwin 25.3.0, Apple Silicon)
  • Terminal: iTerm2
  • tmux version: 3.6
  • Shell: zsh
  • Theme: dark

tmux config (relevant parts):
set -g default-terminal "tmux-256color"
set -ag terminal-overrides ",xterm-256color:Tc"
set -g mouse on
set -s extended-keys on
set -as terminal-features ',xterm-256color:extkeys'

What I've tried (none of these fixed the issue):

  • Setting COLORTERM=truecolor via set-environment -g COLORTERM truecolor
  • Setting FORCE_COLOR=3 environment variable
  • Adding set -ag terminal-overrides ",tmux-256color:RGB"
  • Setting set -g allow-passthrough all
  • Setting set-environment -g TERM_PROGRAM iTerm.app
  • Setting COLORFGBG="15;0" in shell
  • Changing default-terminal to xterm-256color
  • Setting theme to dark via /theme

Truecolor verification:
Truecolor works correctly inside tmux for all other applications. Running the following produces three distinct, vibrant orange blocks:

printf '\e[38;2;231;111;44m██████ truecolor\e[0m\n'
printf '\e[38;5;208m██████ 256-color\e[0m\n'
printf '\e[38;2;204;102;0m██████ truecolor darker\e[0m\n'

Suspected cause
Claude Code likely performs its own terminal capability detection for UI elements and falls back to a muted color palette when it detects tmux, regardless of actual truecolor support.

View original on GitHub ↗

9 Comments

quza · 5 months ago

<img width="106" height="97" alt="Image" src="https://github.com/user-attachments/assets/b1658c32-31d9-441a-aac5-816ad4d8822e" /> - Claude logo in iTerm2

<img width="105" height="88" alt="Image" src="https://github.com/user-attachments/assets/fc7c6cfe-2dab-4233-87c5-37dd184d80ff" /> - Claude logo in tmux

quza · 5 months ago

accidentally closed issue, the problem still persists

github-actions[bot] · 5 months ago

Found 1 possible duplicate issue:

  1. https://github.com/anthropics/claude-code/issues/32365

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

luan · 5 months ago

I can confirm the same is true on ghostty within tmux, and that this is a regression in 2.1.77, 2.1.76 renders colors correctly.

<img width="2014" height="664" alt="Image" src="https://github.com/user-attachments/assets/4b10fda5-fe86-4788-b64c-5a606070b33a" />

joshukraine · 5 months ago

Confirming this regression in v2.1.77. Tested across multiple terminals and narrowed down the root cause.

Environment

  • Claude Code: 2.1.77
  • macOS (Darwin 25.3.0, Apple Silicon)
  • Terminals tested: Ghostty 1.3.1, Kitty
  • tmux: 3.6a
  • Shell: zsh
  • Truecolor verified working in tmux for all other applications

Key finding: $TMUX env var triggers the desaturation

Running Claude Code with the TMUX variable unset restores correct colors inside tmux:

env -u TMUX claude

The screenshot below shows Claude Code launched with env -u TMUX claude inside tmux — colors are
correct, matching non-tmux rendering.

This confirms Claude Code v2.1.77 checks $TMUX and applies a different (muted) color palette,
regardless of actual terminal color capabilities.

What didn't help

  • FORCE_COLOR=3 claude — no effect
  • TERM_PROGRAM=ghostty claude — no effect
  • COLORTERM=truecolor is set and verified
  • Various terminal-overrides / terminal-features changes in tmux config

Additional data points

  • Issue reproduces in both Ghostty and Kitty — terminal-independent, purely a tmux detection

issue

  • Neovim syntax highlighting renders correctly in the same tmux session — truecolor passthrough is

working

  • Only Claude Code's UI elements (logo, thinking animation, borders) are affected

<img width="1182" height="777" alt="Image" src="https://github.com/user-attachments/assets/80d41376-f1cf-4ba4-b38e-21d60aa954ba" />

Uzinyi · 5 months ago

Found the exact root cause in the bundled cli.js:

function IB3() {
  if (process.env.TMUX && _1.level > 2) return _1.level = 2, true;
  return false;
}

This explicitly downgrades chalk's color level to 2 (256-color) whenever $TMUX is set, regardless of actual terminal capabilities.

ToxMox · 5 months ago

Additional context from psmux (tmux-compatible multiplexer on Windows)

I'm running Claude Code inside psmux, a tmux-compatible terminal multiplexer for PowerShell on Windows. It creates ConPTY with PSEUDOCONSOLE_PASSTHROUGH_MODE and sets COLORTERM=truecolor for child processes. Full 24-bit RGB works correctly for all other applications.

Root cause identified: In the bundled cli.js, the IB3() function unconditionally caps chalk's color level to 2 (256-color) when the TMUX env var is set:

function IB3() {
  if (process.env.TMUX && _1.level > 2)
    return _1.level = 2, true;
  return false;
}

This runs after FORCE_COLOR detection, so even FORCE_COLOR=3 cannot override it. The result is that RGB theme colors get approximated to the nearest 256-color palette entry, which is why some colors look fine (close match exists) while others appear washed out/desaturated.

Suggested fix: Rather than blanket-capping at level 2, check the multiplexer's actual capability — e.g., tmux display -p '#{client_termfeatures}' reports RGB on capable setups, or respect COLORTERM=truecolor even when TMUX is set.

Environment: Windows 11, psmux 3.2.0, TERM=xterm-256color, COLORTERM=truecolor, Claude Code 2.1.78.

mertyatir · 4 months ago

There's an env var that fixes this.

export CLAUDE_CODE_TMUX_TRUECOLOR=1

Add to your shell rc, open a new pane, done.

It's documented at https://code.claude.com/docs/en/env-vars

---

Why it works

The check in the bundled JS already has an opt-out:

function Hj1() {
  if (process.env.CLAUDE_CODE_TMUX_TRUECOLOR) return false;          // ← short-circuit
  if (process.env.TMUX && K_.level > 2) return K_.level = 2, true;   // chalk → 256-color
  return false;
}

Setting the env var returns early before chalk gets capped at level 2, so RGB sequences leave the process unmangled.

---

Version timeline (verified by inspecting old npm tarballs)

| Version | Date | State |
|---|---|---|
| 2.1.76 | 2026-03-14 | No clamp — colors fine |
| 2.1.77 | 2026-03-16 | Clamp added — regression starts |
| 2.1.78–2.1.81 | through 2026-03-20 | Clamp present, no escape hatch |
| 2.1.83 | 2026-03-24 | CLAUDE_CODE_TMUX_TRUECOLOR added |
| docs | 2026-04-15 | Env var finally documented |

huntie · 2 months ago

This bug persists / has freshly manifested specifically in the VS Code integrated terminal.

  • In all cases, I have the CLAUDE_CODE_TMUX_TRUECOLOR override set (fixes tmux, does not fix VS Code).
  • This is a regression, with colours working fine ~1w ago.

Environment (VS Code terminal, outside of tmux)

Claude Code: 2.1.160

TERM=xterm-256color
TERM_PROGRAM=vscode
TERM_PROGRAM_VERSION=1.122.1
COLORTERM=truecolor
FORCE_COLOR=
NO_COLOR=
TMUX=
CLAUDE_CODE_TMUX_TRUECOLOR=1
VSCODE_INJECTION=1

Comparison

Left: Enter tmux then claude (works ✅). Right: claude only (washed out ❌).

<img width="956" height="280" alt="Image" src="https://github.com/user-attachments/assets/0e7c3ba2-2eb2-469f-99de-712b14359004" />

[New] Claude investigation (pasted) ⬇️

I was able to resolve this with a TERM_PROGRAM=generic override for my VS Code (https://github.com/huntie/dotfiles/commit/ef43f42402b4276b0948974aacce303032316cb2).

<details>
<summary><strong>Investigation</strong></summary>

Investigation: dull/washed-out logo + spinner under VS Code's integrated terminal

TL;DR: Not a colour-depth problem. Claude Code detects truecolor correctly and emits 24-bit RGB. The desaturation is triggered by Claude's own vscode/xterm.js render branch — gated on TERM_PROGRAM === "vscode". Removing that one signal (terminal capabilities otherwise unchanged) restores vibrant colours. Same family as #35148, but a different code path from the tmux case.

Environment

  • Claude Code 2.x (inspected the bundled detection logic in @anthropic-ai/claude-code-*@2.1.181; the JS is identical across platform builds).
  • macOS, Apple Silicon. Shell: Fish.
  • Affected: VS Code integrated terminal (xterm.js).
  • Unaffected: Ghostty, and tmux with a truecolor workaround set.

Symptom

Brand orange and the "Thinking" spinner gradient render muted/desaturated. Everything else — syntax highlighting, markdown, ANSI output — is correct. Only the RGB-coloured branding is affected.

What this is NOT (ruled out empirically)

| Hypothesis | Check | Result |
|---|---|---|
| 256-colour quantisation (chalk.level === 2, the salmon-cube bug) | diagnostic prints level: 3, COLORTERM: 'truecolor' | Ruled out — at truecolor |
| boostChalkLevelForXtermJs (256→3) needed but not firing | already level 3 pre-boost | Ruled out — boost irrelevant |
| VS Code terminal.integrated.minimumContrastRatio luminance adjustment | already set to 1; other apps render full-saturation RGB in the same terminal | Ruled out |
| tmux passthrough clamp | inTmux: false | Ruled out |
| Terminal can't do truecolor | truecolor swatch renders vibrant in the same VS Code terminal | Ruled out — emulator is fine |

Diagnostic output from the affected terminal:

{ level: 3, note: 'truecolor', TERM: 'xterm-256color',
  COLORTERM: 'truecolor', TERM_PROGRAM: 'vscode', inTmux: false }

Confirmed trigger

The deciding A/B. With the terminal's colour capabilities held constant (still COLORTERM=truecolor, still xterm.js), only the TERM_PROGRAM signal changes:

# washed-out
claude
 
# vibrant
env -u TERM_PROGRAM claude          # COLORTERM=truecolor already exported by VS Code

So the differentiator is TERM_PROGRAM === "vscode", not anything about reported colour support.

In the bundle this maps to the "am I in xterm.js?" predicate, which several render paths key off:

function D_() {
  if (H_()?.isVscodeTerm) return true;
  if (process.env.TERM_PROGRAM === "vscode") return true;
  return CBr?.startsWith("xterm.js") ?? false;   // XTVERSION probe reply
}

When D_() is true, Claude takes an xterm.js-specific rendering branch that the Ghostty and tmux paths never touch. Unsetting TERM_PROGRAM makes D_() false (the XTVERSION probe does not independently return xterm.js on this setup), and the branding renders at full saturation.

Candidate mechanism (not yet confirmed)

D_() gates more than colour level — in the bundle it also controls glyph-atlas behaviour in the renderer: maybeProactiveAtlasReset, proactiveAtlasResetOnFocus, forceRedraw all emit an atlas/palette reset (OSC 104;255) only when D_(), and there is glyph-cardinality telemetry (tengu_render_glyph_cardinality with stylepool_overflowed / atlas_keys_saturated, is_xtermjs). Leading candidates, in rough order:

  1. Glyph texture-atlas / stylepool colour saturation specific to the xterm.js renderer — the logo/spinner use many distinct RGB shades (a gradient); if the atlas/style cap is hit, colours can degrade.
  2. A dim/faint (SGR 2) styling difference — xterm.js renders faint as a heavier alpha reduction than Ghostty, so the same dim sequence looks far more washed-out here.
  3. Some other styling applied only on the D_() branch.

This can be discriminated by capturing and diffing the raw output streams (not yet run):

script -q /tmp/cc-vscode.raw   claude   # then quit after the spinner shows
script -q /tmp/cc-ghostty.raw  claude   # same, in Ghostty
 
# SGR inventory diff
diff (grep -aoE \e'\[[0-9;:]*m' /tmp/cc-vscode.raw  | sort -u | psub) \
     (grep -aoE \e'\[[0-9;:]*m' /tmp/cc-ghostty.raw | sort -u | psub)
 
# is brand orange wrapped in faint? (38;2;215;119;87 = orange, 2 = faint)
grep -aoE \e'\[2(;[0-9;:]*)?m' /tmp/cc-vscode.raw | sort | uniq -c

A differing SGR inventory points to (1)/(3); orange consistently wrapped with 2; points to (2).

Workaround

Mask the trigger for the VS Code terminal only:

// VS Code settings.json — scoped to the integrated terminal, leaves Ghostty/tmux untouched
"terminal.integrated.env.osx": {
  "TERM_PROGRAM": "generic"   // any non-vscode/ghostty/iTerm.app value Claude has no branch for
}

Tradeoff: this also hides TERM_PROGRAM from Claude's VS Code extension integration (in-editor diff, selection/diagnostic context), since that keys off TERM_PROGRAM === "vscode" too. A per-command Fish wrapper guarded on vscode narrows the blast radius to the claude process if IDE integration matters.

Suggested direction

The terminal advertises and supports truecolor, and Claude emits the correct RGB bytes — proven by the fact that suppressing the D_() branch alone restores them. The xterm.js render branch is muting colours the renderer can display. Worth checking the atlas/stylepool path (candidate 1) and the faint-render assumption (candidate 2) against the stream capture above.
</details>

Showing cached comments. Read the full discussion on GitHub ↗