The Problem
You know that moment? You're vibing, Claude is coding for you, you switch to Slack for literally 30 seconds — and when you come back, Claude has been sitting there for 5 minutes waiting for your permission to write a file. Silently. No sound, no notification, nothing.
This drove me absolutely crazy. I kept losing 5-10 minutes every time because I'd miss a permission prompt. And it turns out — I'm not alone. There's a known issue filed on GitHub, hundreds of people complaining about the same thing, and still no built-in fix as of May 13, 2026.
So I spent an evening trying every possible solution — the Notification hook (doesn't work reliably), code-notify brew package (overcomplicated), custom scripts... Nothing worked cleanly.
Until I found the answer. And it's embarrassingly simple.
The Fix: Two Hooks, Zero Dependencies
Claude Code has a hooks system. One of the hooks is called PermissionRequest — and it fires every single time Claude needs your approval. Another one is Stop — fires when Claude is done.
All you need is afplay — a command that's already built into every Mac since forever. It plays sound files. That's it. No npm, no pip, no brew, no background daemons.
I wrapped it into a one-line installer: claude-desktop-code-bell
Install (10 seconds, seriously)
curl -fsSL https://raw.githubusercontent.com/Zubrock/claude-desktop-code-bell/main/install.sh | bash
The installer lets you pick from 14 built-in macOS sounds (Glass, Ping, Submarine, Funk — whatever fits your vibe) and previews each one before you choose. Then just restart Claude Code.
That's it. You're done. 🎉
How It Works
Two hooks get added to your ~/.claude/settings.json:
{
"hooks": {
"PermissionRequest": [{
"hooks": [{
"type": "command",
"command": "afplay /System/Library/Sounds/Glass.aiff &",
"timeout": 5
}]
}],
"Stop": [{
"hooks": [{
"type": "command",
"command": "afplay /System/Library/Sounds/Ping.aiff",
"timeout": 5
}]
}]
}
}
- Glass chime → Claude needs your permission (file edit, bash command, etc.)
- Ping → Claude finished working
The & makes it non-blocking so Claude doesn't slow down. The whole thing adds maybe 50ms of overhead. You won't notice it.
What I Tried Before (So You Don't Have To)
-
Notificationhook withpermission_promptmatcher — doesn't fire reliably in Claude Desktop. Known bug. -
code-notify(brew package) — works but adds unnecessary complexity. Background processes, config files, the works. -
preferredNotifChannel: terminal_bell— only works in terminal, not in Desktop app. - Custom wrapper scripts — too fragile, breaks on updates.
The PermissionRequest hook is the only thing that fires consistently. I tested it dozens of times. It just works.
Uninstall
curl -fsSL https://raw.githubusercontent.com/Zubrock/claude-desktop-code-bell/main/uninstall.sh | bash
Clean removal, no leftovers. It even offers to restore your original settings from backup.
GitHub: Zubrock/claude-desktop-code-bell
macOS only for now — PRs for Linux/Windows are very welcome!
If this saved you from going insane, drop a ⭐ on the repo. And if you have ideas for improvements — issues and PRs are open.
Published May 13, 2026
Top comments (1)
It's amazing! Just ask me if you need some help )