Native macOS notifications for Claude Code and OpenCode. A lightweight SwiftUI panel appears when Claude finishes a response or needs permission -- with one click to jump to the exact editor window.
Author: Andrew Naegele Platform: macOS 14+ (Sonoma and later)
- Smart focus detection -- only plays a chime when your editor is focused, shows full popup when you're away
- Completion alerts with configurable chime when Claude stops responding
- Permission alerts with distinct sound when Claude needs approval
- Settings UI -- configure sounds, timeouts, and notification behavior from a native settings window
- 14 macOS system sounds to choose from (Glass, Tink, Ping, Pop, and more)
- Smart editor detection -- automatically detects Zed, Cursor, VS Code, Windsurf, Terminal, and more
- One-click focus -- brings the exact window/tab to the front, even with multiple editor instances
- Stacking -- multiple notifications stack vertically, never overlap
- Auto-dismiss with visual countdown bar (configurable: 10s to 5min, or persist until dismissed)
- Terminal window targeting -- uses tty matching to focus the exact Terminal.app or iTerm2 tab
- Works with both Claude Code and OpenCode
Zed, Cursor, VS Code, Windsurf, Void, Sublime Text, Fleet, Nova, Warp, iTerm2, WezTerm, Alacritty, Ghostty, Terminal.app
brew tap vibe-marketer/devping
brew install devping
devping-setup# Build from source
swift build -c release
# Install binary
mkdir -p ~/.local/bin
cp .build/release/devping ~/.local/bin/
chmod +x ~/.local/bin/devping
# Run setup
./bin/devping-setupThe setup script installs hook scripts and patches your Claude Code / OpenCode settings. Run it once -- future updates to the binary don't require re-running setup.
- Claude Code / OpenCode fires the Stop hook when it finishes a response
- The hook script detects the runtime (Claude vs OpenCode) and editor (Zed, Cursor, Terminal, etc.)
- It grabs the tty device from the parent process for terminal window targeting
- The binary checks if your editor is the frontmost app via
NSWorkspace - If editor is focused: plays a chime sound only (no popup -- you're already looking at it)
- If editor is NOT focused: renders a floating SwiftUI panel AND plays the chime
- Clicking the action button activates the correct editor and focuses the right window
- The panel auto-dismisses after the configured timeout with a visual countdown
The hook script uses three strategies in order:
- IDE lock files (
~/.claude/ide/*.lock) -- Claude Code creates these withideNameandworkspaceFolders. Matched by comparing the session's working directory. - Process tree walk -- walks up the parent process chain looking for known editor process names (Zed, Cursor, etc.)
TERM_PROGRAMenv var -- identifies the terminal emulator for standalone CLI sessions
- Code editors (Zed, Cursor, VS Code, etc.): Activated via AppleScript, then the editor's CLI command opens/focuses the project path
- Terminal.app: AppleScript iterates all windows/tabs, matches by tty device, brings the exact tab to front
- iTerm2: Same approach using iTerm2's AppleScript dictionary (windows > tabs > sessions)
devping/
Package.swift Swift package manifest
Sources/
main.swift SwiftUI notification app
bin/
devping-setup Interactive setup script
hooks/
notify-complete.sh Hook script (detects editor, launches binary)
Open the settings window:
devping --settingsFrom here you can configure:
- Focus behavior -- enable/disable focus detection, toggle chime-only mode when editor is focused
- Sounds -- pick from 14 macOS system sounds for completion and permission events (with preview)
- Display -- enable/disable popup notifications, set auto-dismiss timeout (10s to 5min, or never)
- Test -- preview completion and permission sounds with one click
Settings are stored in macOS UserDefaults (com.devping.app) and persist across updates.
| Setting | Default |
|---|---|
| Completion sound | Glass |
| Permission sound | Tink |
| Auto-dismiss | 30 seconds |
| Focus detection | Enabled |
| Chime-only when focused | Enabled |
Basso, Blow, Bottle, Frog, Funk, Glass, Hero, Morse, Ping, Pop, Purr, Sosumi, Submarine, Tink
Homebrew:
brew uninstall devping
brew untap vibe-marketer/devping
rm ~/.claude/hooks/notify-complete.sh
rm ~/.config/opencode/hooks/notify-complete.shThen remove the Stop and Notification entries from:
~/.claude/settings.json~/.config/opencode/settings.json
(c) 2026 Andrew Naegele | All Rights Reserved @andrew_naegele