claude-ghostty-notify
Tab-level click-through notifications for Claude Code running in Ghostty on macOS.
中文版 / 中文说明点这里
When a long-running Claude task finishes, a macOS notification pops up. Click Go to tab, and Ghostty jumps straight to the exact tab that was running that Claude session — not the frontmost tab, not the app, that specific tab. Works across multiple concurrent Claude sessions in the same project.
What you get
Three tiers of notifications, so short tasks don't spam you:
| Elapsed task time | What happens |
|---|
< 3 min | Silent — no notification at all |
3 – 10 min | Notification, no sound — glance at Notification Center if you wandered off |
≥ 10 min | Notification with Glass sound — you've clearly walked away, we'll wake you |
Only fires on task completion (Stop). Input / permission prompts (Notification events) are intentionally ignored — under bypass-permissions mode they're rare, and when they do fire, the terminal bell already covers them.
The thresholds are all configurable via env vars.
Why this exists
Other Claude Code notification tools (code-notify, claude-code-notifier, claude-notifications-go) either:
- don't do tab-level focus (they bring the app forward, you still have to find the right tab yourself),
- don't suppress short-task noise (every 2-second
ls fires a notification), or
- break when you upgrade Claude Code / plugins.
This project:
- Precise tab identification — writes a unique marker to the terminal's title via OSC 2, queries Ghostty via AppleScript to find which tab got the marker, then restores the title. Works even if you have several Claude sessions in the same project folder.
- Three-tier elapsed gate — configurable silence/silent-notify/loud-notify thresholds.
- No accessibility permission required — uses Ghostty's native AppleScript
select tab command, not keystroke simulation.
- Immune to Claude Code & plugin updates — pure bash hooks you own, with
alerter as the preferred backend (action-button-based clicks) and terminal-notifier as a fallback you can force via env var.
- Multi-session aware — keys saved state by Claude's
session_id, so several concurrent sessions each know their own tab.
Installation
1. Install dependencies
brew install jq alerter
- jq — parses the JSON Claude Code passes to hooks
- alerter — shows persistent macOS notifications with action buttons (clicks aren't reliable on stock
terminal-notifier banners)
2. Install the plugin
Inside Claude Code, run:
/plugin marketplace add Davie521/claude-ghostty-notify
/plugin install claude-ghostty-notify
That's it — hooks are auto-registered via the plugin manifest. No manual settings.json edits needed.
3. Flip one macOS setting
System Settings → Notifications → Script Editor → Alert Style → Persistent
Why Script Editor? alerter delivers notifications under the Script Editor bundle by default. Persistent style keeps the notification on screen until you dismiss it, and shows the Go to tab button directly. Banner style auto-hides and tucks the button behind a "Show" chevron — clicks won't reliably trigger.
4. Restart Claude Code
Quit and relaunch so the new hooks are loaded.
You're done. Default thresholds (3 min / 10 min / 20 min timeout) work out of the box — see Configuration to tune them.
Manual install (without the plugin system)
If you'd rather not use the plugin marketplace, the legacy installer still works:
git clone https://github.com/Davie521/claude-ghostty-notify.git
cd claude-ghostty-notify
./install.sh
It copies the hooks to ~/.claude/hooks/ and prints a settings.json snippet to merge manually. See example-settings.json for the exact JSON.
Configuration
All three thresholds are controlled by environment variables in your settings.json env block. Restart Claude Code for changes to take effect. Defaults are tuned for a workflow where most tasks finish under 3 minutes — only longer tasks get notifications.