Resume (--bg -r) forks a new session id but resumeSessionId points to itself — ancestry unrecoverable, listings show permanent duplicates
Summary
claude --bg -r <sessionId> resumes by forking: the continuation gets a new session id and the old session keeps its own row in claude agents --json --all. That's reasonable — but nothing on disk records the parent→child relationship, so no external tool (dashboards, fleet managers) can detect that the dead row was superseded by the live one. Listings accumulate permanent "duplicates": a dead ancestor next to its live continuation, usually under the same name.
The near-miss: jobs/<short>/state.json has a resumeSessionId field — but it points to the session's own id, not the parent it was resumed from.
Measured (2.1.245, Linux)
Session A = 7da51498-… (background, completed). Then:
claude --bg -r 7da51498-… "continue"
# => new session B = 88817c33-…
claude agents --json --alllists both A (status null) and B — permanently.jobs/88817c33*/state.json:sessionId = 88817c33-…,resumeSessionId = 88817c33-…(itself; same self-reference on every resumed session checked).- B's transcript (
projects/<dir>/88817c33-….jsonl): every copied record'ssessionIdfield is rewritten to B's id. A's id survives only inside message text — not machine-readable.
So ancestry is unrecoverable after the fact: heuristics (same name + cwd + timestamps) are the only option and they false-positive on fleets that reuse naming patterns.
Ask
Record the parent linkage at resume time — either:
- have
resumeSessionIdhold the resumed-from id (arguably what the name says), or - add a
resumedFromSessionIdfield to the jobs record and/or theagents --jsonrow.
One field would let tools mark dead ancestors as superseded (hide/collapse them) instead of showing every resume as a duplicate session forever.
Environment
- Claude Code 2.1.245, Linux (CachyOS), background sessions via
--bg