This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
ClaudeNotifier is a macOS notification app for Claude Code integration. It displays native macOS notifications with Claude's icon, with smart suppression when the user is actively viewing the Claude terminal tab. Clicking a notification focuses the terminal that triggered it.
make build # Compile, bundle as .app, and codesign to build/ClaudeNotifier.app
make install # Build + install to /Applications + create CLI at ~/.local/bin/claude-notifier
make uninstall # Remove app and CLI symlink
make clean # Remove build directory
make icons # Generate icon variants from assets/icon.svg (requires librsvg)
make lint # Run SwiftLint
make format # Run SwiftFormat
make setup # Install pre-commit hooksRun make setup after cloning to install git hooks. On each commit:
- SwiftFormat auto-formats staged Swift files
- SwiftLint checks for violations (strict mode)
- Conventional commits validates commit message format
Commit messages must follow Conventional Commits:
feat: add new feature
fix: resolve bug
docs: update readme
chore: update dependencies
Multi-file Swift application using AppKit and UserNotifications frameworks.
File structure:
Sources/ClaudeNotifier/
├── main.swift # Entry point - parses args, configures and runs NSApplication
├── Constants.swift # Shared constants (paths, keys, defaults)
├── Models.swift # Data structures (NotificationConfig, ParsedArguments)
├── AppDelegate.swift # NSApplicationDelegate + UNUserNotificationCenterDelegate
├── Setup.swift # Setup command + embedded notify.sh script
├── Doctor.swift # Doctor command - diagnoses installation and permission issues
├── Config.swift # AppConfig model + persistence (load/save config.json)
├── ConfigCommand.swift # Config command - interactive TUI for preferences
├── TUI.swift # Raw terminal input + menu rendering for interactive config
├── Icon.swift # Icon variant utilities (used by ConfigCommand and Doctor)
├── Update.swift # Update command + version check
├── ArgumentParser.swift # CLI flag parsing and help text
└── Utilities.swift # Helpers (exitWithError, terminateApp, focusTerminalSession)
Key components:
- Constants: Centralized magic strings (
claudeDirectory,sessionIdKey, etc.) - Models:
NotificationConfigandParsedArgumentsdata structures - AppDelegate: Handles notification display, authorization, and click responses
- Setup: Embedded
notify.shscript + functions to configure~/.claude/settings.jsonhooks - Doctor: Checks installation, hooks, permissions, and PATH configuration
- Config:
AppConfigmodel with icon/sound fields, JSON persistence to~/Library/Application Support/ClaudeNotifier/config.json - ConfigCommand: Interactive TUI for configuring icon color and notification sound
- TUI: Raw terminal mode handling, arrow key navigation, and menu rendering
- Icon:
IconVariantenum,getCurrentVariant(),setVariant(), and helper functions for icon switching - Update: Version check via GitHub API, brew upgrade integration, doctor version check
- ArgumentParser: Parses
-t,-s,-m,-iflags andsetup/doctor/config/update/helpsubcommands - Utilities:
exitWithError(),terminateApp(),focusTerminalSession(),TerminalTypeenum
Entry flow: Parse args → configure NSApplication → show notification (if -m provided) → handle notification click → focus terminal → exit
claude-notifier -m "Message" -t "Title" -s "Subtitle"
claude-notifier -m "Message" -i "$ITERM_SESSION_ID" # With session ID for focus-on-click
claude-notifier setup # Auto-configure Claude Code hooks
claude-notifier doctor # Diagnose installation and permission issues
claude-notifier config # Configure preferences (icon, sound) interactively
claude-notifier update # Check for updates and upgrade via Homebrew- Never use em dashes (
—) or spaced hyphens (-) as punctuation. Use commas, colons, or parentheses instead.
- Requires macOS 11.0+
- Uses native frameworks: AppKit, UserNotifications
- Makefile uses
swiftcdirectly (not full SPM build) for the app bundle - App is ad-hoc codesigned during build
- Runs as LSUIElement (no dock icon)
- Requires Automation permission for iTerm2 and Terminal.app (prompted on first notification click)
- IDE editors (VS Code, Cursor, Windsurf, Zed) use Launch Services for focus — no Automation permission needed