[BUG] TUI renders garbled inside tmux since 2.1.200 (last-good 2.1.199) — only repaints on forced redraw

Status Open
Reported on v2.1.201
Maintainer reply None cached
Activity 9 comments · opened Jul 4, 2026

Summary

Since v2.1.200, the Claude Code TUI renders garbled inside tmux — text is
corrupted/overwritten and does not repaint on its own. It only redraws correctly
when a forced full redraw happens (switching tmux panes, or resizing). This is a
clean regression: v2.1.199 renders correctly; v2.1.200 and v2.1.201 do not, same
terminal, same tmux, same config.

Correction (updated): this report originally pinned the regression to 2.1.201 with 2.1.200 as last-good. Further bisection proved that wrong — 2.1.200 is also garbled. The real last-good build is 2.1.199. The regression landed in 2.1.200 and persists in 2.1.201. Title/table/workaround below have been corrected accordingly.

Regression bisection

| Version | Result |
|---|---|
| 2.1.199 | ✅ renders correctly in tmux |
| 2.1.200 | ❌ garbled until a forced redraw (pane switch / resize) |
| 2.1.201 | ❌ garbled (same behavior; inherited from 2.1.200) |

Nothing else changed across these builds — tmux, terminfo, and the terminal emulator
were identical. Rolling the native-install symlink back to 2.1.199 restores
correct rendering; 2.1.200 reproduces the corruption, confirming the regression
first landed in the 2.1.200 build.

Environment

  • Claude Code 2.1.200 / 2.1.201 (native installer, macOS arm64) — both regressed;

2.1.199 OK

  • tmux 3.7a (unchanged across good/bad builds)
  • iTerm2 3.6.11
  • TERM=tmux-256color, COLORTERM=truecolor, tmux client reports RGB + sync

(synchronized-output / mode 2026) features

  • macOS (Darwin 25.5.0)

Steps to reproduce

  1. Run Claude Code v2.1.200 (or 2.1.201) inside a tmux pane (iTerm2 outer, tmux-256color).
  2. Interact so the TUI repaints (type, let output stream, scroll).
  3. Text becomes garbled / overwrites itself and stays that way.
  4. Switch to another tmux pane and back → the pane redraws correctly, then degrades

again on the next update.

Likely area

The "stays garbled until a forced full redraw" behavior is the classic signature of a
synchronized-update (\e[?2026h / \e[?2026l) frame not being flushed — tmux
holds the paint after "begin sync" and only the pane-switch full-redraw clears it.
tmux advertises the sync feature to the client, so if 2.1.200 changed how/when it
emits begin/end-sync (or emits an unbalanced pair), tmux would sit on the frame exactly
like this. (Shared as a hypothesis, not a confirmed root cause.) Whatever the change
was, it shipped in 2.1.200, not 2.1.201.

Workaround

Native install keeps prior versions on disk; repoint the symlink back to 2.1.199:

ln -sfn ~/.local/share/claude/versions/2.1.199 ~/.local/bin/claude

then relaunch Claude Code (a running session keeps its in-memory binary, so the
rollback only takes effect on a fresh launch).

Possibly related

  • #29937 (open) — general tmux rendering corruption. This report adds a precise

199→200 regression window which that issue lacks.

View original on GitHub ↗

7 Comments

Rivil · 1 month ago

Correction to the bisection window.

The original report pinned this to 2.1.201 with 2.1.200 as last-good. That was wrong. Rolling back to 2.1.200 did not fix the garbling — 2.1.200 reproduces it identically. Rolling back one further, to 2.1.199, renders cleanly in tmux.

So the corrected bisection is:

  • 2.1.199 — ✅ clean
  • 2.1.200 — ❌ garbled (regression landed here)
  • 2.1.201 — ❌ garbled (inherited)

I've updated the title, summary, bisection table, environment, repro, and workaround to point at 2.1.199 as the last-good build and 2.1.200 as the first-bad. Whatever changed in the synchronized-update / redraw path shipped in 2.1.200, not 2.1.201.

AdamTerhaerdt · 1 month ago
ln -sfn ~/.local/share/claude/versions/2.1.199 ~/.local/bin/claude

this fixed it for me thanks

gan4dd · 1 month ago

Root cause identified — it's a tmux 3.7a bug, not Claude Code itself.

A single DECSET 2026 sync block containing an ED (\e[2J) is not flushed to the client:
content lands in the pane grid
(capture-pane shows it) but never reaches the screen until a full redraw (keypress / SIGWINCH / refresh-client).
Minimal repro
(4 lines of printf, no Claude needed) filed as tmux/tmux#5340.

Claude Code ≥ 2.1.200 triggers it because the initial paint is now sync-wrapped under tmux 3.4+; 2.1.199 predates that, which is why pinning to 2.1.199 works as a workaround.

Rivil · 1 month ago

Thanks @gan4dd — tmux#5340 looks like a solid root-cause find, and the no-Claude printf repro is the convincing part: a DECSET 2026 sync block whose ED (\e[2J) never flushes to the client until a forced redraw is squarely a tmux bug, and worth fixing upstream.

That said, I don't think it reduces to a tmux-only issue — both things are true at once, which is presumably why this one is already tagged regression:

  • tmux has a latent flush bug (tmux#5340).
  • Claude Code 2.1.200 newly wraps the initial paint — including that ED clear — in synchronized output, which is what trips the bug. 2.1.199 renders cleanly on the identical tmux 3.7a / iTerm2 3.6.11 setup, so 2.1.200 is what changed the trigger, not the environment.

Reasons I'd argue CC should still ship a mitigation rather than wait on the tmux side:

  1. Fix asymmetry. A tmux fix has a long tail before it reaches users through distro packaging, and the affected range is roughly every tmux 3.4–3.7 — a very large installed base broken now. A CC-side change ships in a release and fixes everyone at once.
  2. The trigger is specifically avoidable. Synchronized output is there to cut flicker on incremental repaints; the one-time initial clear doesn't need to be inside the sync wrapper. Emitting that first ED outside ?2026h … ?2026l sidesteps tmux#5340 while keeping the flicker win. Alternatives: probe the capability at runtime instead of gating on "tmux ≥ 3.4," or expose an opt-out (env var / setting) for the sync-wrapped paint.

Happy to test any candidate build against the repro. Pinned to 2.1.199 in the meantime.

gan4dd · 1 month ago

Update: fixed upstream.

tmux master (d53f1b74 / next-3.8) no longer reproduces — Claude Code 2.1.202 renders correctly inside it, no downgrade needed.
Broken on tmux ≤ 3.7b. Until a tmux release ships the fix, workarounds are: pin Claude Code to 2.1.199, or run tmux built from master.

gan4dd · 1 month ago

*Final update:
root cause was a tmux 3.7a bug in synchronized-output redraw, already fixed in tmux 3.7b (e802909d).

*Fix:
upgrade tmux to ≥ 3.7b and run tmux kill-server — a lingering pre-upgrade server keeps the bug alive and tmux -V won't warn you (it reports the client version; check the server with display -p '#{version}').
No Claude Code downgrade needed.

Rivil · 1 month ago

The tmux-side fix landed — tmux 3.7b (commit e802909d, "Fix so that the end of a synchronized update again triggers a redraw") flushes the end-of-sync redraw again, and Claude Code 2.1.204 renders cleanly on it (verified on macOS + Homebrew tmux 3.7b). Resolved for anyone on tmux ≥ 3.7b.

That said, this only started biting when 2.1.200 enabled synchronized output (?2026) on the initial paint (changelog: "Fixed rendering flicker under tmux 3.4+ by enabling synchronized terminal output") — tripping a latent flush bug in every tmux from the 3.4 sync era through 3.7a. Distro tmux tails move slowly, so users on ≤ 3.7a will keep hitting this. A CC-side mitigation would spare them: emit the one-time initial ED (\e[2J) outside the ?2026h … ?2026l wrapper (sync is for incremental-repaint flicker, not the initial clear); or runtime-probe the sync capability instead of gating on "tmux ≥ 3.4"; or add a sync opt-out. Cross-ref tmux/tmux#5340 (fixed in 3.7b).

Showing cached comments. Read the full discussion on GitHub ↗