Desktop app: isRunning: false conflates "idle", "not observable", and "gone" -- and VS Code sessions are absent from the listing entirely

Status Open
Maintainer reply None cached
Activity 1 comment · opened Aug 7, 2026

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:

  1. the session is idle (alive, between turns, will receive a message)
  2. the session is not observable by the desktop app (alive, but absent from its session map)
  3. 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: false for 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: false is 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:

  1. Document the semantics — state plainly that false means "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.
  2. Rename or split the field — e.g. executionState: running | idle | unknown, so "I cannot see it" is representable.
  3. 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.

View original on GitHub ↗

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