Desktop app persists session metadata before any user message → 'No messages yet' zombies clutter Recents

Resolved 💬 1 comment Opened May 14, 2026 by AdelElo13 Closed Jun 12, 2026

Summary

The Claude desktop app writes a local_*.json session-metadata file the moment a new session is opened, before any user message exists. If the user closes the window without typing, the metadata persists and the session shows up in the Recents sidebar forever — with a (often auto-generated or stale) title and No messages yet. in the body. Over time this is significant UI clutter.

Reproduction

  1. Open the Claude desktop app
  2. Click + New session in any project
  3. Wait ~3 seconds without typing
  4. Close the window / switch to another session

→ A new entry appears in the Recents sidebar with a title (sometimes pre-generated from project context, sometimes blank) and No messages yet. when reopened. It cannot be auto-cleared.

Evidence from one user's machine

Inspection of ~/Library/Application Support/Claude/claude-code-sessions/<UUID>/<UUID>/local_*.json files for a single project (Open-Jarvis):

Sessions sorted by (lastActivityAt - createdAt):
    1.0s  Implement crash reporter and recovery system
    2.9s  Check Jarvis binary version
    8.6s  Set up crash reporting and metrics collection
   11.5s  Resubmit awesome claude code
   67.3s  Research deliverable for Logos multi-faith search engine
  ...
112142.2s  Fix mac-control-mcp bugs   ← real 31-hour work session
943008.9s  Cerebral Valley hackathon  ← real 10.9-day work session

4 of 26 sessions (~15%) had lifetimes under 12 seconds — almost certainly never received a user message. Each local_*.json is 60–100 KB of metadata (mcp tool grants, model, permissionMode, etc.) but contains no messages array — the file only has session config, never message content.

$ jq 'keys' local_482754cc-...json
[ "alwaysAllowedReasons", "branch", "chromePermissionMode", "createdAt",
  "cwd", "effort", "enabledMcpTools", "isArchived", "lastActivityAt",
  "model", "originCwd", "permissionMode", "remoteMcpServersConfig",
  "sessionId", "sessionPermissionUpdates", "sourceBranch", "title",
  "worktreeName", "worktreePath" ]

The cwd of one zombie pointed at /Users/<user>/Open-Jarvis/.claude/worktrees/nifty-austin — a directory that no longer exists on disk. The session can never be resumed meaningfully, yet the entry stays in Recents.

Suggested fix

Don't persist the local_*.json until the first user message is committed. Hold it in memory only. On window close before any message: discard.

Alternative (less invasive): keep current behavior but auto-delete any local_*.json that has zero messages AND lastActivityAt - createdAt < N seconds AND createdAt > 1 hour ago. Same logic could run on app startup.

Current local workaround

Built a launchd agent that scans ~/Library/Application Support/Claude/claude-code-sessions/**/local_*.json every 5 minutes and moves zombies (lifetime < 30s AND age > 1h) to a .trash-zombies-<date>/ sibling directory. Reversible. Detection criteria are conservative — even a fast \"what is X?\" prompt takes >10s including response.

Logic in shell pseudo-code:

for f in claude-code-sessions/**/local_*.json; do
  created=$(jq '.createdAt' "$f")
  last_act=$(jq '.lastActivityAt' "$f")
  lifetime=$((last_act - created))
  age=$(( $(date +%s)*1000 - created ))
  if [ $lifetime -lt 30000 ] && [ $age -gt 3600000 ]; then
    mv "$f" .trash-zombies-$(date +%Y%m%d-%H%M%S)/
  fi
done

Happy to share the full plist/script if useful.

Environment

  • macOS (Apple Silicon)
  • Claude desktop app: latest (2026-05-14)
  • Claude Code CLI: 2.1.141
  • Sessions affected: 4/26 (~15%) on my machine, accumulated over ~6 weeks

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗