Desktop app: isRunning: false conflates "idle", "not observable", and "gone" -- and VS Code sessions are absent from the listing entirely
Environment: Windows 11, Claude desktop app + VS Code sessions, multi-session workflow (many parallel sessions sharing one git repo)
Summary
isRunning: false from list_sessions / get_session conflates three materially different states, and there is no field that distinguishes them:
- the session is idle (alive, between turns, will receive a message)
- the session is not observable by the desktop app (alive, but absent from its session map)
- the session is gone
Because the field is named isRunning, readers reasonably interpret false as (3) or at best (1). In a multi-session workflow that inference is load-bearing and it is wrong often enough to cause real errors.
Measured
A session that had been actively exchanging messages was queried while demonstrably alive:
isArchived : false
isRunning : false
lastActivityAt : 2 minutes before the query
It answered a message immediately afterward. Three instruments were consulted; the two named for liveness both returned something that reads as "not alive", and the only field that actually answered the question was lastActivityAt — which is not surfaced as a liveness verdict anywhere.
The harder case: sessions absent from the map entirely
VS Code sessions do not appear in the desktop app's session list at all. For those, no value of isRunning describes them — they are absent, not listed-and-quiet. A reader told "false means idle" will expect a row that does not exist, conclude no such session is running, and act on it.
Observed impact
In a workflow where multiple sessions coordinate over a shared repository:
- A session read
isRunning: falsefor its peers, concluded none were live, and skipped announcing its work to all of them — then found the peers had been active throughout. - The same read is one inference away from a destructive action: several coordination schemes let a session reclaim another's resource lock/claim if the holder is believed gone.
isRunning: falseis the natural evidence for "gone", and it is not evidence of that. - Two independent sessions made the same wrong inference from the same field on the same day.
The general failure: two instruments disagree, and isRunning: false is the one that lets the reader stop looking.
Expected behavior
Any of these would resolve it; the first is cheapest:
- Document the semantics — state plainly that
falsemeans "not currently executing a turn as far as this surface can see", that it is not evidence the session has ended, and that sessions may be absent from the listing entirely. - Rename or split the field — e.g.
executionState: running | idle | unknown, so "I cannot see it" is representable. - Surface a liveness verdict derived from
lastActivityAt, which is currently the only reliable signal and requires each caller to invent its own threshold.
Workaround
Read lastActivityAt and treat recency as the liveness signal; treat isRunning: false as carrying no information about whether a session is alive. send_message does deliver to sessions reporting false.
Related but distinct
#80885 also reports isRunning: false on sessions that are still alive, but there the field is a symptom of scheduled-task sessions leaking orphaned OS processes. This report is about the field's semantics for ordinary interactive sessions, and about sessions that never appear in the listing at all — no process leak involved.
#72720 is the inverse symptom (stuck showing RUNNING while idle), which suggests the underlying state tracking is unreliable in both directions.
Showing cached comments. Read the full discussion on GitHub ↗
3 Comments
Still relevant.
isRunning: falsestill collapses three states that call for opposite responses: idle and reachable, alive but not observable by the desktop app, and gone.The practical cost is that the field reads backwards as a reachability signal. An idle session that would answer a message reports
false; a session mid-turn that will queue reportstrue. Anyone building on it has to learn that by measurement, because nothing in the field name or the docs says so.#82313 covers the other half, VS Code sessions being absent from the listing entirely. Both are cases of a session listing returning a confident answer that silently omits categories.
Still open. The measurement I would point a maintainer at is this one: a session that had been actively exchanging messages reported
isRunning: falsewithlastActivityAttwo minutes before the query, and answered a message immediately afterward. Both fields named for liveness returned something that reads as not alive. The only field that answered the question waslastActivityAt, which is not surfaced as a liveness verdict anywhere.The field conflates three materially different states with no way to tell them apart: idle, not observable by the desktop app, and gone. Because it is named
isRunning, a reader reasonably takesfalseas gone. In a multi-session workflow that inference is load-bearing.The harder case is the second half, and #82313 covers the cause. A VS Code session is absent from the map entirely, so no value of
isRunningdescribes it. A reader told "false means idle" will expect a row that is not there.Still open. The opposite case, #72720, where a session showed RUNNING while idle, was closed as completed in August. This issue is the other direction on the same field:
falsefor a session that is alive and answers messages.#80885, from another user, adds a third shape: scheduled-task sessions that report
isRunning: falsewhile their background processes are still alive. Sofalsecurrently covers idle, not observable, gone, and orphaned-but-running. A field that separates those states would let tools act on it.