fix: stream-parse session JSONL to prevent OOM on large sessions #160
+66
−35
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #526 —
happycrashes withFATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memoryon long-running Claude Code sessions.Root Cause
Long-running Claude Code sessions (especially after context compaction via
--continue) produce JSONL files of 500MB+. Two functions load the entire file into memory:readSessionLog()— usesreadFile(path, 'utf-8')then.split('\n'), creating two copies of the entire file in memoryclaudeCheckSession()— usesreadFileSync(path, 'utf-8').split('\n')just to check if one valid message existsV8's default heap limit is ~4GB. A 650MB JSONL file becomes ~1.3GB as a UTF-16 JS string, then doubles with
.split(), plus the parsed JSON objects — easily exceeding the heap.Fix
readSessionLog(): ReplacereadFile()withcreateReadStream()+readline.createInterface()for line-by-line streaming. Memory stays flat (~50MB) regardless of file size. Also caps retained messages at 500 most recent — the mobile app only needs recent context, not the full history.claudeCheckSession(): ReplacereadFileSync()with a 16KB partial read viaopenSync/readSync. Only need to find one valid JSON line to confirm session validity — no need to read the entire file.Testing
Tested with a 650MB session JSONL file (long-running Claude Code session with multiple context compactions). Before: OOM crash within 60 seconds. After: starts successfully with ~50MB memory usage.
Test plan
happy --continuewith a large session (500MB+ JSONL)claudeCheckSession.test.tsandsessionScanner.test.ts🤖 Generated with Claude Code