Skip to content

Instantly share code, notes, and snippets.

@bavanws
Last active January 20, 2026 02:45
Show Gist options
  • Select an option

  • Save bavanws/7506c9748ee3cf5baef5ec0bc608ebb1 to your computer and use it in GitHub Desktop.

Select an option

Save bavanws/7506c9748ee3cf5baef5ec0bc608ebb1 to your computer and use it in GitHub Desktop.
Claude Code desktop notifications for macOS

Claude Code desktop notifications for macOS

Claude Code Desktop Notifications (macOS)

Desktop notifications when Claude Code needs your input (permission prompts, questions).

Behaviour

  • Notification fires after a configurable delay (default 10s)
  • Each Claude session gets independent notifications - works with multiple instances in tmux/zellij
  • Notifications clear automatically when you respond (approve, reject, or send a message)

Configuration

Environment Variable Default Description
CLAUDE_NOTIFY_DELAY 10 Seconds to wait before showing notification
CLAUDE_NOTIFY_DEBUG 0 Set to 1 to enable logging to /tmp/claude-notify-debug.log

Tip: Set notification style to "Alerts" in macOS Settings > Notifications > terminal-notifier for persistent notifications that don't auto-dismiss.

Requirements

  • macOS
  • terminal-notifier (brew install terminal-notifier)
  • jq (brew install jq)

Installation

Create ~/.claude/hooks/ directory with these two files:

~/.claude/hooks/notify-start.sh

#!/bin/bash
DELAY="${CLAUDE_NOTIFY_DELAY:-10}"

INPUT=$(cat)
SESSION_ID=$(echo "$INPUT" | jq -r '.session_id' | grep -E '^[a-f0-9-]{36}$')
[ -z "$SESSION_ID" ] && exit 1
PIDFILE="/tmp/claude-notify-${SESSION_ID}.pid"

[ -f "$PIDFILE" ] && kill "$(cat "$PIDFILE")" 2>/dev/null

(
    sleep "$DELAY"
    terminal-notifier -title "Claude Code" -message "Waiting for input" -group "claude-$SESSION_ID" -sound default
    rm "$PIDFILE" 2>/dev/null
) &

echo $! > "$PIDFILE"

~/.claude/hooks/notify-cancel.sh

#!/bin/bash
INPUT=$(cat)
SESSION_ID=$(echo "$INPUT" | jq -r '.session_id' | grep -E '^[a-f0-9-]{36}$')
[ -z "$SESSION_ID" ] && exit 1
PIDFILE="/tmp/claude-notify-${SESSION_ID}.pid"

[ -f "$PIDFILE" ] && kill "$(cat "$PIDFILE")" 2>/dev/null && rm "$PIDFILE"
terminal-notifier -remove "claude-$SESSION_ID"

Make both scripts executable: chmod +x ~/.claude/hooks/notify-*.sh

Add to ~/.claude/settings.json

Merge this into the existing settings (or create the file if it doesn't exist):

{
  "hooks": {
    "Notification": [
      { "matcher": "permission_prompt", "hooks": [{ "type": "command", "command": "~/.claude/hooks/notify-start.sh" }] },
      { "matcher": "elicitation_dialog", "hooks": [{ "type": "command", "command": "~/.claude/hooks/notify-start.sh" }] }
    ],
    "UserPromptSubmit": [
      { "matcher": "*", "hooks": [{ "type": "command", "command": "~/.claude/hooks/notify-cancel.sh" }] }
    ],
    "PostToolUse": [
      { "matcher": "*", "hooks": [{ "type": "command", "command": "~/.claude/hooks/notify-cancel.sh" }] }
    ],
    "Stop": [
      { "matcher": "*", "hooks": [{ "type": "command", "command": "~/.claude/hooks/notify-cancel.sh" }] }
    ]
  }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment