Set up (or toggle) a macOS desktop banner that appears whenever Claude Code finishes a task, showing a one-line summary of what was done.
Library skill — the default version is maintained in GitHub; edits you make live in your own clone.
Show a large, always-on-top desktop banner when Claude Code finishes a turn — with a one-line summary of what was actually completed. Works even when macOS Notification Center silently drops osascript display notification calls (a common problem: the CLI has no Notification Center registration, so the command exits 0 but nothing shows).
The banner is a borderless Cocoa overlay window drawn by mac-overlay.js (a JXA script adapted from peon-ping), so no notification permissions are needed.
osascript -l JavaScript)Copy mac-overlay.js from this skill directory to ~/.claude/scripts/mac-overlay.js.
Merge a Stop hook into ~/.claude/settings.json (read the file first and preserve existing hooks):
{
"hooks": {
"Stop": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "m=$(cat /tmp/claude-banner-msg 2>/dev/null); rm -f /tmp/claude-banner-msg; [ -f ~/.claude/banner.off ] || osascript -l JavaScript ~/.claude/scripts/mac-overlay.js \"${m:-Task done}\" blue \"\" 0 4 2>/dev/null || true",
"async": true
}
]
}
]
}
}
~/.claude/CLAUDE.md or AGENTS.md):After finishing each task, write a short summary of what was completed to
/tmp/claude-banner-msg(e.g.printf 'Typecheck fixed and committed' > /tmp/claude-banner-msg). Identify the actual task; never use a generic "task done".
The Stop hook displays the message and deletes the file. If the file is absent, it falls back to "Task done".
The hook checks a sentinel file — no config editing needed:
touch ~/.claude/banner.off # mute the banner
rm -f ~/.claude/banner.off # unmute
When the user asks to mute/unmute the banner, run the matching command and report the resulting state.
mac-overlay.js <message> <color> <icon> <slot> <dismiss_seconds> — color is blue/yellow/red, dismiss 0 means persistent-until-click./tmp/claude-banner-msg even while muted, so no stale summary pops up later when unmuted.NSTextAlignmentCenter evaluates to the legacy AppKit value (2), which the unified runtime treats as right-aligned — the bundled script hardcodes alignment 1 (center) to compensate./tmp/claude-banner-msg is shared across parallel Claude sessions; if two finish in the same instant one banner may show the other's summary. Use a per-session file path if that ever matters.