[BUG] cct = TUI: multi-paragraph live-render-duplication
<img width="1680" height="1050" alt="Image" src="https://github.com/user-attachments/assets/57e4793b-0451-4220-94e3-1605ab105bcd" />
<img width="1680" height="1050" alt="Image" src="https://github.com/user-attachments/assets/1ee56512-cd1d-4bcc-8ee7-2c5818838356" />
## Cluster context — cct TUI live-render-path defect cluster This issue is one of five filed/pending GitHub issues documenting a cluster ofcctTUI live-render-path defects. The cluster's unifying upstream class: parsing-vs-structure fragility incctTUI rendering, combined with alternate-screen-buffer state preservation across resumes. See the cluster meta-issue (forthcoming; placeholder#NNNNNuntil filed) for the cross-cluster architectural framing. Cluster members: - #64007 — render-omission at turn transitions - #64567 — render-duplication at Bash permission gates - Pending: multi-paragraph live-render-duplication (this issue) — render-duplication in substantive multi-paragraph turns with progressive contraction across resume cycles - #67254: render-duplication in turns containing Bash tool_use calls — multi-turn duplication with Bash tool_use involvement (cluster-membership relative to #64567 open pending clean-test re-run) - #67252 rendered-text character-level garbling — character-level corruption with cold-boot persistence (the cluster's only corruption-family member) (https://github.com/anthropics/claude-code/issues/67252) This issue covers: live-render duplication of substantive multi-paragraph single turns, with the duplication progressively contracting across multiple/exit + bash-clear + claude -cresume cycles (rather than #64567's binary clear).
---
What's Wrong?
The Claude Code TUI (cct) live-render path produces duplicated content. In the exemplar, a paragraph-break-spanning region (two adjacent lines crossing a paragraph break, duplicated as a contiguous block) in the visible output. The .jsonl source-of-truth for the same space has properly formed content. Two previous bug reports (#64007 and #64567) document related live-render path failures in cct — turn transitions producing omission (#64007) and Bash permission gates producing duplication (#64567). This report concerns both a recurring pattern across several sessions in separate project spaces and what appears to be a member of the larger family. The capture documented below shows only the exemplary instance.
This report adds a progressive-contraction property absent from the previous reports. Live-rendered duplication is preserved across /exit + bash-clear + claude -c cycles, but the duplication progressively contracts across multiple cycles rather than binary-clearing on the first cycle (as #64567's permission-gate duplication does). A clean-test observation across the night of 2026-06-07/08 (live-render anomaly → multiple workaround cycles → no intervening turn) showed three cycles to progressively shrink and finally clear a duplicated region. The .jsonl source-of-truth being clean while the resumed render still shows duplication on cycle 1 indicates cct is restoring rendered content from some store other than the .jsonl on resume — most likely the terminal alternate-screen buffer, which is known to bypass terminal scrollback (cf. #28077 and #42002).
The relationship to #64567 is left open at filing time; see Relationship to existing issues below for the discriminating test.
What Should Happen?
Initial, live-render should not have anomalous repetition of content within or across user-agent turns matching the .jsonl exactly; the live-render path should not be capable of writing duplicated content into any render-state that subsequent resumes restore from. The restored buffer at claude -c should match what the .jsonl records — each turn rendered exactly once, with each paragraph/line appearing once.
How to reproduce
The defect recurs across normal use of cct being encountered routinely. Specific trigger conditions are not fully characterized — substantive multi-paragraph agent turns with bolded headers and paragraph breaks between content blocks appear to be a sufficient pattern, but bisection across response shapes has not been attempted.
For the captured instance:
- Operate a
cctsession that produces substantive multi-paragraph agent turn. /exitthe session.claude -cto resume — observe the duplicated block in the restored scrollback for the affected turn./exit+ bashclear+claude -c(repeat 1-3 times) — confirm the duplication persists across these operations rather than clearing.- Submit any fresh user prompt — observe that the rendering anomaly remains in the previous turns. If a new anomaly appears in the most recent turn expect 3 for that turn only.
- Repeat 4. Observe the rendering anomaly preceding the last turn has resolved.
Environment
cccversion: 2.1.153- Platform: Linux (KDE Plasma 6 / Konsole)
- Conversation
.jsonlsource-of-truth: verified clean for the affected turn
Evidence
The pattern recurs across normal sessions; the captured instance evinces the pattern. Additional captures have not been made, but will be attempted upon request.
- Source
.jsonl(clean): the affected turn's.jsonlrecord contains a singletextcontent block emitted once; verified via direct inspection at session jsonl line 1121 (~/.claude/projects/.../c25f6fb4-cf26-4ede-9025-eebb26ce99cb.jsonl). - TUI scrollback (duplicated): screenshots showing the duplicated block in the rendered buffer.
- Persistence demonstration: screenshot of two consecutive
/exit + Goodbye!exchanges in the same buffer with the duplicated content preserved between them. - Discriminator finding:
exit + bash-clear + claude -csequence (3x) did not clear the duplication; only the subsequent fresh user-prompt + agent-response + workaround cycle affected the anomaly.
Probable root cause (observation-grounded hypothesis)
cct uses the terminal's alternate screen buffer, which bypasses the normal terminal scrollback. This is documented as a known limitation in #28077 and #42002. The alternate-screen buffer's internal viewport has a hardcoded size that doesn't scale with session length, and its contents are preserved across cct exits — which is how the duplication carries through /exit + bash-clear + claude -c cycles.
The defect appears to be a live-render path error that writes duplicated content at initial-render time into the alternate-screen buffer. On resume via claude -c, cct's resume-reconstruction populates the alternate-screen buffer from some combination of .jsonl replay and pre-existing buffer state — faithfully reproducing the initial-render's duplicated output. The progressive-contraction observed across multiple resume cycles is unexplained mechanistically, but it lives within the alternate-screen-buffer architecture.
Two readings of the relationship to #64567 are possible:
- Distinct sibling defects under the same upstream class. #64007, #64567, and this defect are three separate live-render bugs that share an upstream parsing-vs-structure-fragility class. Different triggers, different surface failure modes, distinct fixes. The progressive-contraction property here is a property of this bug's trigger condition specifically.
- Same defect across reports, with different trigger surfacing different render-state properties. #64567's body documented the
/exit + bash-clear + claude -cworkaround as reliably clearing its duplication; that finding was specific to the trigger condition tested at original filing (Bash permission gate at CCC 2.1.145) and may not generalize. This report's substantive-multi-paragraph trigger at CCC 2.1.153 exposes a progressive-contraction property the prior trigger may not have surfaced.
The two readings are equally weighted at filing; discriminator test below.
Discriminating test Anthropic can run. Re-trigger #64567's permission-gate duplication on current cct version (2.1.153). Run /exit + bash-clear + claude -c once and observe. If the duplication clears in one cycle (matching #64567's original filing), the two defects are distinct triggers with different render-state behaviors (reading 1). If the duplication shows progressive contraction across multiple cycles (matching this report), the two defects collapse to one with a wider trigger surface than originally characterized (reading 2).
Not yet verified against cct's actual codebase; the above is observation-grounded with three discriminator data points (clean .jsonl source-of-truth; one /exit + bash-clear + claude -c cycle does not fully clear the duplication; progressive contraction observed across multiple cycles in clean-test conditions).
Relationship to existing issues
This defect is probably a sibling under the same family as #64007 and #64567 — all three are cct TUI render failures in the live-render path producing output that diverges from the clean .jsonl source-of-truth. The defect may be the same as #64567 with a previously-untested trigger and a render-state-persistence property; see Probable root cause above for the two readings and the discriminating test.
Surface differences across the three reports:
- #64007 — live-render path produces omission at turn transitions (content present in
.jsonl, absent from rendered scrollback) - #64567 — live-render path produces duplication at Bash permission gates (single emission in
.jsonl, double emission in rendered scrollback) - This defect — live-render path produces duplication at initial render of substantive multi-paragraph turns (single emission in
.jsonl, duplicated block in rendered scrollback) with progressive contraction across multiple/exit + bash-clear + claude -ccycles (one cycle does not fully clear; multiple cycles progressively shrink the duplicated region) - Comment on #64567 (2026-06-07) — a fourth live-render-path defect with another trigger (
away_summaryrecord format match)
Filing as separate issue rather than as comment. The progressive-contraction property is the differentiator that warrants its own diagnostic visibility rather than being subordinated to #64567's permission-gate framing. As a standalone issue, this finding is also more discoverable for someone searching the cct bug-tracker for "resume", "duplication", or "progressive contraction" — keywords that don't fit #64567's framing. Filing separately doesn't preclude collapse: Anthropic's triage should feel free to consolidate this into an extended #64567 if codebase investigation confirms common origin per the discriminator test above.
Note on prior diagnostic claims. #64567's body line 106 stated: "This pinpoints the defect to the live-render code path rather than the .jsonl-driven replay-render code path. The same .jsonl content, read at resume time, produces clean output." A follow-up comment-draft for #64007 stated the replay-render path is "Clean in all observed cases". The prior claims hold for the triggers tested at original filing. The "replay-render is clean" claim's generality needs revisiting in light of this report's progressive-contraction observation — the same .jsonl content read at resume time can produce duplicated output that contracts across cycles, at least for this content shape.
The unifying upstream class across all four defects appears to be parsing-vs-structure fragility in cct TUI rendering combined with alternate-screen-buffer state preservation across resumes. See #64007 follow-up comments for the broader cluster framing across both omission and duplication families.
Versions / regression notes
ccc 2.1.153 observed. Defect potentially predates this version but not characterized at earlier versions in this submitter's records. If reading (2) above is correct and the persistence property was introduced by code changes between 2.1.145 and 2.1.153, the regression boundary is plausibly in that range. Anthropic engineering would have visibility into whether render-state-preservation logic was added or modified in that version range.