Rewind / time-travel picker hangs on large session transcripts (~40MB / 15k events)
Summary
The rewind / time-travel picker hangs indefinitely when opened against a session whose transcript JSONL has grown large (tens of MB / tens of thousands of events). The terminal becomes unresponsive and must be killed to recover. Smaller sessions in the same environment open the picker normally, so the trigger correlates with transcript size rather than content, corruption, or environment.
Environment
- Claude Code versions observed in the same transcript:
2.1.114,2.1.117,2.1.119(a single long-running session was appended across all three — the hang reproduces on2.1.119) - OS: Ubuntu 22.04.5 LTS on WSL2, kernel
6.6.87.2-microsoft-standard-WSL2 - Node:
v22.22.2 - Model:
claude-opus-4-7 - Terminal: any (tested in the invoking WSL terminal; not terminal-emulator specific based on symptom)
Steps to reproduce
- Use a single session in one working directory over a prolonged period so its transcript at
~/.claude/projects/<encoded-cwd>/<sessionId>.jsonlgrows into the multi-tens-of-MB / tens-of-thousands-of-events range. claude --resume <sessionId>- Open the rewind / time-travel picker.
Expected: the picker lists rewind points and remains interactive.
Actual: the picker opens but never completes rendering. No input (including Esc, Ctrl+C) is accepted. Only killing the terminal process recovers.
File characteristics where the hang reproduces
Measurements taken from the affected transcript:
| Attribute | Value |
|---|---|
| File size | ~40 MB |
| Line count (events) | 15,361 |
| Trailing bytes | Valid JSON — file is intact, not truncated by a crash |
Event-type distribution (from jq -r '.type' file.jsonl | sort | uniq -c):
7054 assistant
4208 user
1600 attachment
721 permission-mode
711 last-prompt
385 system
371 queue-operation
309 file-history-snapshot
2 custom-title
A sibling session file in the same projects/<encoded-cwd>/ directory (~640 KB, 299 events) opens the picker normally. The only meaningful difference between the two is size / event count.
Workaround
Resuming with --fork-session creates a new session UUID and a fresh, small event log inheriting the conversation context. The picker is responsive in the forked session because its local event count starts at zero.
claude --resume <sessionId> --fork-session
Caveat: the rewind graph of the forked session starts at the fork point; rewind into the pre-fork history of the original session is no longer reachable through the picker.
Suspected cause
The scaling cutoff between a 299-event session (fine) and a 15,361-event session (hangs) suggests the picker loads and renders the full event history synchronously — no streaming parse, no virtualized list. The hang scales with transcript size rather than any content-specific trigger. No error is surfaced, and there is no cancellable progress indicator, so the UI appears frozen rather than slow.
Suggested directions
- Stream-parse the transcript rather than reading it into memory in one pass.
- Virtualize the picker list so rendering cost is bounded by visible rows, not total event count.
- Short-term mitigation: time-box the load with a cancellable progress indicator so users can abort without killing the terminal.
- Surface a size / event-count warning on resume when transcripts cross a threshold, pointing at
--fork-sessionas an escape hatch.
Impact
- User-visible freeze with no graceful abort.
- Recovery requires killing the terminal.
- Long-running sessions gradually lose access to the rewind feature without any deprecation signal.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗