Feature request: reliable session state detection API

Resolved 💬 5 comments Opened Mar 24, 2026 by MarcinDudekDev Closed Apr 23, 2026

Problem

There is no reliable way to programmatically detect whether a Claude Code session is idle, working, or waiting for input from outside the session.

Current workarounds and their limitations

1. Hook-based status tracking (Stop, UserPromptSubmit, Notification hooks writing to status files)

  • Tracks state transitions, not current state. If a transition is missed (restart, race condition, SessionEnd cleanup), the state is stuck until the next event fires.
  • SessionEnd hook must clean up, but then there's no record that the session existed at all — new sessions that --continue may not fire SessionStart reliably.
  • Status files become stale with no self-correction mechanism.

2. Tmux pane scraping (capturing pane content, looking for prompt, spinner characters, etc.)

  • Fragile: depends on TUI rendering details that can change between versions.
  • Point-in-time snapshot with race conditions.
  • Cannot distinguish all states (e.g., thinking with no visible spinner).

3. JSONL transcript file modification time

  • Only tells you when the file was last written, not what state the session is in now.
  • Undocumented internal format.

Real-world use case

We run 10-20+ concurrent Claude Code sessions in tmux, managed by an orchestration layer that:

  • Queues messages for sessions that are busy
  • Delivers messages when sessions become idle
  • Shows a dashboard with real-time status of all sessions
  • Announces via TTS when sessions finish work

We've spent months battling detection bugs across multiple fallback tiers. The fundamental issue is that Claude Code doesn't expose its internal state.

Proposed solution

A first-party mechanism to query the current state of a running Claude Code session. Some options:

Option A: Status file written by Claude Code itself
Claude Code writes/updates a well-known file (e.g., ~/.claude/sessions/<session-id>/status.json) with its current state: idle, working, waiting_for_permission, waiting_for_input. Updated atomically on every state change. Cleaned up on exit.

Option B: CLI query command

claude --status                    # current session in this terminal
claude --status --session <id>     # specific session
# Output: {"state": "idle", "session_id": "...", "uptime": 3600, ...}

Option C: Unix socket / IPC
Each running session exposes a socket at a well-known path that accepts simple state queries.

Option D: Enhanced hook data
Add a session_state field to all hook event payloads, and/or add a periodic heartbeat hook that fires every N seconds with current state.

Any of these would eliminate the need for fragile tmux scraping and stale-file workarounds.

Context

The Claude Code TUI already knows its own state internally (the statusline shows "Active...", "Running...", idle prompt, etc.). Exposing this externally would unlock reliable multi-session orchestration.

Related issues: #38015 (external interfaces for sessions), #37986 (statusLine refresh), #37629 (lifecycle hook gaps)

View original on GitHub ↗

This issue has 5 comments on GitHub. Read the full discussion on GitHub ↗