TUI relayouts (SIGWINCH / permission-mode toggle) spill entire transcript into scrollback as duplicate copies

Status Open
Maintainer reply None cached
Activity 15 comments · opened Apr 12, 2026

Version

  • Claude Code v2.1.101
  • macOS (Darwin 25.3.0)
  • Opus 4.6 (1M context), Claude Max
  • Standard macOS terminal

What happens

During a single Claude Code session, the entire conversation transcript is re-emitted into the terminal's primary scrollback as a fresh full copy every time the TUI relayouts. The live alt-screen pane continues to show the session correctly, but scrolling up reveals N identical copies of the session so far.

Each duplicate is the same session content — same user messages, same assistant responses, same tool calls, same tool-output line numbers, same in-progress spinner state (e.g. Wibbling… (4m 39s)) — rewrapped at a slightly different terminal column width.

Repro

  1. Start a CC session. Run a few commands that produce meaningful transcript (e.g. an MCP call, a skill launch, multi-hunk file edits with visible diffs).
  2. Trigger any of:
  • Resize the terminal window
  • Press Shift+Tab to cycle permission mode (e.g. flip to ⏵⏵ accept edits on)
  • External display connect/disconnect, full-screen toggle, Mission Control gesture — anything that fires a SIGWINCH
  1. Scroll up in the terminal.

Expected: one transcript of the session.
Actual: multiple full copies of the transcript stacked in scrollback, each at a different column width.

Evidence it's a renderer issue, not duplicate sessions

  • ps aux | grep claude shows only one live claude process
  • Each scrollback copy wraps at a different column width (e.g. ~100 → ~115 → ~130 cols) — the content is being re-laid out and re-emitted
  • Status line drifts between copies: earlier copies show 1 MCP server failed · /mcp, later copies show ⏵⏵ accept edits on (shift+tab to cycle), proving the copies were captured at different TUI states within the same session
  • The in-memory conversation the model sees is not duplicated — only the primary scrollback buffer is

Likely cause

The Ink/Yoga TUI appears to re-render the full in-scrollback conversation history on SIGWINCH or permission-mode toggle, rather than limiting the relayout to the active alt-screen pane. Each relayout flushes the entire history back into primary scrollback as a fresh block. The cost is proportional to transcript length, so it's most visible in long sessions.

Impact

Cosmetic / disorienting. The session itself continues to work correctly and the model does not see duplicated context. But scrollback becomes unusable for reviewing a long session, and on first encounter it reads like a real duplication bug — my first hypothesis was that my MCP memory layer was writing duplicate records. It wasn't; the storage was clean.

Suggested fix

  • Limit relayout to the active alt-screen pane; don't re-emit historical transcript on SIGWINCH
  • If relayout of in-scrollback history is truly necessary for correctness, do it in place via cursor addressing rather than appending to scrollback

Workarounds

  • cmd+K / clear to flush scrollback after the fact
  • Avoid resizing the terminal mid-session
  • Avoid toggling permission mode via Shift+Tab in long sessions

Happy to provide additional environment info, a recording, or a minimal repro if useful.

View original on GitHub ↗

15 Comments

carrotRakko · 4 months ago

Adding another trigger and a version regression data point that may help localize the root cause.

Trigger: Ctrl+O toggle (open transcript view → Ctrl+O again to return)

Same root symptom as described here: after toggling Ctrl+O into transcript view and Ctrl+O back out, the primary scrollback accumulates another full render of the session instead of the normal view being redrawn in place. Each Ctrl+O round-trip stacks another copy, so scrollback grows with every toggle.

Version regression: v2.1.96 → v2.1.111

  • On v2.1.96 with the same setup (CLAUDE_CODE_NO_FLICKER=0), Ctrl+O round-trips work correctly: returning to the normal view redraws in place, no duplication in scrollback.
  • On v2.1.111 with the same setup, every Ctrl+O round-trip leaves another stacked copy in scrollback.

This localizes the regression somewhere between v2.1.97 and v2.1.111 (inclusive). The v2.1.110 CHANGELOG note "Changed Ctrl+O to toggle between normal and verbose transcript only; focus view is now toggled separately with the new /focus command" is a plausible suspect window, but I haven't bisected.

Environment

  • Claude Code: v2.1.111
  • OS: Linux (Debian bookworm inside a Docker container)
  • Terminal: iTerm2 (host) → container
  • Model: Opus 4.7
  • CLAUDE_CODE_NO_FLICKER=0 (intentional, to preserve native terminal scrollback)

Workaround tradeoff (no good combination exists today)

  • CLAUDE_CODE_NO_FLICKER=0 → native terminal scroll works, but Ctrl+O round-trips stack in scrollback.
  • CLAUDE_CODE_NO_FLICKER=1 → Ctrl+O stacking is fixed, but the TUI captures scroll events and native terminal scrollback is no longer usable, making long-session navigation painful.

So Ctrl+O looks like another event (alongside SIGWINCH and Shift+Tab) that triggers the same TUI relayout → re-emit-transcript-into-primary-scrollback path described in the original report, and the Ctrl+O path specifically appears to have regressed between v2.1.96 and v2.1.111.

✍️ Author: Claude Code with @carrotRakko (AI-written, human-approved)

lucasec · 4 months ago

The most obvious changelog entry is in 2.1.101: Fixed rendering issues: flicker in non-fullscreen mode when content above the visible area changed, terminal scrollback being wiped during long sessions in non-fullscreen mode, and mouse-scroll escape sequences occasionally leaking into the prompt as text

My testing confirmed the issue appears to have been introduced in 2.1.101. 2.1.98 still clears the scrollback as expected.

I assume this was introduced due to some users complaining that Claude would clear other output from other shell programs or previous Claude sessions in the scrollback. However, the alternative is that scrollback piles up quickly, fulling up memory for those of us that do not set a limit on scrollback, and making searching via Ctrl-F harder. Ideally, this should be a customizable option.

mevouc · 4 months ago

I can confirm. I'm using Windows Terminal Quake mode to open/reduce my terminal dynamically. Which may be the same issue as resizing the window talked about above.

This is a nightmare as a user, and an obvious regression from previous versions.
I did not have any issue in the past two months (before the last few days).

Some of Claude outputs just become straight-up unreadable because it's mixed up with other pieces of the history.

My only workaround is too ask Claude to tell his answer again when that happens.

nedlern · 4 months ago

+1, reproduced on Opus 4.7 (1M context), Claude Max, macOS Darwin 25.4.0, iTerm2. Same pattern: in-flight response re-emitted into scrollback at progressively wider column widths as the terminal window was resized during generation.

Additional evidence: the effect is especially bad when the response contains wide markdown tables. Tables reflow column widths on every SIGWINCH, so each redraw produces a visibly different layout — the same content at ~70, ~80, ~95, ~105, ~115, ~125, ~135, ~145 chars was captured in 8 consecutive scrollback blocks from a single response. Bullet lists reflow trivially and don't seem to trigger the same visual explosion.

Agreeing with OP's diagnosis — the issue is the full transcript being re-emitted on relayout, not any model-side duplication. Eager to see this fixed; it degrades long multi-table responses to unreadable scrollback quickly.

cslovell · 4 months ago

I had a similar issue - closed as likely duplicate of this.

eyalev · 4 months ago

Cross-platform confirmation + version-by-version bisection data for this same bug.

Linux x64 + tmux + xterm.js (web client). Reproduces identically to the macOS-native-terminal report above. The trigger is the same — any SIGWINCH (or any TUI relayout) leaks a fresh copy of the UI/transcript into primary-buffer scrollback.

Bisection (2026-04-25)

Tested every available native build on downloads.claude.ai from 2.1.100 through 2.1.119. Deterministic harness: launch CC in a fresh tmux session at 120×40, wait for startup, issue 6 tmux resize-window calls, then capture-pane and count duplicate UI frames. Baseline = 1; each leak = +1.

| Version | CDN upload (UTC) | Leak count (6 resizes) |
|---------|----------------------|------------------------|
| 2.1.100 | 2026-04-10 04:55 | 0 (clean) |
| 2.1.101 | 2026-04-10 18:36 | 6 (regression lands) |
| 2.1.102 | 2026-04-11 20:24 | 6 |
| 2.1.103 | 2026-04-11 23:09 | 6 |
| 2.1.104 | 2026-04-12 02:20 | 6 |
| 2.1.105 | 2026-04-13 19:45 | 6 |
| 2.1.109 | 2026-04-15 03:37 | 6 |
| 2.1.110 | 2026-04-15 20:25 | 6 |
| 2.1.113 | 2026-04-17 18:54 | 6 (first native build) |
| 2.1.114 | 2026-04-17 23:11 | 6 |
| 2.1.116 | 2026-04-20 19:10 | 6 (see note) |
| 2.1.117 | 2026-04-21 21:38 | 6 |
| 2.1.118 | 2026-04-22 23:27 | 6 |
| 2.1.119 | 2026-04-23 21:16 | 6 |

3/3 reproducible at the boundary. Confirms this issue's "v2.1.101" pinpoint independently. The flip is exact — 2.1.100 (released 2026-04-10 04:55 UTC) is clean, 2.1.101 (released ~14 hours later, 2026-04-10 18:36 UTC) leaks one frame per resize.

The 2.1.116 changelog "fix" does NOT cover this variant

The 2.1.116 changelog says:

Fixed scrollback duplication in inline mode where resizing the terminal or large output bursts would repeat earlier conversation history

The harness above shows 2.1.116 still leaks 6 copies on 6 resizes — identical to 2.1.101 and to current 2.1.119. Either that fix targeted a narrower case (mid-stream burst dup?) or it was regressed in a later release. The "resizing the terminal" wording matches exactly what this issue reproduces.

Conversation content also leaks

Secondary harness: prompt CC for a 3-line response, wait for stream completion, then resize 6 times. 2.1.100 = 0 added copies. 2.1.101 / .116 / .119 = +30 added copies (5 copies per resize of the 3-line response). For long conversations this is catastrophic.

Minimal repro (no API calls — fires from resize alone)

tmux kill-session -t cctest 2>/dev/null
tmux new-session -d -s cctest -x 120 -y 40
tmux send-keys -t cctest 'claude --dangerously-skip-permissions' C-m
sleep 10                                                          # let CC start

for w in 80 100 140 90 130 120; do
  tmux resize-window -t cctest -x $w -y 40
  sleep 1
done
sleep 2

tmux capture-pane -t cctest -p -S -2000 | grep -c 'Claude Code v'
# expected 1, actual 7 on 2.1.101 → 2.1.119

Mitigation tradeoff worth noting in any fix discussion

Opus 4.7 was added in 2.1.111 (2026-04-16) — six days after the leak landed in 2.1.101. There is no version that has both Opus 4.7 and clean scrollback rendering; downgrading to 2.1.100 caps users at Opus 4.6.

(I had filed #53248 as a separate report and the auto-deduper correctly flagged this as the canonical issue. Closing #53248 as duplicate.)

benjaminv · 4 months ago

Adding cross-issue evidence — requesting this be promoted as the canonical tracker.

The 2.1.116 → 2.1.119 regression that @eyalev's bisection above confirmed is also still being reported on at least two parallel issues, and the duplicate-handling has fragmented the conversation in a way that's working against a fix:

  • #49086 — got a "fixed in 2.1.116" comment from claude, but has 6+ subsequent reports of continued reproduction across 2.1.116 / 2.1.118 / 2.1.119, on iTerm2, Ghostty, macOS Terminal.app, VS Code integrated terminal, and Windows 11. (I'm one of the reporters — cross-terminal repro on Apple Silicon, drag-resize SIGWINCH stacking is worst on Ghostty due to faster GPU rendering capturing more intermediate frames.) Issue is still open but has the same premature "fixed" note.
  • #47235 — got the same "fixed in 2.1.116" comment, was closed, and is now auto-locked after 7 days of inactivity, preventing affected users from continuing the conversation there.
  • #49057 — auto-closed by the duplicate bot as a duplicate of #46462.

So between the auto-lock, the auto-dedupe, and the premature "fixed" notes, this issue (#46834) is effectively the only live thread where the bisection, minimal repro, and Ctrl+O second-trigger evidence are accumulating. Worth flagging that explicitly so it doesn't get auto-closed by the duplicate bot itself.

Concrete asks:

  1. Reopen tracking here (or wherever a maintainer prefers) and link the related issues so reporters know where to land.
  2. Treat the 2.1.116 changelog entry — "Fixed scrollback duplication in inline mode where resizing the terminal or large output bursts would repeat earlier conversation history" — as not covering this variant, per @eyalev's 6/6-leaks-on-6-resizes harness on 2.1.116.
  3. The Ctrl+O trigger @carrotRakko documented strongly suggests a single underlying TUI-relayout path (SIGWINCH, Ctrl+O, Shift+Tab all re-emit the transcript into primary scrollback) — fixing the path should resolve all three.

Happy to add asciinema captures from Ghostty / iTerm2 / Terminal.app drag-resize if useful — the differential frame counts across emulators (Ghostty worst, iTerm2 middle, Terminal.app fewest) might help confirm the SIGWINCH-frequency hypothesis.

zarifaziz · 3 months ago

You can force claude on tui mode for scrolling issues
use

CLAUDE_CODE_NO_FLICKER=1 claude
lucasec · 3 months ago
You can force claude on tui mode for scrolling issues use `` CLAUDE_CODE_NO_FLICKER=1 claude ``

That variable enables the alternate screen mode, where Claude Code takes over the entire terminal and controls all scrolling, etc. In many cases, that is not desired, hence why the normal mode exists (and remains the default). E.g. many terminal emulators provide a better native experience scrolling through the history.

If Anthropic is committed to maintaining the normal mode (which most indications suggest they are), this redraw problem will need to be figured out. As before, ideally the user would be offered a choice: either (A) dump a _clear_ separator and new scrollback on every resize/full redraw, or (B) issue the clear scrollback command.

mevouc · 2 months ago

Claude spontaneously recommended me /tui fullscreen, which I didn't know of.

It fixed the issue for me (and it's the best TUI experience I was hoping for from ClaudeCode), and I think it should be the default TUI mode.

Issue can be closed in my opinion, it's now just a personal configuration matter.

mevouc · 2 months ago

@rdmgator12 did you know/have you tried /tui fullscreen ?

lucasec · 2 months ago

This was addressed earlier in the thread.

thampton-lexant · 2 months ago

+1 — still reproducible on v2.1.170 (current latest), iTerm2, macOS (Darwin 25.5.0), Max plan.

Same symptom as OP: stale frames of the live region re-emitted into primary scrollback, overlapping/interleaved with newer output (short new lines painted over longer old ones without clear-to-EOL, stray SGR digits where escape bytes got split). Live view stays correct; only scrollback is corrupted.

Data points that may help:

  • Worst during long turns (30–45 min) with multiple parallel subagents running plus the todo-list overlay visible — each relayout stacks another corrupted copy of that tall live block.
  • Confirmed triggers here: shift+tab permission-mode cycling and ctrl+o expand/collapse while generation is in flight; window resize also does it.
  • Ruled out local causes before landing here: custom statusline width (bounded well under terminal width, no change), terminal profile/font settings, plugins — identical config on a second machine profile that doesn't run long multi-agent turns never shows it.

Workaround for anyone hitting this: Cmd+K (iTerm2 clear buffer) wipes the garbage; session content is unaffected.

thampton-lexant · 2 months ago

Follow-up to my earlier comment with a cleaner trigger bisection, after several days of debugging this across two profiles on the same machine (iTerm2, macOS Darwin 25.5.0, now on v2.1.172).

Setup that made this a clean experiment: two CLAUDE_CONFIG_DIR profiles with verified-identical terminal settings (full iTerm2 profile diff), same CC version, same statusline (width-bounded well under the window). One profile ran long multi-agent turns; the other short interactive sessions.

Findings:

  • The corruption tracks session shape, not config: it only appeared in whichever profile ran long turns with a tall live region (parallel subagents + todo list overlay). When the other profile started running the same workload, the corruption followed it there.
  • Confirmed relayout triggers, each observed at the corruption site across six captures:
  1. Session recap insertion (awaySummaryEnabled) — the italic ✻ recap: line was present at the corruption site in every capture until we disabled recaps; in one frame it was character-interleaved with the -- INSERT -- vim indicator line.
  2. Large multi-line paste growing the input box ([Pasted text #N +18 lines] visible in the corrupted frame).
  3. "Image in clipboard · ctrl+v to paste" notice appearing in the prompt region.
  4. Previously reported: shift+tab permission-mode cycling, ctrl+o, window resize.
  • Ruled out by testing: custom statusline (bounded to 120 cols, corruption persisted), a hook-heavy plugin (fully disabled, corruption persisted), iTerm2 profile/font settings (byte-compared), GSD/MCP servers.
  • Disabling recaps dramatically reduced frequency for us, since recap-on-return was the most common relayout in long autonomous sessions. The defect itself (stale frames spilled/interleaved into scrollback on live-region relayout) remains in 2.1.170; not yet re-tested long enough on 2.1.172 to say either way.

Hope the trigger list helps narrow the repaint path. Happy to provide full-resolution captures if useful.

benswift · 2 months ago

+1, and adding an environment not yet represented in this thread: zellij.

  • Claude Code v2.1.181, zellij 0.44.3, Ghostty, macOS (Darwin 25.5.0).
  • Same symptom as OP — stale frames of the live region spilled/interleaved into

primary scrollback on relayout; the live view stays correct.

  • Ctrl+L reliably heals it, consistent with the Cmd+K / clear workaround

others have reported.

Worth flagging that zellij amplifies this relative to a bare terminal: it emits
SIGWINCH not only on manual resize but on every tab switch, pane resize, and
session attach/detach, so a long multi-pane session keeps hitting the relayout
path. That mechanism was written up in #52304, which was closed as a duplicate
of this issue — so the zellij angle currently has no live home here.