Skip to content

Fix stale Claude sidebar needs-input status - #4742

Closed
austinywang wants to merge 7 commits into
mainfrom
issue-1027-sidebar-running-and-needs-input-status
Closed

austinywang wants to merge 7 commits into
mainfrom
issue-1027-sidebar-running-and-needs-input-status

Conversation

@austinywang

@austinywang austinywang commented May 26, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • track Claude hook runtime state when the sidebar is set to Running, Idle, or Needs input
  • suppress post-stop Claude idle_prompt notifications so they do not relight Needs input or fire a user-facing alert
  • localize the Claude needs-input sidebar status and add a regression test for the stale idle-prompt path

Issue

Testing

  • Not run locally per repository/user policy; CI will run the regression.

Scope

  • This PR handles the deterministic Claude idle_prompt false-positive path from the issue discussion. Broader cross-agent shell-state reconciliation can follow separately if other agents still report stale Running state.

View with Codesmith Autofix with Codesmith
Need help on this PR? Tag @codesmith with what you need. Autofix is disabled.


Note

Low Risk
Targeted Claude hook notification and session-state updates with a regression test; no auth or broad architectural changes.

Overview
Claude Code hook handling now persists runtimeStatus and lastNotificationStatus on session upserts for start, stop, prompt-submit, and notification paths so sidebar state matches the real turn lifecycle.

Post-stop idle_prompt notifications are suppressed when the mapped session is already idle (including nested data.notification_type signals), so the UI does not flip back to Needs input or fire notify_target_async after a completed stop.

Status labels for Running, Idle, and Needs input use agent.generic.* localized strings instead of hardcoded English, with expanded locale entries in Localizable.xcstrings. A regression integration test covers the idle-prompt-after-stop scenario.

Reviewed by Cursor Bugbot for commit 2ffb7b2. Bugbot is set up for automated code reviews on this repo. Configure here.


Summary by cubic

Fixes #1027 by preventing stale “Needs input” in the Claude sidebar via runtime/notification state tracking and by suppressing post‑stop idle_prompt notifications (flat and nested). Finalizes localized status strings and uses generic agent keys for Running/Idle/Needs input across locales.

  • Bug Fixes
    • Persist runtime and last-notification status to keep the sidebar accurate (Running/Idle/Needs input).
    • Suppress idle_prompt after stop (including nested signals) so it doesn’t relight “Needs input” or trigger alerts.
    • Localize status labels via agent.generic.status.running, agent.generic.notification.status.idle, agent.generic.notification.status.needsInput; add a regression test covering flat and nested idle‑prompt paths.

Written for commit 2ffb7b2. Summary will update on new commits. Review in cubic

Summary by CodeRabbit

  • New Features

    • Session status messages now use localized lookups and localization coverage expanded beyond English/Japanese.
  • Bug Fixes

    • Suppress idle-prompt notifications so sessions are not incorrectly marked as "Needs input" after stop; idle/needs-input status handling improved.
  • Tests

    • Added regression test to verify idle-prompt notification handling and status update behavior.

Review Change Stack

@vercel

vercel Bot commented May 26, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cmux Ready Ready Preview, Comment May 26, 2026 9:48am
cmux-staging Building Building Preview, Comment May 26, 2026 9:48am

@coderabbitai

coderabbitai Bot commented May 26, 2026 •

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR adds explicit runtimeStatus (and updateRuntimeStatus) to session status payloads, replaces hard-coded status strings with localized lookups, detects and suppresses idle-prompt notifications when a session is already .idle, and adds a regression test ensuring suppression prevents false "Needs input" transitions.

Changes

Status Tracking and Notification Suppression

Layer / File(s) Summary
Runtime status tracking and localized strings
CLI/cmux.swift, Resources/Localizable.xcstrings
Session state transitions (clear start, running, idle, needs-input) now set runtimeStatus and updateRuntimeStatus fields; status rendering and tool status fallbacks use localized strings.
Idle-prompt detection & suppression
CLI/cmux.swift
Adds helpers to detect idle_prompt cues from parsedInput.object / rawObject and a guard that logs a breadcrumb, prints {}, and returns early when the mapped session runtimeStatus is .idle.
Regression test
cmuxTests/CLINotifyProcessIntegrationRegressionTests.swift
testClaudeIdlePromptNotificationAfterStopDoesNotMarkNeedsInput verifies idle-prompt notifications after a stopped turn neither set "Needs input" nor emit notify commands (tests direct and nested payload formats).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

  • #3749: Modifies the same notification-handling and status mapping code paths; changes address idle_prompt vs needs-input classification there.
  • #2576: Implements explicit runtimeStatus and idle/needs-input distinction described in that issue.

Poem

🐰
A little hop, a tiny tweak,
Idle prompts now hide when meek.
Status texts speak in locales bright,
Runtime flags keep states in sight.
No false needs-input—hop, all right!


Caution

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

  • Ignore

❌ Failed checks (1 error, 2 warnings)

Check name Status Explanation Resolution
Cmux Full Internationalization ❌ Error PR violates i18n rules: agent.generic.status.running has copied English values in 17 non-English locales instead of proper translations. Replace copied English "Running" values in non-English locales with proper translations for agent.generic.status.running.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ⚠️ Warning The PR description covers the summary, issue reference, and testing approach, but is missing key sections from the template. Add a 'Demo Video' section (or indicate N/A for non-UI changes), complete the 'Review Trigger' block, and add a checklist with marked items to confirm testing and review status.
✅ Passed checks (14 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Changes address all coding requirements from #1027: tracking runtime state to ensure accurate Running/Idle/Needs input display, suppressing stale idle_prompt notifications, and localizing status indicators.
Out of Scope Changes check ✅ Passed All changes directly support the scope stated in PR description: Claude hook state tracking, idle_prompt suppression, status localization, and regression test for the specific false-positive path.
Cmux Swift Actor Isolation ✅ Passed Private Codable structs with Sendable-safe types, local store instance with file-based locking, and test additions only. No actor isolation issues introduced.
Cmux Swift Blocking Runtime ✅ Passed No blocking primitives (semaphores, sleeps, locks, dispatch) in production code. Changes implement deterministic idle prompt suppression via string tokenization and state comparison.
Cmux No Hacky Sleeps ✅ Passed PR contains only Swift and localization files. The check applies only to TypeScript, JavaScript, shell, or build/runtime scripts; Swift code is explicitly out of scope per runtime-no-hacky-sleeps.md.
Cmux Swift Concurrency ✅ Passed No legacy async patterns detected. Changes are localization updates, state fields, and synchronous helper functions only.
Cmux Swift @Concurrent ✅ Passed The PR adds only synchronous private helper functions and a synchronous test. No async functions, @concurrent annotations, or actor isolation issues are present.
Cmux Swift File And Package Boundaries ✅ Passed PR adds 62 lines (under 250-line threshold) to existing oversized 29.7k-line file as focused bug fix, with well-scoped private helpers and clear extraction path—matching allowed exception criteria.
Cmux Swift Logging ✅ Passed Print statements are only for CLI hook command responses (OK, {}, JSON), which are allowed per rules. No debugPrint, dump, NSLog, or file logging in app runtime code.
Cmux User-Facing Error Privacy ✅ Passed User-facing status strings ("Running", "Idle", "needs input") are generic and contain no sensitive data such as vendor names, credentials, internal details, or billing information.
Cmux Swiftui State Layout ✅ Passed This PR modifies only non-SwiftUI files: CLI/cmux.swift (Pure Swift CLI), Localizable.xcstrings (localization JSON), and test files. No SwiftUI views, state management, or layout code is present.
Cmux Architecture Rethink ✅ Passed Adds runtimeStatus tracking to ClaudeHookSessionStore with clear ownership and flock synchronization. Idle-prompt suppression prevents false positives. No sleeps, polling, or split lifecycle detected.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PR contains no new NSWindow, NSPanel, NSWindowController, or SwiftUI Window/WindowGroup; changes are limited to Claude hook status tracking and localization.
Title check ✅ Passed The title accurately reflects the main change: fixing a stale status issue in the Claude sidebar where needs-input status was incorrectly persisting.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-1027-sidebar-running-and-needs-input-status

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps

greptile-apps Bot commented May 26, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes stale "Needs input" in the Claude sidebar (#1027) by persisting a runtimeStatus field on session events and suppressing idle_prompt notifications when the mapped session's runtime status is already .idle (post-stop). It also completes locale coverage for three status strings and adds a regression test for flat and nested idle-prompt payloads.

  • Bug fix: shouldSuppressClaudeIdlePromptNotification gates on runtimeStatus == .idle to prevent a post-stop idle_prompt from relighting the sidebar or firing a user alert; the session record is not updated on suppression so state remains .idle.
  • Localization: agent.generic.status.running, agent.generic.notification.status.idle, and agent.generic.notification.status.needsInput now carry translations for all 19 previously-supported locales (replacing "Running" placeholders) plus a newly introduced km entry; the sidebar labels are updated to use String(localized:) instead of hard-coded English strings.
  • Test: New integration regression exercises session-start → prompt-submit → stop → idle_prompt (flat and nested data-wrapped payloads) and asserts stdout == \"{}\" with no set_status or notify_target_async commands emitted.

Confidence Score: 4/5

Safe to merge for the targeted idle-prompt bug fix; the parallel runtimeStatus field and partial km locale introduction are worth resolving before the PR is considered complete.

The suppression logic is narrow and well-tested — the regression covers both flat and nested idle-prompt payloads and asserts the right stdout and absence of sidebar/alert commands. The localization updates for the 19 already-supported locales are complete. Two areas need attention: runtimeStatus is a new side-channel field that duplicates information already present in agentLifecycle and lastNotificationStatus without a documented invariant tying them together, and km is introduced for only three of the catalog's many strings, leaving Khmer-locale users with a patchy translation experience.

CLI/cmux.swift — the relationship between runtimeStatus and agentLifecycle; Resources/Localizable.xcstrings — the partial km locale rollout.

Important Files Changed

Filename Overview
CLI/cmux.swift Adds runtimeStatus/lastNotificationStatus tracking on session events, introduces shouldSuppressClaudeIdlePromptNotification to gate idle-prompt notifications on the session's last sidebar state, and localizes status strings. New runtimeStatus field runs parallel to agentLifecycle with no documented invariant between them.
Resources/Localizable.xcstrings Expands locale coverage for agent.generic.notification.status.idle and agent.generic.notification.status.needsInput to all 19 existing locales, and upgrades agent.generic.status.running from placeholder "Running" values to real translations. Also introduces a km (Khmer) entry for all three keys, which is new to the catalog.
cmuxTests/CLINotifyProcessIntegrationRegressionTests.swift Adds a regression test exercising session-start → prompt-submit → stop → idle_prompt (flat and nested payloads) and asserting no set_status "needs input" or notify_target_async commands are issued.

Sequence Diagram

sequenceDiagram
    participant Claude
    participant Hook as Claude Hook Handler
    participant Store as Session Store
    participant Sidebar

    Claude->>Hook: session-start
    Hook->>Store: "upsert runtimeStatus=.running (if clear/replace)"
    Hook->>Sidebar: set_status Running

    Claude->>Hook: prompt-submit
    Hook->>Store: "upsert runtimeStatus=.running"
    Hook->>Sidebar: set_status Running

    Claude->>Hook: stop
    Hook->>Store: "upsert runtimeStatus=.idle, lastNotificationStatus=.idle"
    Hook->>Sidebar: set_status Idle

    Claude->>Hook: notification idle_prompt stale post-stop
    Hook->>Store: read runtimeStatus .idle
    Note over Hook: shouldSuppressClaudeIdlePromptNotification = true
    Hook-->>Claude: "print {} suppressed no sidebar update"

    Claude->>Hook: notification real needs-input
    Hook->>Store: read runtimeStatus .idle or .running
    Note over Hook: isIdlePromptNotification = false OR runtimeStatus ne .idle
    Hook->>Store: "upsert runtimeStatus=.needsInput, lastNotificationStatus=.needsInput"
    Hook->>Sidebar: set_status Needs input
    Hook->>Claude: notify_target_async user alert
Loading

Reviews (6): Last reviewed commit: "merge: resolve conflicts with main" | Re-trigger Greptile

Comment thread Resources/Localizable.xcstrings Outdated
Comment thread CLI/cmux.swift
coderabbitai[bot]
coderabbitai Bot previously requested changes May 26, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CLI/cmux.swift`:
- Around line 19727-19734: The suppression branch currently writes "OK" to
stdout but other hook completions return an empty JSON object string; update the
suppression path inside the shouldSuppressClaudeIdlePromptNotification
conditional to print an empty JSON object (e.g. use print("{}") so it emits
"{}\n") instead of print("OK"), keeping the
telemetry.breadcrumb("claude-hook.notification.idle-prompt-suppressed") and the
early return in place to preserve behavior.
- Line 19504: The localized string keys used in CLI/cmux.swift (e.g.,
String(localized: "agent.generic.status.running"),
"agent.generic.notification.status.idle", and
"cli.claude-hook.status.needsInput") are missing translations for several
supported locales; update Resources/Localizable.xcstrings to add the missing
locale entries for these keys (add km for agent.generic.status.running; add ar,
bs, da, de, es, fr, it, km, ko, nb, pl, pt-BR, ru, th, tr, uk, zh-Hans, zh-Hant
for agent.generic.notification.status.idle and
cli.claude-hook.status.needsInput) so all locales referenced by the app have
translations; verify the usages at the other sites in CLI/cmux.swift (around the
occurrences noted) still reference the same keys and run localization validation
to ensure no missing-key warnings remain.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 0d984384-5686-4b5d-984e-02e278e56c76

📥 Commits

Reviewing files that changed from the base of the PR and between 89533ee and 6eac055.

📒 Files selected for processing (3)
  • CLI/cmux.swift
  • Resources/Localizable.xcstrings
  • cmuxTests/CLINotifyProcessIntegrationRegressionTests.swift

Comment thread CLI/cmux.swift
Comment thread CLI/cmux.swift

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 4c31a63. Configure here.

Comment thread CLI/cmux.swift Outdated
coderabbitai[bot]
coderabbitai Bot previously requested changes May 26, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Resources/Localizable.xcstrings`:
- Line 22441: The localization entry for key "agent.generic.status.running"
contains many non-English locale slots set to the English word "Running"; update
each non-English locale stringUnit value to a proper translation (or remove the
locale slot if a genuine translation is not available) so no locale uses copied
English, ensuring every locale follows the project's placeholder/copy rules and
leaving only true translations for the "agent.generic.status.running" key.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 87622493-4a03-43f9-b179-3a4f1e79851a

📥 Commits

Reviewing files that changed from the base of the PR and between 6eac055 and 09b1c96.

📒 Files selected for processing (3)
  • CLI/cmux.swift
  • Resources/Localizable.xcstrings
  • cmuxTests/CLINotifyProcessIntegrationRegressionTests.swift

Comment thread Resources/Localizable.xcstrings Outdated
@austinywang
austinywang dismissed stale reviews from coderabbitai[bot] and coderabbitai[bot] May 26, 2026 03:15

Superseded by follow-up commits addressing the actionable CodeRabbit findings; the inline threads are resolved and the CodeRabbit check is green.

@lawrencecchen lawrencecchen added the stale-revisit Closed after 30+ days without activity; preserved for possible revisit or reopening. label Sep 23, 2026
@github-project-automation github-project-automation Bot moved this from Todo to Done in cmux backlog Sep 23, 2026

This branch was successfully deployed

1 active deployment
Preview – cmux — 2ffb7b26 Deployed May 26, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stale-revisit Closed after 30+ days without activity; preserved for possible revisit or reopening.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Sidebar 'Running' and 'Needs Input' status indicators are flaky and unreliable

3 participants