Skip to content

Instantly share code, notes, and snippets.

@pib
Created February 26, 2026 21:30
Show Gist options
  • Select an option

  • Save pib/59bdc55c38cc86fb92600e7680e307e2 to your computer and use it in GitHub Desktop.

Select an option

Save pib/59bdc55c38cc86fb92600e7680e307e2 to your computer and use it in GitHub Desktop.
Claude Code hook: ring terminal bell when user input is needed (permission dialogs, questions)
#!/bin/bash
# Ring terminal bell when Claude needs user input.
# Registered on: Notification (permission_prompt), Stop
#
# - Notification:permission_prompt fires for tool permissions AND AskUserQuestion
# dialogs, after a ~6s typing-idle delay. Bell rings unconditionally.
# - Stop fires when Claude's turn ends. Bell rings only if the final message
# ends with "?" (trailing whitespace stripped).
#
# Always exits 0 — never break Claude's workflow over a cosmetic bell.
# Writes to /dev/tty because hook stdout is captured by Claude Code.
ring_bell() {
printf '\a' > /dev/tty 2>/dev/null
}
INPUT=$(cat)
EVENT=$(echo "$INPUT" | jq -r '.hook_event_name // "unknown"' 2>/dev/null)
case "$EVENT" in
Notification)
ring_bell
;;
Stop)
# Check if last message ends with "?" (ignoring trailing whitespace).
# Skip silently if jq is missing or JSON is malformed.
ENDS_WITH_Q=$(echo "$INPUT" | jq -r '
.last_assistant_message // ""
| test("\\?\\s*$")
' 2>/dev/null)
if [ "$ENDS_WITH_Q" = "true" ]; then
ring_bell
fi
;;
esac
exit 0

Claude Code: Bell on Input Needed

A Claude Code hook that rings the terminal bell (\a) when user input is needed. In Windows Terminal, this shows a bell icon on the tab — so you can tell which tab needs you at a glance.

What triggers the bell

Trigger How it works
Permission dialogs Notification:permission_prompt fires when Claude needs tool approval
AskUserQuestion dialogs Also fires as permission_prompt
Response ends with ? Stop event, script checks last_assistant_message

No bell for working or idle states — only when Claude is waiting on you.

Setup

  1. Save bell-on-input-needed.sh to ~/.claude/hooks/ and make it executable:

    mkdir -p ~/.claude/hooks
    curl -o ~/.claude/hooks/bell-on-input-needed.sh <raw-url-of-this-gist>
    chmod +x ~/.claude/hooks/bell-on-input-needed.sh
  2. Add the hook registrations to your ~/.claude/settings.json under the "hooks" key:

    "Notification": [
      {
        "matcher": "permission_prompt",
        "hooks": [
          {
            "type": "command",
            "command": "~/.claude/hooks/bell-on-input-needed.sh",
            "timeout": 1
          }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "~/.claude/hooks/bell-on-input-needed.sh",
            "timeout": 1
          }
        ]
      }
    ]

Requirements

  • jq (for question-mark detection on Stop events; bell still works for permission dialogs without it)
  • A terminal that supports the bell character (Windows Terminal, iTerm2, most modern terminals)

Known limitations

  • Trailing ? heuristic — May false-positive on code ending with ? (URLs, ternary operators). May miss questions that aren't at the end of the response.
  • Bell fires even if you're looking at the tab — The ~6s typing-idle delay only suppresses during active typing, not passive viewing.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment