Headsup notifications
Glanceable Claude Code and Codex state in your terminal tabs: white=idle, blue=working, orange=waiting. Multi-terminal (iTerm2, WezTerm, AI Power Term), a live status bar with Anthropic usage limits, /sfl and /nil window save-and-restore, and twelve companion skills. macOS only.
npx -y skills add wasulajr/headsup --skill headsup-notificationsAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Manage the macOS notification that fires when a Claude Code tab has been waiting on the user for more than N minutes. Use when the user types /headsup-notifications, asks to enable/disable the "Claude is waiting" notification, wants to change how long it waits before notifying, or wants to test that notifications are working. Accepts on/off, a numeric threshold (minutes), "test" to fire a one-off notification, and "sound <name|none>" to change the alert sound.
SKILL.md
6.5 KB, as published. Nobody here has run it
iTerm waiting-notifications
The launchd watchdog (claude-code.headsup-watchdog) runs every 30 seconds. When it finds a tab whose state file has been orange (waiting) for longer than THRESHOLD_MIN minutes, it fires a macOS notification. This skill is the user-friendly way to toggle the feature, change the threshold, change the sound, or test that it works.
Notifications are posted from the bundled headsup-notifier.app at ~/Library/Application Support/headsup/, so Notification Center renders them with the headsup icon. The bundle is built and installed by setup.sh (Step 5/8). No third-party dependencies like terminal-notifier are required.
Usage forms
| Form | Effect |
|---|---|
/headsup-notifications | Show current state (enabled / threshold / sound) |
/headsup-notifications on | Enable notifications |
/headsup-notifications off | Disable notifications |
/headsup-notifications <N> | Set threshold to N minutes (positive integer) |
/headsup-notifications <N> on | Set threshold AND enable |
/headsup-notifications <N> off | Set threshold AND disable |
/headsup-notifications test | Fire a test notification right now (doesn't change config) |
/headsup-notifications sound <name> | Set sound, any macOS system sound name (Glass, Ping, Submarine, etc.) |
/headsup-notifications sound none | Silence the notification |
What to do when invoked
Run the helper script with the user's args. Don't try to parse the args yourself; pass them through unchanged. The helper updates the config in place and prints the resulting state.
~/.claude/hooks/headsup-notifications.sh "$@"
If the user just said "turn on notifications" or "enable", pass on. "Turn them off" or "disable" becomes off. "Set the threshold to 10 minutes" or "wait 10 minutes" becomes 10. "Test it" or "send me a test" becomes test.
After the helper prints the new state, don't add a long explanation; the output is clear enough. One short confirmation sentence if the change is non-obvious (e.g., "Notifications will now fire after 10 minutes of waiting").
First-run macOS permissions
macOS requires per-bundle notification permission. The first time a notification fires (from /headsup-notifications test or a real wait), macOS shows "headsup wants to send notifications." Click Allow. The decision sticks to the bundle's codesigning identity, so future notifications fire silently.
If notifications stop appearing later: System Settings, Notifications, scroll for headsup, ensure "Allow Notifications" is on.
If headsup isn't in the list at all (rare, indicates macOS recorded a silent denial), the recovery is in the README's Troubleshooting section: bump the bundle ID in notifier-app/Info.plist.template and re-run setup.sh so macOS treats it as a fresh app.
Notification content
What you see when a notification fires:
| Slot | Source |
|---|---|
| Top header + icon | headsup (the bundle's CFBundleName) and the orange face icon |
| Title (large, bold) | The per-tab badge from ~/.claude/hooks/.state/<uuid>.badge (matches the iTerm2 watermark; defaults to the project name, override via /headsup-label) |
| Subtitle | Claude is waiting |
| Body | Idle for <N>m (or longer) |
| Sound | NOTIFICATION_SOUND from conf (default Glass) |
The title differing from the app name is how you tell which tab needs you when multiple are waiting.
How the threshold actually applies
THRESHOLD_MIN is matched against the .state file's mtime via find -mmin +N. The watchdog runs every 30s, so the actual notification fires at THRESHOLD_MIN to THRESHOLD_MIN + 30s after Claude started waiting.
The wait period is identified by:
.statecolor matchesWAIT_COLOR(orange).statemtime is older thanTHRESHOLD_MINminutes- No
.notifiedsidecar exists, OR.notifiedis older than.state(a fresh wait period started)
When you respond (UserPromptSubmit), the state file gets rewritten with a new color and mtime; the next wait period restarts the cycle.
What this skill DOESN'T do
- Doesn't change tab colors or the dock-attention behavior; those still work whether notifications are on or off.
- Doesn't notify per-event during Claude's normal turn-end. The tab going orange already handles fast feedback. Notifications are for the "I walked away, Claude finished, I forgot to come back" case.
- Doesn't bundle or batch notifications across multiple tabs; each waiting tab gets its own.
- Doesn't support sub-minute thresholds.
find -mminis integer-minute granularity, and the watchdog cadence is 30s. Sub-minute would require additional changes to both.
Where the supporting files live
~/.claude/hooks/headsup-notifications.shis this skill's helper script~/.claude/hooks/headsup-notifications.confis the persisted config~/.claude/hooks/headsup-notify-waiting.shis the actual notifier sweep (called from the watchdog)~/.claude/hooks/headsup-watchdog.shcalls the notifier every 30s~/Library/Application Support/headsup/headsup-notifier.appis the Swift binary that posts the notification (so macOS renders the headsup icon)
All under version control at github.com/wasulajr/headsup.