Context compaction clears terminal scrollback, losing visible conversation history

Resolved 💬 7 comments Opened Apr 1, 2026 by use7en Closed Apr 18, 2026

Context compaction clears terminal scrollback, losing visible conversation history

During a running session, context compaction triggers a full terminal re-render that erases the scrollback buffer. The user sees the startup banner and "Searched memories" as if the session restarted — but the session ID is unchanged. This happens multiple times per session, making it impossible to reference earlier messages or tool outputs.

---

Observed Behavior

| What the user sees | What actually happens |
|---|---|
| Startup banner appears mid-session | Terminal cleared and re-rendered from compaction point |
| "Searched memories (ctrl+o to expand)" | System reloads memory index after compaction |
| Cannot scroll up to previous messages | Scrollback buffer overwritten by re-render |
| Session appears to restart | Session ID unchanged, JSONL log shows continuous session |

Reproduction

Minimal Conditions

  1. Large initial context (see configuration below)
  2. Multi-turn conversation with tool calls
  3. Subagent spawns that return large results
  4. Session continues long enough to trigger compaction

The bug triggers earlier and more frequently with larger initial context.

Context Configuration (tested setup)

| Component | Size | Notes |
|-----------|------|-------|
| CLAUDE.md files | 175 lines | Project + user instructions |
| Auto-loaded rules | 522 lines | 10 rule files (path-scoped + unconditional) |
| MEMORY.md index | 101 lines | Persistent memory pointers |
| MCP servers | 6 | Each injects instruction text |
| Registered skills | 40+ | Listed in system-reminder |
| Active hooks | 6 | Shell scripts on events |
| System-reminder injection | ~2,700 chars/msg | Injected into user messages |

---

Session Analysis

Full analysis of an affected session (JSONL log, anonymized).

Key Metrics

| Metric | Value |
|--------|-------|
| Duration | 96 minutes (07:13–08:49 UTC) |
| JSONL lines | 357 |
| Cumulative size | 1,095,522 chars |
| Messages | 191 assistant, 111 user |
| Tool calls | 99 (49 Bash, 19 Edit, 18 Read, 12 Agent, 4 Write, 1 Glob) |
| Subagent spawns | 12 → 25 subagent JSONL files (largest: 982KB) |
| file-history-snapshot events | 25 (each correlates with a visible terminal reset) |
| Turns (by turn_duration) | 9 |

Compaction Growth Curve

| Turn | Messages | Turn Duration | Cumulative Size | Snapshots Since Last Turn |
|------|----------|---------------|-----------------|---------------------------|
| 1 | 33 | 302s | 92KB | 1 (initial) |
| 2 | 45 | 38s | 118KB | 2 |
| 3 | 57 | 42s | 138KB | 2 |
| 4 | 72 | 85s | 205KB | 2 |
| 5 | 114 | 475s | 437KB | 3 |
| 6 | 215 | 813s | 841KB | 10 |
| 7 | 234 | 87s | 890KB | 2 |
| 8 | 298 | 1380s | 1,052KB | 2 |
| 9 | 320 | 121s | 1,096KB | 1 |

Turn 6 is the worst: 10 file-history-snapshot events in a single turn (813s), including a dense cluster of 7 snapshots in 19 JSONL lines (lines 140–159). This suggests compaction fires repeatedly mid-turn during heavy subagent work.

<details>
<summary>Snapshot cluster analysis</summary>

Cluster 1: lines 37-42   — 2 snapshots in 5 lines (between turns)
Cluster 2: lines 51-56   — 2 snapshots in 5 lines (between turns)
Cluster 3: lines 96-99   — 2 snapshots in 3 lines (mid-turn)
Cluster 4: lines 127-129 — 2 snapshots in 2 lines (mid-turn)
Cluster 5: lines 140-159 — 7 snapshots in 19 lines (dense, mid-turn)

Dense region (lines 127-186): 10 snapshots in 59 lines
Positions: [127, 129, 140, 143, 146, 149, 152, 155, 159, 186]

Each snapshot correlates with a terminal clear/re-render visible to the user.

</details>

<details>
<summary>User experience timeline</summary>

07:13 — User sends first prompt (simple navigation request)
07:13 — file-history-snapshot (line 0)
07:18 — Turn 1 ends (302s, 33 msgs) — SNAPSHOT at line 37
         User: "das dauert nun schon 6min" (frustrated by long turn)
07:20 — SNAPSHOT at line 42
07:21 — Turn 2 ends (38s, 45 msgs) — SNAPSHOT at line 51
07:25 — User describes the bug: "meistens wenn ich abbreche und neu eingebe"
07:28 — SNAPSHOT at line 56
07:29 — Turn 3 ends (42s, 57 msgs) — SNAPSHOT at line 65
07:41 — Turn 4 ends (84s, 72 msgs) — SNAPSHOT at line 81
07:45 — User requests optimization with subagents
07:49 — SNAPSHOTs at lines 96, 99 (rapid)
07:53 — Turn 5 ends (475s, 114 msgs)
07:57 — SNAPSHOTs at lines 127, 129 (rapid)
07:59 — User re-sends same message (previous input lost?)
08:00–08:04 — DENSE: 7 snapshots in 19 lines (140-159)
08:07 — SNAPSHOT at line 186
08:13 — Turn 6 ends (813s, 215 msgs) — worst turn
08:14 — SNAPSHOTs at lines 247, 253
08:17 — SNAPSHOT at line 268
08:40 — Turn 8 ends (1380s, 298 msgs)
08:47 — SNAPSHOT at line 335
08:49 — Turn 9 ends (121s, 320 msgs)

Note at 07:59: User re-sends the same message — likely because the previous terminal output was cleared by compaction and they couldn't tell if their input was received.

</details>

---

Root Cause Hypothesis

The TUI rendering layer (Ink/React-based) re-renders the entire conversation output after each file-history-snapshot / compaction event. This overwrites the terminal scrollback buffer. The internal state is correct — only the visual representation is destroyed.

Evidence:

  • JSONL log shows continuous session with correct message sequencing
  • Session ID unchanged across all 25 snapshot events
  • The file-history-snapshot events have no timestamp (empty), suggesting they are internal bookkeeping, not user-facing events
  • Snapshots cluster during heavy subagent work, when large tool results are being processed

Suggested Fix

  • [ ] Compaction should only affect the internal message context sent to the API
  • [ ] The terminal scrollback should remain untouched during compaction
  • [ ] If re-rendering is necessary, append rather than clear+rewrite
  • [ ] Consider adding a visible indicator (e.g., "Context compacted — earlier messages summarized") instead of replaying the startup banner

Workaround

Increase terminal scrollback buffer:

// VS Code settings.json
{ "terminal.integrated.scrollback": 10000 }

This mitigates but does not solve the issue — the re-render still clears everything beyond the buffer.

Environment

  • Claude Code: v2.1.89
  • Model: Opus 4.6 (1M context)
  • Platform: VS Code Remote (Dev Container on WSL2)
  • OS: Linux (WSL2)
  • Terminal: VS Code integrated terminal (default scrollback: 1000)

---
🤖 Generated with Claude Code

View original on GitHub ↗

This issue has 7 comments on GitHub. Read the full discussion on GitHub ↗