[BUG] TUI renders garbled inside tmux since 2.1.200 (last-good 2.1.199) — only repaints on forced redraw
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 reportsRGB+sync
(synchronized-output / mode 2026) features
- macOS (Darwin 25.5.0)
Steps to reproduce
- Run Claude Code v2.1.200 (or 2.1.201) inside a tmux pane (iTerm2 outer,
tmux-256color). - Interact so the TUI repaints (type, let output stream, scroll).
- Text becomes garbled / overwrites itself and stays that way.
- 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.
Showing cached comments. Read the full discussion on GitHub ↗
7 Comments
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:
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.
this fixed it for me thanks
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-paneshows 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.
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:EDclear — 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:
EDoutside?2026h … ?2026lsidesteps 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.
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.
*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 andtmux -Vwon't warn you (it reports the client version; check the server withdisplay -p '#{version}').No Claude Code downgrade needed.
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 initialED(\e[2J) outside the?2026h … ?2026lwrapper (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).