Smart notifications for Claude Code with click-to-focus, git branch display, and webhook integrations.
- Features
- Installation
- Supported Notification Types
- Platform Support
- Configuration
- Manual Testing
- Contributing
- Troubleshooting
- Documentation
- License
- Cross-platform: macOS (Intel & Apple Silicon), Linux (x64 & ARM64), Windows 10+ (x64)
- 6 notification types: Task Complete, Review Complete, Question, Plan Ready, Session Limit, API Error
- Click-to-focus (macOS, Linux): click notification to focus the exact project window and tab β Ghostty, VS Code, iTerm2, Warp, kitty, WezTerm, Alacritty, Hyper, Apple Terminal, GNOME Terminal, Konsole, Tilix, Terminator, XFCE4 Terminal, MATE Terminal
- Multiplexers: tmux, zellij β click switches to the correct session/pane/tab
- Git branch in title:
β Completed main [cat] - Sounds: MP3/WAV/FLAC/OGG/AIFF, volume control, audio device selection
- Webhooks: Slack, Discord, Telegram, Lark/Feishu, Microsoft Teams, ntfy.sh, PagerDuty, Zapier, n8n, Make, custom β with retry, circuit breaker, rate limiting (docs)
- Plugin compatibility: works with double-shot-latte and other plugins that spawn background Claude instances
- Claude Code
- Windows users: Git Bash (included with Git for Windows) or WSL
- macOS/Linux users: No additional software required
One command to install everything:
curl -fsSL https://raw.githubusercontent.com/777genius/claude-notifications-go/main/bin/bootstrap.sh | bashThen restart Claude Code and optionally run /claude-notifications-go:settings to configure sounds.
The binary is downloaded once and cached locally. You can re-run /claude-notifications-go:settings anytime to reconfigure.
If the bootstrap script doesn't work for your environment, use the Manual Install below.
Step-by-step installation (if bootstrap doesn't work)
# 1) Add marketplace
/plugin marketplace add 777genius/claude-notifications-go
# 2) Install plugin
/plugin install claude-notifications-go@claude-notifications-go
# 3) Restart Claude Code
# 4) Download binary
/claude-notifications-go:init
# 5) (Optional) Configure sounds and settings
/claude-notifications-go:settingsHaving issues with installation? See Troubleshooting.
Run the same command as for installation β it will update both the plugin and the binary:
curl -fsSL https://raw.githubusercontent.com/777genius/claude-notifications-go/main/bin/bootstrap.sh | bashThen restart Claude Code to apply the new version. Your settings in ~/.claude/claude-notifications-go/config.json are preserved across updates.
Manual update (if bootstrap didn't work)
Claude Code also periodically checks for plugin updates automatically. Binaries are updated on the next hook invocation when a version mismatch is detected.
To update manually via Claude Code UI:
- Run
/plugin, select Marketplaces, chooseclaude-notifications-go, then select Update marketplace - Select Installed, choose
claude-notifications-go, then select Update now
If the binary auto-update didn't work (e.g. no internet at the time), run /claude-notifications-go:init to download it manually. If hook definitions changed in the new version, restart Claude Code to apply them.
| Status | Icon | Description | Trigger |
|---|---|---|---|
| Task Complete | β | Main task completed | Stop/SubagentStop hooks (state machine detects active tools like Write/Edit/Bash, or ExitPlanMode followed by tool usage) |
| Review Complete | π | Code review finished | Stop/SubagentStop hooks (state machine detects only read-like tools: Read/Grep/Glob with no active tools, plus long text response >200 chars) |
| Question | β | Claude has a question | PreToolUse hook (AskUserQuestion) OR Notification hook |
| Plan Ready | π | Plan ready for approval | PreToolUse hook (ExitPlanMode) |
| Session Limit Reached | β±οΈ | Session limit reached | Stop/SubagentStop hooks (state machine detects "Session limit reached" text in last 3 assistant messages) |
| API Error | π΄ | Authentication expired, rate limit, server error, connection error | Stop/SubagentStop hooks (state machine detects via isApiErrorMessage flag + error field from JSONL) |
Supported platforms:
- macOS (Intel & Apple Silicon)
- Linux (x64 & ARM64)
- Windows 10+ (x64)
No additional dependencies:
- β Binaries auto-download from GitHub Releases
- β Pure Go - no C compiler needed
- β All libraries bundled
- β Works offline after first setup
Windows-specific features:
- Native Toast notifications (Windows 10+)
- Works in PowerShell, CMD, Git Bash, or WSL
- MP3/WAV/OGG/FLAC audio playback via native Windows APIs
- System sounds not accessible - use built-in MP3s or custom files
Clicking a notification activates your terminal window. Auto-detects terminal and platform.
macOS β via AX API / AppleScript with bundle ID detection:
| Terminal | Focus method |
|---|---|
| Ghostty | AXDocument (OSC 7 CWD) |
| VS Code / Insiders | AXTitle (focus-window subcommand) |
| iTerm2, Warp, kitty, WezTerm, Alacritty, Hyper, Apple Terminal | AppleScript (window title) |
Any other (custom terminalBundleId) |
AppleScript (window title) |
Linux β via D-Bus daemon with automatic compositor detection:
| Terminal | Supported compositors |
|---|---|
| VS Code | GNOME, KDE, Sway, X11 |
| GNOME Terminal, Konsole, Alacritty, kitty, WezTerm, Tilix, Terminator, XFCE4 Terminal, MATE Terminal | GNOME, KDE, Sway, X11 |
| Any other | Fallback by name |
Linux focus methods (tried in order): GNOME extension, GNOME Shell Eval, GNOME FocusApp, wlrctl (Sway/wlroots), kdotool (KDE), xdotool (X11).
Multiplexers (both platforms): tmux, zellij β click switches to the correct pane/tab.
Windows β notifications only, no click-to-focus.
See Click-to-Focus Guide for configuration details.
Run /claude-notifications-go:settings to configure sounds, volume, webhooks, and other options via an interactive wizard. You can re-run it anytime to reconfigure.
Config file location:
| Platform | Path |
|---|---|
| macOS / Linux | ~/.claude/claude-notifications-go/config.json |
| Windows (Git Bash) | ~/.claude/claude-notifications-go/config.json |
| Windows (PowerShell) | $env:USERPROFILE\.claude\claude-notifications-go\config.json |
Edit the config file directly:
{
"notifications": {
"desktop": {
"enabled": true,
"sound": true,
"volume": 1.0,
"audioDevice": "",
"clickToFocus": true,
"terminalBundleId": "",
"appIcon": "${CLAUDE_PLUGIN_ROOT}/claude_icon.png"
},
"webhook": {
"enabled": false,
"preset": "slack",
"url": "",
"chat_id": "",
"format": "json",
"headers": {}
},
"suppressQuestionAfterTaskCompleteSeconds": 12,
"suppressQuestionAfterAnyNotificationSeconds": 12,
"notifyOnSubagentStop": false,
"notifyOnTextResponse": true,
"respectJudgeMode": true,
"suppressFilters": [
{
"name": "Suppress ClaudeProbe completions (remote-control)",
"status": "task_complete",
"gitBranch": "",
"folder": "ClaudeProbe"
}
]
},
"statuses": {
"task_complete": {
"title": "β
Completed",
"sound": "${CLAUDE_PLUGIN_ROOT}/sounds/task-complete.mp3"
},
"review_complete": {
"title": "π Review",
"sound": "${CLAUDE_PLUGIN_ROOT}/sounds/review-complete.mp3"
},
"question": {
"title": "β Question",
"sound": "${CLAUDE_PLUGIN_ROOT}/sounds/question.mp3"
},
"plan_ready": {
"title": "π Plan",
"sound": "${CLAUDE_PLUGIN_ROOT}/sounds/plan-ready.mp3"
},
"session_limit_reached": {
"title": "β±οΈ Session Limit Reached",
"sound": "${CLAUDE_PLUGIN_ROOT}/sounds/error.mp3"
},
"api_error": {
"title": "π΄ API Error: 401",
"sound": "${CLAUDE_PLUGIN_ROOT}/sounds/error.mp3"
},
"api_error_overloaded": {
"title": "π΄ API Error",
"sound": "${CLAUDE_PLUGIN_ROOT}/sounds/error.mp3"
}
}
}| Option | Default | Description |
|---|---|---|
notifyOnSubagentStop |
false |
Send notifications when subagents (Task tool) complete |
notifyOnTextResponse |
true |
Send notifications for text-only responses (no tool usage) |
respectJudgeMode |
true |
Honor CLAUDE_HOOK_JUDGE_MODE=true env var to suppress notifications |
suppressQuestionAfterTaskCompleteSeconds |
12 |
Suppress question notifications for N seconds after task complete |
suppressQuestionAfterAnyNotificationSeconds |
12 |
Suppress question notifications for N seconds after any notification |
suppressFilters |
[] |
Array of rules to suppress notifications by status, git branch, and/or folder. Each rule is an AND of its fields; omitted fields match any value. Set gitBranch to "" to match sessions outside git repos. |
Each status can be individually disabled by adding "enabled": false.
Built-in sounds (included):
${CLAUDE_PLUGIN_ROOT}/sounds/task-complete.mp3${CLAUDE_PLUGIN_ROOT}/sounds/review-complete.mp3${CLAUDE_PLUGIN_ROOT}/sounds/question.mp3${CLAUDE_PLUGIN_ROOT}/sounds/plan-ready.mp3${CLAUDE_PLUGIN_ROOT}/sounds/error.mp3
System sounds:
- macOS:
/System/Library/Sounds/Glass.aiff,/System/Library/Sounds/Hero.aiff, etc. - Linux:
/usr/share/sounds/**/*.ogg(varies by distribution) - Windows: Use built-in MP3s (system sounds not easily accessible)
Supported formats: MP3, WAV, FLAC, OGG/Vorbis, AIFF
See all available notification sounds on your system:
# List all sounds (built-in + system)
bin/list-sounds
# Output as JSON
bin/list-sounds --json
# Preview a sound
bin/list-sounds --play task-complete
# Preview at specific volume
bin/list-sounds --play Glass --volume 0.5Or use the skill command: /claude-notifications-go:sounds
Route notification sounds to a specific audio output device instead of the system default:
# List available audio devices
bin/list-devices
# Output:
# 0: MacBook Pro-Lautsprecher
# 1: Babyface (23314790) (default)
# 2: ImmersedThen add the device name to your ~/.claude/claude-notifications-go/config.json:
{
"notifications": {
"desktop": {
"audioDevice": "MacBook Pro-Lautsprecher"
}
}
}Leave audioDevice empty or omit it to use the system default device.
Preview any sound file with optional volume control:
# Test built-in sound (full volume)
bin/sound-preview sounds/task-complete.mp3
# Test with reduced volume (30% - recommended for testing)
bin/sound-preview --volume 0.3 sounds/task-complete.mp3
# Test macOS system sound at 30% volume
bin/sound-preview --volume 0.3 /System/Library/Sounds/Glass.aiff
# Test custom sound at 50% volume
bin/sound-preview --volume 0.5 /path/to/your/sound.wav
# Show all options
bin/sound-preview --helpVolume flag: Use --volume to control playback volume (0.0 to 1.0). Default is 1.0 (full volume).
The plugin is invoked automatically by Claude Code hooks. To test manually:
# Test PreToolUse hook
echo '{"session_id":"test","transcript_path":"/path/to/transcript.jsonl","tool_name":"ExitPlanMode"}' | \
claude-notifications handle-hook PreToolUse
# Test Stop hook
echo '{"session_id":"test","transcript_path":"/path/to/transcript.jsonl"}' | \
claude-notifications handle-hook StopSee CONTRIBUTING.md for development setup, testing, building, and submitting changes.
See Troubleshooting Guide for common issues:
- Ubuntu 24.04:
EXDEV: cross-device link not permittedduring/plugin install(TMPDIR workaround) - Windows: install issues related to
%TEMP%/%TMP%location
-
Architecture - Plugin architecture, directory structure, data flow
-
Click-to-Focus - Configuration, supported terminals, platform details
-
Volume Control Guide - Customize notification volume
- Configure volume from 0% to 100%
- Logarithmic scaling for natural sound
- Per-environment recommendations
-
Interactive Sound Preview - Preview sounds during setup
- Interactive sound selection
- Preview before choosing
-
Plugin Compatibility - Integration with other Claude Code plugins
-
Troubleshooting - Common install/runtime issues
- Ubuntu 24.04
EXDEVduring/plugin install(TMPDIR workaround)
- Ubuntu 24.04
-
Webhook Integration Guide - Complete guide for webhook setup
- Slack - Slack integration with color-coded attachments
- Discord - Discord integration with rich embeds
- Telegram - Telegram bot integration
- Lark/Feishu - Lark/Feishu integration with interactive cards
- Custom Webhooks - Any webhook-compatible service
- Configuration - Retry, circuit breaker, rate limiting
- Monitoring - Metrics and debugging
- Troubleshooting - Common issues and solutions
GPL-3.0 - See LICENSE file for details.


