[BUG] Ghost sessions from remote-control connections and background summary tasks pollute the resume picker
What's Wrong?
The /resume picker (and claude --resume) displays "ghost" sessions that contain no real user interaction. These ghost sessions are created by two internal mechanisms:
- Remote-control bridge connections: Every time the claude.ai web UI opens/refreshes a code session link, a new
.jsonlsession file is created containing only abridge_statussystem message andfile-history-snapshotentries — even if the user never sends a single message.
- Background session summary generation: When Claude Code generates summaries for past conversations, it creates separate
.jsonlsession files (starting withqueue-operationtype) that contain only the auto-generated summary prompt ("Context: This summary will be shown in a list...") and the model's response.
Both types of sessions appear indistinguishable from real conversations in the resume picker, crowding out actual work sessions. Since the picker only displays ~10 most recent sessions, ghost sessions can push real conversations below the visible threshold.
Measured impact (single project)
| Session type | Count | % of total |
|---|---|---|
| Normal (real user interaction) | 96 | 78% |
| Auto-summary (background task) | 15 | 12% |
| Remote-control empty connections | 10 | 8% |
| Empty init (no interaction) | 2 | 2% |
| Total ghost sessions | 27 | 22% |
In the most recent 24 hours alone, 25 out of 35 new session files were ghosts.
What Should Happen?
Sessions that never received a real user message should not appear in the resume picker. Specifically:
- A session file should either (a) not be created until the first real user message arrives, or (b) be excluded from the resume picker if it contains no user messages.
- Background summary tasks should not create top-level session files at all, or should be clearly marked as internal/system sessions.
- Remote-control bridge connections should not create a persistent session record until actual interaction occurs.
Steps to Reproduce
- Enable remote-control (e.g., via claude.ai web bridge)
- Open the code session URL in a browser
- Do not send any message — just let the connection establish
- Close the browser tab
- Repeat steps 2-4 several times
- Run
claude --resumeor use/resume - Observe: each empty connection created a separate session entry in the picker
For auto-summary ghosts:
- Have multiple existing sessions with conversations
- Wait for Claude Code to run background summary generation (triggered automatically)
- Run
/resume - Observe: summary-generation sessions appear as separate entries with the prompt "Context: This summary will be shown in a list..."
Evidence
Ghost session file content — remote-control empty connection (1,701 bytes each)
{"type":"system","subtype":"bridge_status","content":"/remote-control is active. Code in CLI or at https://claude.ai/code/session_xxx"}
{"type":"file-history-snapshot",...}
{"type":"file-history-snapshot",...}
No human/user messages. No assistant responses. Just a bridge status notification and file snapshots.
Ghost session file content — auto-summary (3-4 KB each)
{"type":"queue-operation","operation":"dequeue","sessionId":"..."}
{"type":"user","message":{"content":"Context: This summary will be shown in a list to help users and Claude choose which conversations are relevant..."}}
{"type":"assistant","message":{"content":"<summary>...</summary>"}}
These are internal housekeeping operations, not user-initiated conversations.
Timeline showing ghost session creation pattern
02-27 11:08 | AUTO-SUMMARY (×3) ← background summary generation
02-27 11:04 | REMOTE-CTRL ghost ← empty bridge connection
02-27 11:03 | AUTO-SUMMARY (×2)
02-27 10:50 | AUTO-SUMMARY (×9) ← burst of summary generation
02-27 10:48 | REMOTE-CTRL ghost
02-27 03:11 | REMOTE-CTRL ghost
02-26 22:00-22:06 | REMOTE-CTRL ghost (×5) ← rapid reconnections
02-26 21:52 | REMOTE-CTRL ghost
02-26 21:39 | REMOTE-CTRL ghost
Proposed Solution
From a first-principles perspective, the root cause is that session file creation is conflated with meaningful interaction. Three approaches, in order of preference:
Option A: Lazy session file creation (prevention)
Do not write a .jsonl session file until the first real human/user message is received. Buffer system events (bridge_status, file-history-snapshot, progress) in memory. If the session ends without any user message, discard the buffer — no file is ever written.
Option B: Mark and filter (display-time fix)
Add a sessionType field to session metadata ("interactive", "system", "summary"). The resume picker filters to show only "interactive" sessions by default.
Option C: Post-hoc cleanup (least preferred)
Add a garbage collection pass that removes session files with no human/user messages older than N minutes. This is fragile and doesn't prevent the display problem during active use.
Related Issues
- #25032 — sessions-index.json not updated, stale/missing sessions
- #24435 — Resume picker only shows ~8 most recent sessions
- #25130 — Allow /resume to display full session history
- #12052 — Show session/agent IDs in resume picker
Environment
- Claude Code Version: 2.1.62
- Platform: Anthropic API
- OS: macOS (Darwin 25.3.0)
- Terminal: WezTerm + tmux
- Remote-control: Active (claude.ai web bridge)
- Plugins: ~30 marketplace plugins installed (superpowers, plan-cascade, document-skills, etc.)
This issue has 6 comments on GitHub. Read the full discussion on GitHub ↗