Summary
A session that is held as a background agent in the Claude Code daemon cannot be recovered with claude --resume <session-id>. The command refuses with a single terse line and no takeover path:
Session <id> is currently running as a background agent (bg). Use `claude agents` to find and attach to it, or add --fork-session to branch off a copy.
If the client that originally backgrounded the agent loses track of the session id (or — as in my case, via a third-party multiplexer — binds its panel to a different, empty session id), the user is effectively stranded from their own conversation:
--resume <real-id> → refused (held as a bg agent).
--resume <the-id-the-UI-showed-me> → No conversation found (that id is empty).
- The only recovery is the interactive
claude agents picker, or --fork-session, which creates a divergent copy rather than reclaiming the original.
The on-disk transcript is fully intact the whole time — no data is lost — the issue is purely recoverability: there is no clean, scriptable way to foreground/reclaim a backgrounded session by id.
Environment
- Claude Code: 2.1.177
- OS: macOS (Darwin 25.5.0), Apple Silicon
- Install: Homebrew (
/opt/homebrew)
- The session was backgrounded through the daemon by a third-party app (cmux 0.64.16) that runs Claude sessions as background agents. (A separate report is going to that project for its part; this report is specifically about Claude Code's resume behavior, which reproduces from a plain terminal independent of the wrapper.)
Reproduction
- A Claude session becomes a background agent in the daemon and settles into
status: idle, state: blocked.
- From any terminal:
claude --resume <that-session-id> → terse refusal (above).
claude agents --json --all confirms it is alive and held:
{"id":"<id>","kind":"background","sessionId":"<id>",
"name":"resume-background-agent","status":"idle","state":"blocked","pid":<pid>}
- The transcript at
~/.claude/projects/<project>/<id>.jsonl is complete and current — nothing was lost; it just can't be resumed in place.
Daemon log
~/.claude/daemon.log shows the session claimed and never released, then only periodic spare reaping — i.e. the claim persists indefinitely:
[bg] bg claimed-spare <id> (slash)
[bg] bg orphan-spare reap: 1
[bg] bg orphan-spare reap: 1
...
Expected / requests
claude --resume <id> against a held bg agent should offer to take it over / foreground it (Take over this background agent? [y/N]) instead of only refusing — reattach-from-resume, without forcing a separate command.
- If the controlling client has died/detached, detect the stale claim and let
--resume reclaim the session cleanly.
- Surface a human-readable identifier in both the refusal message and
claude agents so a user can find the right session when an external UI lost the id. (In claude agents --json, nearly every entry had title: null.)
Impact
A backgrounded planning session was unreachable for ~2 hours across terminal restarts. The conversation was never lost on disk, but there was no smooth path back to it — --fork-session (a divergent copy) was the only reliable recovery. For users driving Claude through any wrapper that backgrounds sessions, a lost/мismatched id makes the original conversation feel permanently gone even though it's intact.
Summary
A session that is held as a background agent in the Claude Code daemon cannot be recovered with
claude --resume <session-id>. The command refuses with a single terse line and no takeover path:If the client that originally backgrounded the agent loses track of the session id (or — as in my case, via a third-party multiplexer — binds its panel to a different, empty session id), the user is effectively stranded from their own conversation:
--resume <real-id>→ refused (held as a bg agent).--resume <the-id-the-UI-showed-me>→No conversation found(that id is empty).claude agentspicker, or--fork-session, which creates a divergent copy rather than reclaiming the original.The on-disk transcript is fully intact the whole time — no data is lost — the issue is purely recoverability: there is no clean, scriptable way to foreground/reclaim a backgrounded session by id.
Environment
/opt/homebrew)Reproduction
status: idle, state: blocked.claude --resume <that-session-id>→ terse refusal (above).claude agents --json --allconfirms it is alive and held:{"id":"<id>","kind":"background","sessionId":"<id>", "name":"resume-background-agent","status":"idle","state":"blocked","pid":<pid>}~/.claude/projects/<project>/<id>.jsonlis complete and current — nothing was lost; it just can't be resumed in place.Daemon log
~/.claude/daemon.logshows the session claimed and never released, then only periodic spare reaping — i.e. the claim persists indefinitely:Expected / requests
claude --resume <id>against a held bg agent should offer to take it over / foreground it (Take over this background agent? [y/N]) instead of only refusing — reattach-from-resume, without forcing a separate command.--resumereclaim the session cleanly.claude agentsso a user can find the right session when an external UI lost the id. (Inclaude agents --json, nearly every entry hadtitle: null.)Impact
A backgrounded planning session was unreachable for ~2 hours across terminal restarts. The conversation was never lost on disk, but there was no smooth path back to it —
--fork-session(a divergent copy) was the only reliable recovery. For users driving Claude through any wrapper that backgrounds sessions, a lost/мismatched id makes the original conversation feel permanently gone even though it's intact.