Rewind / time-travel picker hangs on large session transcripts (~40MB / 15k events)

Resolved 💬 3 comments Opened Apr 24, 2026 by dbasclpy Closed May 28, 2026

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 on 2.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

  1. Use a single session in one working directory over a prolonged period so its transcript at ~/.claude/projects/<encoded-cwd>/<sessionId>.jsonl grows into the multi-tens-of-MB / tens-of-thousands-of-events range.
  2. claude --resume <sessionId>
  3. 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-session as 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.

View original on GitHub ↗

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