/exit backgrounds a plain (non-worktree) session instead of quitting, and a session that settled as `killed` is re-claimed under the same id, blocking `claude -r` indefinitely

Status Open
Reported on v2.1.257
Maintainer reply None cached
Activity 1 comment · opened Sep 4, 2026

Environment: Claude Code v2.1.260, macOS (Darwin 25.5.0), zsh, plain interactive session (no --worktree, no --bg)

Summary

Two linked defects, both observed on one machine with daemon logs to back them up:

  1. /exit in an ordinary interactive session backgrounds the conversation instead of quitting. A second /exit actually quits.
  2. A background session that has already settled as killed gets re-claimed under the same short id ~83 seconds later with origin fleet, and the resurrected worker is never reaped. It sits in status: busy, state: blocked indefinitely and permanently blocks claude -r.

This is related to but distinct from two existing issues:

  • #82192 reports /exit backgrounding instead of quitting, but scoped to --worktree sessions. This report has no worktree involved, so the behavior is broader than that issue describes.
  • #90039 reports the daemon endlessly respawning a worker for a job in state done that has already disappeared from claude agents --json. Here the job settled as killed, was re-claimed exactly once (not a loop), and is still listed by claude agents --json. Different state and different failure shape, though possibly the same underlying supervision bug.

Symptom

Typing /exit does not exit — the conversation moves to the background. Typing /exit again exits. Afterwards claude -r refuses to resume:

That session is still running as a background session (13a913ca).

Run claude attach 13a913ca to open it, or claude stop 13a913ca first to resume it here.

To branch off a copy instead, run:
 claude --resume <session-uuid> --fork-session

The resurrection, from ~/.claude/daemon.log

[2026-09-02T22:39:41.462Z] [bg] bg spawned       13a913ca (slash)
[2026-09-02T22:40:18.316Z] [bg] bg settled       13a913ca (killed)
[2026-09-02T22:41:41.092Z] [bg] bg claimed-spare 13a913ca (fleet)   <-- 83s after it was killed
[2026-09-02T22:41:41.095Z] [bg] bg spare spawned host pid=57909

The second /exit did work — the session settled as killed. Then the same short id re-claimed a fresh spare worker 83 seconds later, with origin fleet rather than slash.

The identical pattern hit a second id in the same minute, but that one was killed again two minutes later and did not persist:

[2026-09-02T22:39:33.757Z] [bg] bg spawned       b9e1335f (slash)
[2026-09-02T22:40:16.564Z] [bg] bg settled       b9e1335f (killed)
[2026-09-02T22:40:26.699Z] [bg] bg claimed-spare b9e1335f (fleet)
[2026-09-02T22:42:26.918Z] [bg] bg settled       b9e1335f (killed)

State of the orphan, 1 day 20 hours later

claude agents --json:

{
  "pid": 57495,
  "id": "13a913ca",
  "cwd": "<redacted project dir>",
  "kind": "background",
  "startedAt": 1788388901353,
  "sessionId": "<redacted uuid>",
  "name": "<redacted>",
  "status": "busy",
  "state": "blocked"
}

ps -o pid,stat,etime,command -p 57495:

  PID STAT     ELAPSED COMMAND
57495 SNs+ 01-19:52:44 claude bg-spare --bg-spare /tmp/cc-daemon-501/<daemon>/spare/a3900b8e.claim.sock

Note the argv still reads bg-spare — the process was launched as a pool spare and adopted the session via its claim socket, so it never re-execed. Its rendezvous socket /tmp/cc-daemon-501/<daemon>/rv/13a913ca.sock still exists, and the matching a3900b8e.claim.sock is gone from the spare directory, consistent with the claim having happened.

The session has been state: blocked for the entire 1d20h and nothing ever retired it. The daemon does reap idle unclaimed spares in the same log:

[2026-09-02T23:40:33.610Z] [bg] bg retire b016850b: stale-spare, idle 61m
[2026-09-02T23:40:33.686Z] [bg] bg settled b016850b (done)

but no equivalent reap ever fires for a claimed-and-blocked session.

Steps to reproduce

  1. Start an ordinary interactive session: claude (no flags).
  2. Type /exit. The conversation is backgrounded rather than exited.
  3. Type /exit again. It exits, and the daemon log records bg settled <id> (killed).
  4. Run claude -r in the same directory. It refuses, naming the background session id.
  5. claude agents --json shows the id alive again as kind: background, status: busy, state: blocked; ~/.claude/daemon.log shows a bg claimed-spare <same id> (fleet) line dated after the killed line.

Expected behavior

  • /exit should quit on the first invocation in an ordinary session, not background the conversation. If backgrounding is ever intentional, it should say so explicitly.
  • A session that has settled as killed must not be re-claimed under the same id afterwards.
  • A background session sitting in state: blocked should be subject to the same idle reaping that unclaimed spares already get, rather than surviving indefinitely and blocking claude -r.

Workaround

claude stop <id> (conversation is kept) or claude rm <id>, after which claude -r works again.

Environment notes

All five bg spawned events in this daemon log carry origin (slash); none carry a /bg-specific origin, so on this machine backgrounding was initiated by a slash command in every observed case.

Three of those five bg spawned (slash) events occur within ~0.2s of a bg: control socket bound line, i.e. the daemon binding its control socket immediately beforehand. The ordering is consistently bind-then-spawn, which looks like the daemon being started on demand to host the backgrounded session rather than the daemon restart causing the backgrounding. Noting the correlation in case it is useful; I am not claiming a direction of causation.

This machine had three native auto-updates in three days (2.1.257 -> .258 -> .259 -> .260), including one that replaced the binary mid-session about five minutes before the events above, despite autoUpdates: false in ~/.claude.json. #90039 raised version skew between a long-lived daemon and newer worker binaries as a suspected cause for its own symptom, so the churn may be relevant here too. The ignored autoUpdates: false setting is a separate bug and is not what this issue is about.

~/.claude/settings.json on this machine contains "env": { "CLAUDE_AFK_TIMEOUT_MS": "2147483647" }. The user did not set this and its origin could not be determined from available logs — it is already present in a tool result from 2026-08-21. Mentioned only because it makes this environment differ from a default install; I have no evidence it relates to the failure.

View original on GitHub ↗

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