[Feature] Native settings option for idle/ready notification (no hook needed)
[Feature] Native settings option for idle/ready notification (no hook needed)
Summary
Add a built-in config option in settings.json that triggers a sound (terminal bell, local command, or system notification) when Claude Code returns to the idle state waiting for user input. Implementation lives in the binary — no hooks, no LLM tokens, no shell scripts to maintain.
Motivation
Long-running tasks make users tab away. When Claude finishes a complex task and waits for the next prompt, there's no audible signal that it's ready. Hook-based workarounds are unreliable:
Stophook fires multiple times within complex tasks (subagent bubbling, plan mode, internal continuations) → false beeps mid-taskNotificationwithidle_promptmatcher is documented as buggy (#8320) → fires on every response, not on real idle- DIY state machines via shell hooks consume time, debugging effort, and miss edge cases (we tried)
Issue #13024 requests the same goal but as a hook. A hook still requires the user to write/maintain shell scripts, handle WSLg/Wayland/macOS audio differences, and reinvent debounce logic — all for a binary state the runtime already knows internally.
Proposed Design (mirrors existing statusLine)
{
"idleNotify": {
"enabled": true,
"command": "paplay /usr/share/sounds/freedesktop/stereo/complete.oga"
}
}
Or a minimal terminal-bell variant:
{
"idleNotify": "bell"
}
Possible values:
"bell"— emit\ato the terminal"none"(default) — disabled{ "command": "<shell command>" }— runtime invokes any local command
Fires once on the transition into "ready for next user prompt". Subagent stops, auto-compaction, and internal continuations do not trigger it — the runtime distinguishes those because the state is internal to the binary.
Why Not a Hook
A hook can't reliably distinguish "Claude is idle waiting for me" from "Claude is mid-task between internal turns" — the difference lives inside the binary. Exposing the transition as a native config trigger:
- Solves the problem correctly (no false positives possible)
- Zero LLM token cost
- Removes WSLg/Wayland/macOS/tmux audio concerns from user-space
- No shell debugging, no state files in
/tmp
Precedent
statusLine is the existing pattern: native config, runtime decides invocation timing, user provides a local command. idleNotify would be the same shape.
Related
- #13024 — same goal, hook-based proposal
- #8320 —
idle_promptnotification matcher bug - #12048 — broader notification matcher gaps
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗