Feature request: built-in, cross-platform way to list running Claude Code sessions and their state

Status Open
Reported on v2.1.273
Maintainer reply None cached
Activity 7 comments · opened Sep 16, 2026

Summary

There's no built-in, documented way for an external process to answer: "what Claude Code sessions are currently running on this machine, and for each one, is it actively working, idle and ready for a new prompt, or blocked waiting on me (permission prompt, idle notification, elicitation, etc.)?"

Motivation

This is useful for any external monitoring surface: a menu bar / system tray app, a dock widget, a tmux/shell status line, a dashboard, etc. I ran into this building a KDE Plasma widget that lists my running claude sessions with a traffic-light state (ready / running / waiting for input), and I suspect this is a broadly useful capability beyond that one use case.

Current workaround and its limitations

Without an official API, the only way I found to approximate this is:

  1. Find claude processes via pgrep -x claude.
  2. Wire SessionStart, Stop, UserPromptSubmit, Notification, and SessionEnd hooks in ~/.claude/settings.json that each write/clear a small JSON status file per session_id under ~/.local/state/claude-sessions/.
  3. Match each status file back to the process that owns it by walking /proc/<pid>/stat parent links from the hook's own $PPID upward until a process named claude is found.
  4. Fall back to a CPU-activity heuristic (sampling CPU ticks of the process and its whole descendant tree) for any session whose hooks haven't fired yet.

This mostly works on Linux, but:

  • It's fragile — the whole thing depends on hooks firing reliably and on /proc semantics.
  • It's not portable at all — macOS has no /proc, so step 3 (matching a hook payload's session_id back to the OS process that owns it) has no equivalent there. Anyone wanting to build the same kind of tool on macOS is currently stuck.
  • Relatedly, I also tried to detect whether a session has an active background task (a Bash tool call started with run_in_background: true) from outside the process. Neither approach I tried worked: the task does not appear as a descendant of the claude process in the OS process tree (likely due to sandboxing), and TaskCreated/TaskCompleted hooks (both present as literal hook event names in the CLI binary) did not fire for a real background task's start or completion when I wired them up and tested live.

Proposed solution

A built-in, documented, cross-platform way to enumerate active Claude Code sessions and query each one's current state — for example:

  • A claude sessions list / claude sessions status command with JSON output, and/or
  • A local socket/API, and/or
  • A status directory/file the CLI itself maintains (so external tools don't need to reconstruct it via hooks).

At minimum this should expose, per session: a stable identifier, the working directory, and a state covering at least running, ready for a new prompt, and waiting on the user (permission prompt / idle timeout / elicitation). Whether it has an active background task would be a nice addition on top.

This would remove the need for the hooks + process-tree heuristics above entirely, and would work the same way on macOS, Linux, and Windows/WSL.

Environment

  • Claude Code version: 2.1.273
  • OS tested: Linux (Debian sid)

View original on GitHub ↗

4 Comments

asyd · 29 days ago

For context, here's a screenshot of the KDE Plasma widget I built as a workaround (see attached image). It lists each running claude session with a simple traffic-light state:

  • 🟢 green — ready, idle, waiting for a new prompt
  • 🟠 orange — actively running
  • 🔴 red — waiting on me (permission prompt / idle notification)

This is exactly the kind of thing that becomes trivial with a built-in claude sessions list/API, and fragile without one — the hooks + /proc-walking + CPU-heuristic combo described above is the only way I found to get this on Linux, and it doesn't translate to macOS at all. Happy to share the widget's source if useful as a reference for what "good enough" output would look like.

<img width="490" height="511" alt="Image" src="https://github.com/user-attachments/assets/1002a70d-0bc8-4d11-ba5f-d664a7f72b38" />

asyd · 29 days ago

Related: #88511 requests essentially the same three-state model (running / waiting for input / idle), scoped to the Desktop app's "Recents" list UI rather than an external/CLI interface. Worth noting the reporter there mentions an internal list_sessions API already exposing isRunning — suggesting at least part of this data already exists internally, it's just not exposed to external tools/processes.

Also related, narrower in scope: #90775 (CLI/machine-readable session list, focused on Remote Control reconnection), #76089 and #78595 (same need in the VS Code extension sidebar), #94374 (Desktop: see status of many sessions at once).

asyd · 29 days ago

One more concrete pain point worth calling out separately: detecting whether a session has an active background task (a Bash tool call started with run_in_background: true) is also not observable externally today, and I tried two different approaches before giving up:

  1. Process tree inspection (pstree under the session's claude PID): unreliable in both directions.
  • False positive: a persistent MCP server child process is present for the entire life of the session, so "does this PID have child processes" doesn't distinguish idle from busy.
  • False negative: a real backgrounded task (sleep 30 &, run_in_background: true) did not show up as a descendant of the claude PID at all while it was running — most likely because of how the sandbox reparents/tracks it.
  1. TaskCreated / TaskCompleted hooks: both are present as literal event-name strings in the installed binary (2.1.273), so I wired them up in ~/.claude/settings.json (no matcher) expecting them to fire for background task start/finish. I then ran a real ~6s run_in_background Bash command in a live session — neither hook fired.

So today there is no reliable way, from outside the process, to know "is this session currently running something in the background." If the proposed session-state API/CLI from the issue description above ends up covering this too (e.g. a hasActiveBackgroundTask / backgroundTaskCount field per session), that would fully close this gap as well.

ekusiadadus · 29 days ago

I'm integrating session status into TTYbird on macOS. The useful distinction here is ordinary interactive sessions versus background sessions.

The current agent-view docs already document claude agents --json with status and waitingFor. However, the same page explicitly says interactive sessions open in other terminals do not appear until backgrounded. That leaves a gap for a read-only dashboard that discovers sessions people launched normally, without changing their workflow.

For those sessions, our fallback correlates process identity, open transcript descriptors, and optional hooks. Those are observations at different times, not an authoritative current-state query. We also found and are fixing a stale-hook precedence bug in our collector; that is not evidence of a Claude Code hook defect.

A minimal supported record for all live interactive/background sessions would help:

  • stable session ID and session kind;
  • PID plus process-start identity, to distinguish restart/PID reuse;
  • current busy / waiting / idle state and optional waitingFor;
  • observation timestamp or sequence, with explicit unavailable/stale semantics.

No previews, prompts, turns, tool arguments, or credentials are needed. A read-only query should not resume/background a session or subscribe the caller to conversation/approval handling. Extending claude agents --json with an opt-in interactive-session scope would let consumers use one documented interface.

This is based on the current documented scope and integration review (installed CLI 2.1.272), not a claim that I reproduced a new upstream hook failure. Adding these requirements here rather than filing a duplicate.

Showing cached comments. Read the full discussion on GitHub ↗