No in-session way to list tracked background shells (TaskList returns todos, not shells) → false "all clear"
Summary
There is no reliable in-session way for Claude (or the user) to enumerate the background shells the harness is tracking. The exit dialog clearly knows this list ("Background work is running" — with human-readable names like XLSR-53 F01 sweep (background)), but nothing surfaces it during the session:
TaskListreturns the todo task list, not background shells. It reportedNo tasks foundwhile three background shells were still running, so an emptyTaskListis easily (mis)read as "nothing is running."- The task IDs needed for
TaskStoponly appear in the one-off completion notification for each shell. If that notification has scrolled off or a context compaction happened, there is no command to re-list live shells and recover their IDs.
The practical failure mode: to answer the user's "is anything still running / did it all close?", the assistant falls back to a hand-written pgrep pattern over script names it happens to remember. That silently misses any job whose command doesn't match the guessed pattern, producing a confident but wrong "all clear." In my case a genuinely-hung job (sweep_ssl.py, stuck ~17h at model-load, 0.2% CPU) plus two orphaned until … pgrep … sleep watcher loops were still alive, but my pgrep filter (built from other script names) didn't cover sweep_ssl.py, so I reported everything closed. The exit dialog was right; my check was wrong.
Environment
- Claude Code
2.1.202 - Platform: Linux
- Non-interactive/agent shell
Steps to reproduce
- Start one or more long-running background shells (
run_in_background), e.g. a slow job plus anuntil ! pgrep -f "<thing>"; do sleep 5; donewatcher loop. - Let a context compaction occur (or simply lose the original completion notifications).
- Ask the assistant to verify whether background work is still running.
TaskList→No tasks found, even though the exit dialog lists live shells. There is no command that returns the same list the exit dialog uses (task ID + name + status).
Expected
A first-class way to list the harness-tracked background shells in-session — the same data the exit dialog renders — including each shell's task ID, display name, and running/exited status, so that:
- an empty result unambiguously means "no background work is running," and
- the returned IDs can be passed straight to
TaskStop.
Suggestions
- Have
TaskList(or/tasks) include background shells, not just todo tasks; or add a dedicated "list background shells" affordance. - Bonus: surface basic liveness (CPU%/last-output time) so a hung shell (sleeping at 0% CPU, e.g. a stalled model/network fetch) is distinguishable from an actively-running one.
- Doc note: clarify that
TaskListcovers todos, not background shells, so an emptyTaskListis not evidence that background work has stopped.
Workaround
Enumerate the user's own processes directly (ps -o pid,ppid,etime,%cpu,stat,args -u "$(id -un)") instead of grepping for remembered script names, and treat the exit dialog's list — not TaskList — as the source of truth.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗