8000 Claude status update inconsistencies · Issue #151 · amirlehmam/wmux · GitHub
[go: up one dir, main page]

Skip to content

Claude status update inconsistencies #151

Closed

Description

@derekneely

First off, love what you've done. I use cmux on my mac and found this repo as I'm forced to use Windows at work.

Thought I'd post something that I've found after installed. The statuses to not seem to line up with with what Claude is doing very often. More times than not the workspace will say Idle when in fact an agent is running some stuff. Please see screenshot. In addition when you first start a Claude session it will say 'Running' even though it is a brand new instance that is doing nothing. Also, after going to a 'Needs you' workspace, answering questions or following up. The window does not come out of that state. It seems to be stuck in a 'Needs you' status even after resuming work. I find myself having to just click through tabs to see where things are instead of being able to rely on the actual status of the workspace.

Image

Activity

  1. derekneely commented on Aug 11, 2026

    @derekneely
    ContributorAuthor

    Not sure if interested but I forked the code and working through some updates on the status handling now. Will test through for a work day or two and can provide a PR back to you if that helps you out.

  2. amirlehmam commented on Aug 12, 2026

    @amirlehmam
    Owner

    Thank you — this is a good report, and all three symptoms turned out to be one root cause plus three smaller bugs sitting on top of it. Fixed in 0.48.0.

    The root cause: wmux only listened for things ENDING

    wmux drives its status from Claude Code hooks rather than from scraping the TUI. It registered four of them:

    PostToolUse    a tool finished
    Notification   Claude wants you
    Stop           the turn finished
    SubagentStop   a subagent finished
    

    Three of those are terminal events. Nothing ever said work had started. So the state machine only learned a turn was in flight when the first tool completed — and everything before that resolved to idle:

    • you send a message, Claude thinks for 40 s before touching a tool → Idle
    • Claude runs one three-minute npm test → Idle until it finishes
    • a turn that reasons and writes prose without calling a tool at all → Idle, start to finish

    That's your "more times than not it says Idle when an agent is running". It was never a timing or a refresh problem; the event that would have said otherwise was not being listened for.

    0.48.0 registers the opening half of the lifecycle:

    hook what it now tells wmux
    SessionStart this pane is an agent session, currently idle
    UserPromptSubmit the human replied — turn started, and any wait is over
    PreToolUse a tool is starting (matcher-less, so it covers every tool, not just the tracked ones)
    SessionEnd Claude Code exited — release the pane

    "Brand new session says Running"

    Different path, and a fair bit dumber than it looks. With no session known for a pane, the sidebar falls back to the shell's own state — and claude is a foreground command, so shell integration is entirely correct to report the pane as "running" for the whole life of the session. There was simply nothing outranking it.

    SessionStart fixes it by registering the pane as a known agent session at depth 0 the moment Claude launches (also on /clear, /compact and resume), so it reads Idle instead of borrowing the shell's verdict.

    "Needs you" that never clears

    Two separate causes, both fixed:

    1. Following up didn't clear it. The block was only cleared by PostToolUse or Stop — so after you replied, the pane kept saying "Needs you" until the next tool happened to finish. UserPromptSubmit now ends it the instant you hit Enter.

    2. Approving a permission prompt didn't clear it either — and this one has no hook at all. The order is PreToolUse → permission prompt → Notification → you approve → tool runs → PostToolUse. PreToolUse has already fired by the time the prompt appears, so between your approval and the tool finishing, Claude Code emits nothing. Approve a long command and the pane sits on "Needs you" for its entire runtime.

    For that one wmux now uses a fact it owns rather than one it has to infer: it owns the PTY, so it knows with certainty that a human pressed a key in that pane. Keystrokes that commit something — typing, Enter, Escape — clear the block. Arrow keys, page-up and mouse reports do not, because being sent to a pane and scrolling to see what it wants is the normal first move and must not clear the flag that sent you there.

    To be explicit, since it bends a rule I wrote deliberately: this is not a relaxation of "answering never clears blocked". That rule stops wmux declaring a prompt answered on its own say-so — if the sidebar's relayed keystroke were wrong, the pane would silently stop asking for help while the agent was still stuck. Here the human answered it themselves, in the pane, and wmux is reporting its own observation rather than guessing at Claude Code's UI. The failure mode is bounded and self-healing in the safe direction: if the keystroke didn't satisfy the agent, its very next report — a tool, a turn end, or the 60-second idle nudge — puts the pane straight back to asking.

    Two more bugs found while in there

    Subagents collapsed the status to Idle. SubagentStop decremented a refcount that PostToolUse pins to the absolute value 1. Subagent hooks inherit the parent's WMUX_SURFACE_ID, so every subagent reports to one pane — meaning the first subagent to finish drained the count to zero and the pane read Idle with the parent and its siblings still working. Any /wmux:orchestrate or multi-Task turn hit this. Only the parent's Stop ends a turn, and it was already decisive; the refcount was doing nothing but lying. This one probably accounted for a good share of the false Idles in your screenshot.

    Racing hook processes could pin a pane on "Running" forever. Every hook is its own short-lived node process, and they race to the pipe. PostToolUse fires before Stop, but if its process is the slower of the two to connect, its "a run is in flight" lands after Stop cleared the turn — and the pane then claims Running for the full 15-minute trust window with nothing running. Invisible from the outside, because both reports are individually correct. The hook helper now stamps the fire time at process start and wmux orders reports by that instead of by arrival.

    Upgrading

    Hooks are rewritten into ~/.claude/settings.json on startup, so 0.48.0 installs the four new ones by itself — your own hooks in those arrays are preserved untouched, and declining the agent integration still removes every wmux entry cleanly. Restart any Claude Code sessions that were already open: hooks are read at session start, so a session running from before the upgrade keeps the old set until you restart it.

    One honest note on cost: PreToolUse means one extra short-lived node process per tool call. Each is ~100 ms and exits (that was tightened in 0.42.0), but under several very busy agents it's roughly double the hook process churn of 0.47.0. If you notice it, tell me — the fallback is to give PreToolUse the same tracked-tool matcher PostToolUse uses, which cuts the volume at the cost of missing turns spent entirely in untracked tools.

    On your fork

    Yes, genuinely interested — please do open the PR. You're using this on a real work day across many panes, which is exactly the shape of usage that surfaced all of the above and that I can't reproduce reliably here. If your fork solved any of these differently I'd rather take your version than defend mine, and anything it covers that 0.48.0 doesn't is worth having on its own. Rebasing onto 0.48.0 first will save you some noise, since it touches most of agent-hook-bridge.ts and agent-state.ts.

    0.48.0 is building now and will be on the releases page shortly. Please reopen this — or just say so here — if any of the three is still misbehaving for you.

  3. derekneely commented on Aug 12, 2026

    @derekneely
    ContributorAuthor

    Sounds good. I've pulled in your latest release code and we're aligned on quite a few things. I'm still hammering on it and finding some edge cases that I'm working through. Once I'm feeling good about how it all is flowing, responding, and showing statuses, I'll get a PR out to you for review. Thanks.

  4. amirlehmam commented on Aug 13, 2026

    @amirlehmam
    Owner

    Status update, since 0.50.0 is out today: it contains no changes to agent-state handling. The fix for the three symptoms you reported is still exactly what shipped in 0.48.0 — the missing "work started" signal, plus the run-refcount, the seq de-dupe and the rule that answering never clears blocked on its own.

    So if you're testing your fork against a release, 0.50.0 is a safe base to rebase onto: this release is a CLI shim for PowerShell argument quoting (#154), CDP target recovery when a browser renderer dies (#155), browser command timeouts (#153), and the global agent-context block (#152). Nothing under agent-state.ts, agent-state-rpc.ts or agent-hook-bridge.ts moved.

    Still very interested in the PR. The edge cases are where this gets hard — nested subagents, a turn that ends while a subagent is still running, and a session that is answered from another pane via wmux answer-agent are the three that have historically been wrong in different ways. If your work converges on those, that is exactly the part worth reviewing.

    Leaving this open until your PR lands rather than closing on the 0.48.0 fix.

  5. derekneely commented on Aug 13, 2026

    @derekneely
    ContributorAuthor

    Sounds good. And that does sound like the cases that I am working through and testing against. I'll pull in the 0.50.0 stuff today and have a full work day on this and I 'think' I'm pretty close to having things all ironed out. I hope to have a PR out to you by tomorrow.

  6. derekneely commented on Aug 13, 2026

    @derekneely
    ContributorAuthor

    PR is up — ended up splitting it in two. The status work is in #159, and a separate notification-ring thing I found while testing is in #160, since it doesn't share any files with the rest.

    Short version of #159: the single-session path in the sidebar doesn't reach workingSessions yet, so one agent pane reads Idle mid-turn. Three edge cases in the hook bridge — the bare-tool PostToolUse form, the 60s idle nudge reading as "Needs you" on a pane nobody touched, and Escape leaving working set after an interrupt. A guard for SubagentStop arriving after Stop, which is the order I traced on two panes here. And the one that finally explained my original report: background shells and parallel subagents inherit the pane's surface id, so their tool lifecycle was clearing the block while the question was still on screen, and nothing put it back until the turn ended.

    All of it sits on top of 0.48.0 rather than changing the approach — that rewrite is what made these findable in the first place. Once the turn-start signal was there, the readings that were still off had a shape instead of feeling random. I've been running it as my daily driver since, on 0.48.0 and now 0.50.0, usually with several panes going.

    Happy to split any of it up, reorder, or drop pieces. One thing worth your eyes specifically: commit 4 changes behaviour on the answer-agent relay path, and I called out the trade-off in the PR — easy to drop that one and keep the other three if you'd rather leave it as is.

  7. amirlehmam commented on Aug 14, 2026

    @amirlehmam
    Owner

    Your PRs are merged — #159 (all four commits) and #160 — and both are in 1.0.0, out now.

    Closing this, finally, on your fix rather than mine. The detailed review is on each PR; the short version of what your four commits changed since 0.48.0:

    symptom from your original report
    single-session path never reached workingSessions one agent pane reading Idle mid-turn
    bare-tool PostToolUse never reached agent state long turns aging out of working on the clock
    60s idle nudge treated as a prompt Needs you on a pane nobody had touched
    bare Escape left runDepth asserted Running after an interrupt
    SubagentStop arriving after Stop Running with the agent idle at its prompt
    tool events clearing awaitingHuman a question on screen while the row said Running…

    Two of those turned on facts I had asserted in comments and never measured — that Claude Code fires the parent's Stop only after every subagent stops (it doesn't; you traced 1.8–2.2 s the other way on two panes), and that a pending permission dialog would have stopped a tool from running (true for an agent doing one thing at a time, false for background shells and parallel subagents, which is what agents actually do). You were right about both, with traces.

    Reopen if anything is still misreading on 1.0.0 — you've got more hours on this subsystem across more simultaneous panes than I do, and that's how all of the above surfaced.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      0