Feature request: built-in, cross-platform way to list running Claude Code sessions and their state
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:
- Find
claudeprocesses viapgrep -x claude. - Wire
SessionStart,Stop,UserPromptSubmit,Notification, andSessionEndhooks in~/.claude/settings.jsonthat each write/clear a small JSON status file persession_idunder~/.local/state/claude-sessions/. - Match each status file back to the process that owns it by walking
/proc/<pid>/statparent links from the hook's own$PPIDupward until a process namedclaudeis found. - 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
/procsemantics. - It's not portable at all — macOS has no
/proc, so step 3 (matching a hook payload'ssession_idback 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
Bashtool call started withrun_in_background: true) from outside the process. Neither approach I tried worked: the task does not appear as a descendant of theclaudeprocess in the OS process tree (likely due to sandboxing), andTaskCreated/TaskCompletedhooks (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 statuscommand 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)
Showing cached comments. Read the full discussion on GitHub ↗
4 Comments
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:
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" />
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_sessionsAPI already exposingisRunning— 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).
One more concrete pain point worth calling out separately: detecting whether a session has an active background task (a
Bashtool call started withrun_in_background: true) is also not observable externally today, and I tried two different approaches before giving up:pstreeunder the session'sclaudePID): unreliable in both directions.sleep 30 &,run_in_background: true) did not show up as a descendant of theclaudePID at all while it was running — most likely because of how the sandbox reparents/tracks it.TaskCreated/TaskCompletedhooks: 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 ~6srun_in_backgroundBash 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/backgroundTaskCountfield per session), that would fully close this gap as well.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 --jsonwithstatusandwaitingFor. 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:
busy/waiting/idlestate and optionalwaitingFor;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 --jsonwith 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.