Completed background-agent sessions can't be deleted from `claude agents` view on WSL2 (worker not reaped; daemon re-dispatches)
Summary
On WSL2, completed background-agent sessions cannot be deleted from the claude agents fleet view (Ctrl+X on a "Completed" session is a no-op). The delete works fine on native machines. Root cause is not the keybinding — Ctrl+X input reaches the app (it stops a running session correctly). The problem is a background-session lifecycle bug on WSL: a completed session's worker process is never reaped, and killing it causes the supervisor daemon to re-dispatch the session (re-runs the original prompt), so the view's delete has a live/self-resurrecting backend it can never remove.
Environment
- Claude Code: 2.1.204
- OS: WSL2 (Ubuntu),
Linux 6.6.114.1-microsoft-standard-WSL2 - Terminal: Windows Terminal
- Native binary is a proper Linux ELF (installed as
bin/claude.exe, butfileconfirms ELF x86-64)
Steps to reproduce
- Dispatch a background session:
claude --bg "reply 'done' and exit" - It reaches state done almost immediately (shows in
claude agentsunder Completed). - In the interactive
claude agentsview, select the completed session and press Ctrl+X to delete → nothing happens (no "ctrl+x again to delete" confirmation, no removal).
Expected
Ctrl+X on a completed session deletes it from the view (as it does on non-WSL machines).
Actual
The completed session stays in the list; Ctrl+X is a no-op on it. (Ctrl+X on a running session works — two presses stop it into "Completed" — so input delivery is fine.)
Root-cause evidence (reproduced)
For a session that is state: done (with firstTerminalAt set):
- Its worker process (
bg-pty-host … --session-id/--resume) stays alive indefinitely after completion (observed alive across repeated checks; never reaped). ~/.claude/daemon/roster.jsonkeeps the worker;claude agents --json --allstill lists it asdone.- Killing the worker PID → the supervisor daemon re-dispatches it, re-launching
claude.exe --session-id <uuid> "<original prompt>"(a fresh worker,attemptincrements). So the completed session self-resurrects. - The transient supervisor daemon (
daemon run --origin transient --spawned-by {…"claude agents"…}) frequently outlives its spawner (spawner PID already exited) and keeps resurrecting completed sessions as an orphan. claude stop <id>DOES work: it deregisters the session from the daemon (removed from roster, no re-dispatch). After that, only the leftoverdonejob/transcript records remain and the entry finally clears once those are removed.
This strongly suggests the fleet-view "delete" path relies on the worker terminating / daemon deregistration that never completes on WSL, whereas claude stop's control-protocol path succeeds.
Workaround (for other WSL users)
claude stop <id>to deregister + stop re-dispatch, then remove the leftover~/.claude/jobs/<id>/and~/.claude/projects/<proj>/<uuid>.jsonlrecords so it leaves the view.
Ask
- On WSL2, reap completed background workers, and make the fleet-view Ctrl+X "delete" use the same control path as
claude stopso it actually removes completed sessions.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗