You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I confirm this is a reproducible bug, not a feature request, idea, question, contribution proposal, or direction check.
I reproduced this bug on the version and environment reported below using the exact steps provided.
Current behavior
For a Claude Code pane that is in the middle of a turn, herdr agent explain and herdr agent list / pane get disagree. The detection engine classifies the pane as working, but the reported agent_status stays idle.
Same pane, same second:
$ herdr agent explain wF:p9 --verbose
agent: claude
state: working
manifest: remote:.../claude.toml 2026.09.11.1
rule: live_turn_working (region=bottom_non_empty_lines(12) priority=970)
visible: idle=false blocker=false working=true
$ herdr pane get wF:p9
agent: claude
agent_status: idle
agent_session.source: herdr:claude
The divergence is stable, not a sampling race. I sampled both every 2s for 10s while the
pane kept producing output: explain returned working on every sample, list returned idle on every sample.
Two panes were genuinely in a turn at the time and both showed the split. The other 14
idle panes agreed between the two commands, so only the working transition is affected.
Expected behavior
agent list / pane get should report the state the detection engine computes, so the
sidebar, agent wait, and notifications match agent explain.
Reproduction
Start Claude Code in a Herdr pane and give it a task that runs for a while.
While the turn is running, run herdr agent explain <pane> --verbose — it reports state: working, matched rule live_turn_working, visible: working=true.
In the same second, run herdr pane get <pane> — agent_status is idle.
Repeat step 2 and 3 every 2 seconds. The split persists for the whole turn.
What I ruled out
Not a stale custom lifecycle source. I had a custom pane report-agent source on
these panes. I released it from all 16 panes (pane release-agent --source ... --agent claude)
and the split was unchanged. agent_session.source is herdr:claude.
Not a stale manifest.server reload-agent-manifests and server update-agent-manifests
both ran; claude manifest is 2026.09.11.1, remote_update_result: current,
no local override. Split unchanged after each.
Claude Code 2.1.269 sets the terminal title with a leading ✳ (U+2733 EIGHT SPOKED
ASTERISK). The regex only accepts U+2800–U+28FF (braille) and U+25D0–U+25D3 (half circles),
so U+2733 falls outside it. All 16 Claude panes on this machine have a title starting with
U+2733.
I am not claiming U+2733 by itself means "busy" — idle panes carry it too, since the field
holds the last title seen. But if the stored agent_status is driven by the OSC title path
while explain re-evaluates the full rule set on demand, a title rule that can never match
would explain why the stored state never leaves idle even though a lower-priority screen
rule matches. That is a hypothesis, not something I verified from the inside.
This looks like the same class as #2760, which extended the same rule for half-circle
spinner frames.
Impact
agent wait --until idle returns immediately for a pane that is still working, so
CLI-driven orchestration treats a dispatched task as finished the moment it is dispatched.
The sidebar shows the same wrong state, so there is no visual signal either. I worked around
it by having Claude Code's own UserPromptSubmit / Stop hooks write turn state to a file
and reading that instead, but that only helps callers who install that hook.
Herdr version: 0.9.0 (Homebrew), client and server both 0.9.0, protocol 22
Update channel (stable or preview): stable
Operating system: macOS 26.6.2 (arm64)
Terminal: Ghostty
Shell, if relevant: zsh
Relevant config, if any: Claude Code 2.1.269; Claude detection manifest 2026.09.11.1
(remote, no local override); Claude integration hook v9; CLAUDE_CODE_DISABLE_TERMINAL_TITLE=0
Is this a reproducible bug?
Current behavior
For a Claude Code pane that is in the middle of a turn,
herdr agent explainandherdr agent list/pane getdisagree. The detection engine classifies the pane asworking, but the reportedagent_statusstaysidle.Same pane, same second:
The divergence is stable, not a sampling race. I sampled both every 2s for 10s while the
pane kept producing output:
explainreturnedworkingon every sample,listreturnedidleon every sample.Two panes were genuinely in a turn at the time and both showed the split. The other 14
idle panes agreed between the two commands, so only the
workingtransition is affected.Expected behavior
agent list/pane getshould report the state the detection engine computes, so thesidebar,
agent wait, and notifications matchagent explain.Reproduction
herdr agent explain <pane> --verbose— it reportsstate: working, matched rulelive_turn_working,visible: working=true.herdr pane get <pane>—agent_statusisidle.What I ruled out
pane report-agentsource onthese panes. I released it from all 16 panes (
pane release-agent --source ... --agent claude)and the split was unchanged.
agent_session.sourceisherdr:claude.server reload-agent-manifestsandserver update-agent-manifestsboth ran; claude manifest is
2026.09.11.1,remote_update_result: current,no local override. Split unchanged after each.
CLAUDE_CODE_DISABLE_TERMINAL_TITLEis0here, terminal titles are enabled.done/seen semantics from What marks a pane seen, and do external reports take effect? #3912. The panes reportidle, notdone.Possibly related:
osc_title_workingnever matches on this setupexplain --verboseshowsosc_title_working(priority 1100) evaluating to ✗ on every pane:Claude Code 2.1.269 sets the terminal title with a leading
✳(U+2733 EIGHT SPOKEDASTERISK). The regex only accepts U+2800–U+28FF (braille) and U+25D0–U+25D3 (half circles),
so U+2733 falls outside it. All 16 Claude panes on this machine have a title starting with
U+2733.
I am not claiming U+2733 by itself means "busy" — idle panes carry it too, since the field
holds the last title seen. But if the stored
agent_statusis driven by the OSC title pathwhile
explainre-evaluates the full rule set on demand, a title rule that can never matchwould explain why the stored state never leaves
idleeven though a lower-priority screenrule matches. That is a hypothesis, not something I verified from the inside.
This looks like the same class as #2760, which extended the same rule for half-circle
spinner frames.
Impact
agent wait --until idlereturns immediately for a pane that is still working, soCLI-driven orchestration treats a dispatched task as finished the moment it is dispatched.
The sidebar shows the same wrong state, so there is no visual signal either. I worked around
it by having Claude Code's own
UserPromptSubmit/Stophooks write turn state to a fileand reading that instead, but that only helps callers who install that hook.
Related: #1630 (closed, different cause), #3414 (inverse direction), #3912 (external
reports), #2760 (same rule, spinner glyph coverage).
Environment
2026.09.11.1(remote, no local override); Claude integration hook v9;
CLAUDE_CODE_DISABLE_TERMINAL_TITLE=0