Are you the author? Sign in to claim
macOS notification hook for Claude Code that focuses your terminal (Ghostty/Cursor) when you click it
A macOS notification hook for Claude Code that takes you back to your terminal when you click it.
When Claude finishes a task or needs your input, you get a native macOS banner. Clicking it focuses the app your session is running in:
The banner also shows the target app's icon as its image.
curl -fsSL https://raw.githubusercontent.com/filiphric/claude-code-notify/main/install.sh | bash
The installer:
terminal-notifier and jq via Homebrew (if missing),notify.sh into ~/.claude/hooks/,Stop and Notification hooks into ~/.claude/settings.json (existing settings are preserved and backed up first).Then, in System Settings → Notifications, enable notifications for terminal-notifier — set to Alerts so the banner stays long enough to click.
echo '{"hook_event_name":"Stop"}' | ~/.claude/hooks/notify.sh
A banner should appear; clicking it focuses your terminal.
terminal-notifier and jq)All optional, set as environment variables (they're read by the hook, so export them where Claude Code will see them — e.g. your shell profile):
| Variable | Default | Meaning |
|---|---|---|
CLAUDE_NOTIFY_SOUND | Glass | Notification sound name. |
CLAUDE_NOTIFY_TITLE | Claude Code | Banner title. |
CLAUDE_NOTIFY_PRIMARY_TERM | ghostty | $TERM_PROGRAM value that identifies your primary terminal. |
CLAUDE_NOTIFY_PRIMARY_BUNDLE | com.mitchellh.ghostty | Bundle id to focus when the session runs in the primary terminal. |
CLAUDE_NOTIFY_FALLBACK_BUNDLE | com.todesktop.230313mzl4w4u92 (Cursor) | Bundle id to focus otherwise. |
CLAUDE_NOTIFY_PRIMARY_ICON | ~/.claude/hooks/primary-icon.png | Big-image icon for the primary terminal. |
CLAUDE_NOTIFY_FALLBACK_ICON | ~/.claude/hooks/fallback-icon.png | Big-image icon for the fallback app. |
Find an app's bundle id with osascript -e 'id of app "iTerm"', then:
export CLAUDE_NOTIFY_PRIMARY_TERM=iTerm.app
export CLAUDE_NOTIFY_PRIMARY_BUNDLE=com.googlecode.iterm2
export CLAUDE_NOTIFY_FALLBACK_BUNDLE=com.microsoft.VSCode
(For the icons to match, re-run the installer with the same
CLAUDE_NOTIFY_PRIMARY_BUNDLE / CLAUDE_NOTIFY_FALLBACK_BUNDLE set, or point
CLAUDE_NOTIFY_*_ICON at your own PNGs.)
Tip: run echo $TERM_PROGRAM inside your terminal to see the value it reports.
The notification is posted via terminal-notifier's -sender <bundle-id>, so it
carries the target app's icon, groups under that app in Notification Center, and
macOS focuses the app when you click the banner.
The target app must have posted a native notification at least once, or macOS won't know its identity and falls back to terminal-notifier's icon. To register a terminal that supports desktop notifications (e.g. Ghostty), run this in a shell and click away within 3s (terminals suppress notifications while focused):
( sleep 3; printf '\033]777;notify;Claude Code;registering\033\\' )
Once the app's own notification appears once, this stays registered.
Delivery is detached. As an async hook, this script returns immediately;
because -sender makes terminal-notifier linger as the notification's
delegate, it's launched with nohup so it survives the hook exiting long
enough to post (then it's reaped to avoid piling up processes).
When the target app is frontmost, macOS may file the notification straight into Notification Center rather than popping a banner. In practice the case you care about — you kicked off a task and switched away — has the app backgrounded, so the banner appears and pulls you back.
curl -fsSL https://raw.githubusercontent.com/filiphric/claude-code-notify/main/uninstall.sh | bash
or, from a clone, bash uninstall.sh. It removes the hook entries from
settings.json (backing it up first) and deletes the installed script + icons.
MIT
Blocks dangerous git and shell commands from being executed by AI coding agents
One command to install 6 essential safety hooks in 10 seconds — zero dependencies
Give Claude Code memory that evolves with your codebase via hooks and LLM-compiled knowledge
Rule enforcement plugin — save rules with natural language, enforce with 17 lifecycle hooks