[FEATURE] surface live context % in claude agents pane (statusLine / hook)
Preflight Checklist
- [x] Searched existing requests — none match
- [x] Single feature request
Problem Statement
i use a custom statusLine command that writes per-pane ctx% / 5h% / 7d% to a sidecar file, and a tmux HUD reads from it. its the single most useful signal i have for catching compaction risk during long sessions before it fires.
works fine for normal claude invocations. but theres no path to get the same data inside a claude agents pane:
- statusLine never fires for the pane (neither for the orchestrator picker nor when a sub-chat is focused)
- the focused sub-chats are backgrounded by the daemon (
claude --bg-pty-host/--bg-spare), so their process tree roots at launchd. no tmux ancestor anywhere in the chain - the only tmux-attached process is the agents picker itself, which fires
SessionStartonce and then nothing per-turn
i verified this empirically with a probe hook that logged session_id, transcript_path, $TMUX_PANE, and the full PPID chain for every hook event. confirmed the topology split: the process with pane context fires only SessionStart, the processes with per-turn hooks have no pane context.
Proposed Solution
any of these would solve it (in order of preference):
- fire
statusLinein the agents-view pane on each focused-session turn — simplest, matches the existing per-pane contract. JSON payload already has everything needed. - expose the currently-focused
session_idvia env var or sidecar file owned by the picker process — i can do the rest myself (readtranscript_path, scrape usage). env var on the picker process is fine; a/tmp/.claude_agents_focus_<picker_pid>.jsonfile would also work. - fire a hook event when focus changes inside agents-view — same data, different shape. would let me write the sidecar from hook context.
Alternative Solutions
- tried a per-turn hook (
UserPromptSubmit/PostToolUse) thinking i could walk up to the tmux pane from the hooks pid — process tree roots at launchd via--bg-pty-host, no tmux ever reachable - considered a "most recent activity globally within N seconds" heuristic across all live sessions, but fragile if multiple sessions are concurrently active
- current workaround is rendering blank ctx% in agents-view panes (honest "i cant tell" beats confidently-wrong, but loses the signal)
Priority
Medium - Would be very helpful
Feature Category
Interactive mode (TUI)
Use Case Example
- tmux pane running
claude agents - drill into a sub-chat with right-arrow, work through a long task
- context window fills up; HUD ideally shows ctx% creeping up so i can compact before forced compaction fires
- today: HUD column is blank in this pane, no way to see compaction risk approaching
- with any of the proposals above: HUD updates per turn, same as a normal
claudepane
Additional Context
CC 2.x is iterating agents-view actively — happy to test patches behind a feature flag if helpful. the statusLine contract is already well-documented; option 1 is probably a few-line change in whichever process owns the agents-view pane render loop.
3 Comments
Thanks for using Claude — and especially for pushing on advanced workflows like this. The tmux/HUD integration pattern is genuinely clever, and the context-pressure visibility problem you’re solving is exactly the kind of operational signal that becomes critical in long-running agent sessions.
This matches my understanding of how Agents is currently wired.
In a normal
claudesession,statusLineand turn hooks execute in the foreground process tree attached to the tmux pane, so deriving pane identity is straightforward. In Agents mode, the actual conversational workers are detached behind the background PTY host (claude --bg-pty-host/--bg-spare), and the visible tmux-attached process is effectively just the orchestrator UI. Once the agent sessions are daemonized, there’s no stable ancestry path back to the originating pane, so hooks lose all pane locality.I verified the same behavior on my side:
statusLinenever fires for focused agent sub-sessionsSo today there’s effectively no supported mechanism for:
I strongly agree this is a gap. Context pressure telemetry is materially more important in long-running agent workflows than in single sessions, because compaction becomes both more frequent and less visible.
Of the options you listed, I think these make the most sense architecturally:
statusLinefor the currently focused agent session inside the agents-view panesession_idfrom the picker/orchestrator process{previous_session, current_session}payloadsOne additional shape that could work well:
~/.claude/agents/events.sockThat would make external HUDs and integrations dramatically easier without coupling tooling to internal process topology.
As a workaround today, the only semi-viable approach I found was polling the orchestrator TUI state indirectly (screen scraping / tty capture), but that’s brittle and loses the nice hook-based model entirely.
I’d definitely be happy to test patches or prototype integrations if you expose even a minimal focus signal from the agents-view parent process.
The process-tree topology issue you're running into is real -- the background PTY daemon that hosts sub-chat workers has no tmux ancestor, so there is no reliable path to correlate a hook event back to a pane. The PPID chain really does dead-end at launchd.
Of the three options you proposed, option 2 (expose focused session_id from the picker process) is probably the easiest to wire at the tooling layer today, even before a native fix ships:
If the agents picker process writes its own PID to a known path on start (
~/.claude/agents/picker.pidor similar), external tooling can uselsoforproc_infoto find which TTY that process is attached to, and correlate from there. Fragile, but it works on macOS wherelsof -pis reliable.A slightly more robust interim approach: a wrapper script that starts
claude agentsand before exec writes its own PID and$TMUX_PANEto a sidecar file. The hook probe you already wrote (logging PPID chains) has everything needed to close the loop -- the hook runs in the daemon process, the sidecar has the picker PID, and you can do a one-time "is the daemon a descendant of the picker?" walk at hook invocation time.The
statusLinegap in agents view is distinct from the hook scope issue and worth tracking separately. The problem is thatstatusLinefires on the per-turn hook in the conversational worker (daemon process, no pane), not in the picker process (has pane, fires only SessionStart). A minimal fix would be: when the picker process receives a per-turn event from the focused worker, re-firestatusLinein the picker's own process context. That keeps the existing contract without needing to expose a new API surface.For what it's worth: running context pressure as a metric in an external monitoring layer (polling session JSONL files for cumulative token counts) has been a workable fallback for catching compaction risk, but the latency is 5-10s per poll interval versus the per-turn freshness you'd get from a native
statusLinefix. Not the same thing, but it's something until the daemon/picker topology gets cleaner telemetry routing.Thanks, this is genuinely useful. The confirmation that the PPID chain dead-ends at launchd is worth a lot on its own, bc I'd been assuming I was holding it wrong and there was some ancestor I just hadn't found.
Your
statusLinere-fire suggestion is a sharper version of my option 1, and I want to call that out specifically. I'd framed it as "firestatusLinein the agents-view pane," which quietly assumes the pane-owning process can see the focused worker's per-turn events. Framing it as "when the picker receives a per-turn event from the focused worker, re-firestatusLinein the picker's own process context" keeps the existing contract intact and needs no new API surface. That's the one I'd want.On the sidecar, I'll build the wrapper-script variant, bc it removes the
lsofguesswork. I already have$TMUX_PANEat picker start, so writing pane and PID before exec is close to free, and the probe hook I wrote for this report already walks the PPID chain, so the descendant check is a small addition on top. The part I'm less sure about is multiple concurrentclaude agentspanes, which is my actual setup: two pickers means two sidecars, and the hook has to pick the right one. A descendant walk should disambiguate correctly since the daemons really are parented differently, but I'll find out.The JSONL polling fallback is the piece I dismissed too early. I'd written it off on freshness grounds, but you're right that 5-10s is fine for what I actually care about, which is noticing compaction risk while there's still room to act rather than watching the number tick. That's a much weaker requirement than per-turn, and it works today, so I'll probably run it while the sidecar gets built. Beats the blank column I have now.
Happy to keep the
statusLinegap on this issue and split the hook-scope topology into a separate one if that's cleaner to track. The offer to test a patch behind a flag stands.