Bug: /resume does not update sessions/{pid}.json sessionId
Summary
When using /resume inside an already-running Claude Code session to switch to a different conversation, the ~/.claude/sessions/{pid}.json file is not updated with the new session ID. This causes external tools and hooks to have an incorrect view of which session a process is operating on.
Steps to Reproduce
- Open Window A, start Claude Code → creates session SA, writes
sessions/{pidA}.jsonwithsessionId: SA - Open Window B, start Claude Code → creates session SB, writes
sessions/{pidB}.jsonwithsessionId: SB - In Window B, type
/resumeand select session SA - Inspect
sessions/{pidB}.json→ still showssessionId: SBinstead ofSA
Impact
This causes JSONL message chain forks. Since sessions/{pid}.json doesn't reflect the actual session being operated on:
- Two Claude Code processes can silently operate on the same session simultaneously
- The JSONL file develops forked message chains (two children with the same
parentUuid, both withisSidechain: false) claude --resumelater only follows one branch of the fork, losing messages from the other branchSessionStarthooks cannot reliably detect and prevent duplicate processes on the same session
Evidence
The JSONL uses uuid + parentUuid to form a message chain (tree structure). When two processes write to the same JSONL, fork points appear:
# Same parentUuid referenced by two different children = fork
$ jq -r '.parentUuid' session.jsonl | sort | uniq -c | sort -rn | head
2 dc26f80c-bbda-409a-8a8c-5d65bfb2bd5b
2 939c92b3-8870-4b35-99bd-339e045fb176
2 897833f0-d882-4422-8473-b3ad1a3263d5
...
We observed 6 fork points in a real session where a second process resumed the same conversation.
Expected Behavior
When /resume switches to a different session, update ~/.claude/sessions/{pid}.json to reflect the new sessionId. This would allow:
- External tools to correctly identify which session a process is operating on
SessionStarthooks to detect and prevent concurrent access to the same session- Prevention of silent JSONL message chain forks
Workaround
Currently, users must manually /exit the original session before resuming it from another window or tool. A SessionStart hook can detect and kill conflicting processes, but only for claude --resume from the shell — not for /resume within an existing session, because the session file is stale.
Environment
- Claude Code version: 2.1.81
- OS: macOS (Darwin 25.3.0)
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗