Repository navigation
Conversation
Users can now disable Claude Code's idle/waiting-for-input notification (Notification hook) while keeping completion notifications (Stop hook), avoiding duplicate notifications. New setting automation.claudeCodeNotificationHook defaults to true (existing behavior).
|
@yuanzidev is attempting to deploy a commit to the Manaflow Team on Vercel. A member of the Team first needs to authorize it. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThis PR adds a Claude Code "idle notifications" toggle that lets users enable or disable notification hooks when Claude reports it is waiting for input. It includes localized UI labels, a settings model backed by UserDefaults, settings file parsing/validation and search/navigation wiring, and conditional hook injection into the Claude wrapper runtime. ChangesClaude Code Idle Notification Hook
Sequence Diagram(s)sequenceDiagram
participant ComponentA
participant ComponentB
ComponentA->>ComponentB: observable interaction
Estimated Code Review Effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly Related PRs
Poem
Important Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional. ❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (14 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. 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. Comment |
Greptile SummaryThis PR adds a
Confidence Score: 5/5Safe to merge — the change is a clean additive toggle that follows the established pattern for all existing integration settings. Every layer of the change (shell hook assembly, Swift accessor, AppStorage binding, JSONC parsing, search index, localisation) mirrors the existing claudeCodeHooksEnabled / cursorHooksEnabled / geminiHooksEnabled patterns without introducing new state owners, timing dependencies, or architectural divergence. The two JSON assembly paths both produce well-formed JSON. Previous thread concerns (provider-specific copy in the subtitle, locale state values) are resolved in this revision. No files require special attention. Important Files Changed
Sequence DiagramsequenceDiagram
participant User as User
participant SettingsUI as Settings UI (cmuxApp.swift)
participant AppStorage as UserDefaults
participant GTV as GhosttyTerminalView
participant ShimScript as Resources/bin/claude
participant ClaudeCode as Claude Code
User->>SettingsUI: Toggle "Claude Code Idle Notifications" off
SettingsUI->>AppStorage: "Write claudeCodeNotificationHookEnabled = false"
User->>GTV: Open new terminal
GTV->>AppStorage: Read notificationHookEnabled()
AppStorage-->>GTV: false
GTV->>GTV: setManagedEnvironmentValue(CMUX_CLAUDE_NOTIFICATION_HOOK_DISABLED, 1)
User->>ClaudeCode: Run claude command
ClaudeCode->>ShimScript: Execute shim
ShimScript->>ShimScript: Check CMUX_CLAUDE_NOTIFICATION_HOOK_DISABLED
alt Hook disabled
ShimScript->>ShimScript: "HOOKS_JSON = HOOKS_BASE + HOOKS_TAIL"
else Hook enabled
ShimScript->>ShimScript: "HOOKS_JSON = HOOKS_BASE + HOOKS_NOTIFICATION + HOOKS_TAIL"
end
ShimScript->>ClaudeCode: exec claude --settings HOOKS_JSON
Reviews (2): Last reviewed commit: "Fix review feedback: remove internal hoo..." | Re-trigger Greptile |
| SettingsCardRow( | ||
| configurationReview: .json("automation.claudeCodeNotificationHook"), | ||
| String(localized: "settings.automation.claudeCode.notificationHook", defaultValue: "Claude Code Idle Notifications"), | ||
| subtitle: String(localized: "settings.automation.claudeCode.notificationHook.subtitle", defaultValue: "Notify when Claude Code reports that it is waiting for input. Completion notifications still use the Stop hook.") |
There was a problem hiding this comment.
The subtitle exposes "Stop hook" — a Claude Code provider-specific hook name — directly to end users. The custom cmux rule requires that user-facing copy not include upstream vendor or provider-specific implementation terms. A user toggling this setting doesn't need to know the internal hook name; saying "Completion notifications are unaffected" conveys the same intent without leaking the implementation detail. The same wording appears verbatim as the
defaultValue and will be shown any time the localized string is missing.
| subtitle: String(localized: "settings.automation.claudeCode.notificationHook.subtitle", defaultValue: "Notify when Claude Code reports that it is waiting for input. Completion notifications still use the Stop hook.") | |
| subtitle: String(localized: "settings.automation.claudeCode.notificationHook.subtitle", defaultValue: "Notify when Claude Code reports that it is waiting for input. Completion notifications are unaffected.") |
Context Used: Apply cmux's custom review rules from .github/revi... (source)
| "value": "Notify when Claude Code reports that it is waiting for input. Completion notifications still use the Stop hook." | ||
| } | ||
| }, | ||
| "ja": { | ||
| "stringUnit": { | ||
| "state": "translated", | ||
| "value": "Claude Codeが入力待ちのときに通知します。完了通知は引き続きStopフックを使用します。" |
There was a problem hiding this comment.
The English and Japanese subtitle values mention "Stop hook" / "Stopフック", leaking a Claude Code internal hook name into user-facing copy. Both should be updated to avoid the provider-specific term.
| "value": "Notify when Claude Code reports that it is waiting for input. Completion notifications still use the Stop hook." | |
| } | |
| }, | |
| "ja": { | |
| "stringUnit": { | |
| "state": "translated", | |
| "value": "Claude Codeが入力待ちのときに通知します。完了通知は引き続きStopフックを使用します。" | |
| "value": "Notify when Claude Code reports that it is waiting for input. Completion notifications are unaffected." | |
| } | |
| }, | |
| "ja": { | |
| "stringUnit": { | |
| "state": "translated", | |
| "value": "Claude Codeが入力待ちのときに通知します。完了通知には影響ありません。" |
Context Used: Apply cmux's custom review rules from .github/revi... (source)
| @@ -59583,6 +59583,244 @@ | |||
| } | |||
There was a problem hiding this comment.
Non-English locales marked as translated with untranslated text
Every locale other than en and ja for both settings.automation.claudeCode.notificationHook and its .subtitle key carries the English string but is flagged "state": "translated". Xcode's localization pipeline treats "translated" as production-ready and will surface these strings to users of those locales without any further warning. They should be "state": "needs_review" (or omitted entirely so the runtime falls back to the development language) until real translations are available. The same pattern is repeated in the search alias key settings.search.alias.setting.automation.claude-notification-hook.
- Replace "Stop hook" with "are unaffected" in subtitle text - Mark untranslated locales as "new" instead of "translated" - Update Japanese subtitle accordingly
|
Found a workaround that works right now on v0.64.13, no patch needed. cmux already has a filter for this:
So you match on the idle body and drop just that. Drop this in {
"notifications": {
"hooks": [
{
"id": "mute-idle-waiting",
"command": "jq -c 'if ((.notification.body // \"\") | test(\"waiting for your input\"; \"i\")) then .effects.desktop=false | .effects.sound=false | .effects.paneFlash=false | .effects.markUnread=false | .effects.reorderWorkspace=false else . end'"
}
]
}
}Hot-reloads on save. The idle banner, sound, flash, unread ring, and reorder all go away, but permission prompts and completions still come through. And it fails open, so if the hook breaks you just get the banner back. Not a real fix since it matches on text not |
Summary
automation.claudeCodeNotificationHooksetting (defaulttrue) that controls whether the Claude CodeNotificationhook is injected, independently of the mainautomation.claudeCodeIntegrationtoggleStophook), session tracking, Feed, status, and permission hooks continue workingMotivation
Claude Code turns can produce two notifications: a completion notification from the
Stophook, and a second notification from theNotificationhook when Claude sits idle at the prompt. The second notification arrives roughly a minute after completion and feels like a duplicate for users who mainly want to know when work is finished. Currently there is no way to disable only the idle notification while keeping completion notifications.Changes
Sources/cmuxApp.swiftnotificationHookEnabledKey/accessor toClaudeCodeIntegrationSettings,@AppStoragebinding, UI toggle in Automation settings, reset defaultsSources/GhosttyTerminalView.swiftCMUX_CLAUDE_NOTIFICATION_HOOK_DISABLED=1env var when setting is disabledResources/bin/claudeHOOKS_JSONinto base/notification/tail parts, conditionally assemble based on env varSources/KeyboardShortcutSettingsFileStore.swiftclaudeCodeNotificationHookfrom JSONC configSources/CmuxSettingsJSONPathSupport.swiftautomation.claudeCodeNotificationHookas a supported JSON pathSources/SettingsNavigation.swiftSources/SettingsSearchAliases.swiftResources/Localizable.xcstringsSettings UI
The toggle is placed in Settings → Automation, directly below the existing Claude Code Integration toggle. It is disabled and dimmed when Claude Code Integration is turned off.
Label: Claude Code Idle Notifications
Subtitle: Notify when Claude Code reports that it is waiting for input. Completion notifications still use the Stop hook.
Config file
Test plan
true)Notificationhook from the injectedHOOKS_JSONwhile preserving all other hooksStophook completion notifications still fire when the toggle is offautomation.claudeCodeIntegration=falsestill disables the entire integrationcmux.jsontrueSummary by cubic
Adds a toggle to disable Claude Code’s idle “waiting for input” notifications without affecting completion notifications or other hooks. This reduces duplicate pings while keeping the integration intact.
automation.claudeCodeNotificationHook(defaulttrue) to control the Notification hook independently ofautomation.claudeCodeIntegration.cmuxsetsCMUX_CLAUDE_NOTIFICATION_HOOK_DISABLED=1and theclaudeshim omits the Notification hook; completion notifications, session tracking, Feed, status, and permission hooks continue to work.cmux.json(e.g.,"claudeCodeNotificationHook": false); included in Reset All Defaults; localized strings added and user-facing copy updated to avoid internal hook names.Written for commit e551e59. Summary will update on new commits. Review in cubic
Summary by CodeRabbit
New Features
Localization