Enhanced Claude Code notification hooks with adorable cat sounds and better styling for macOS.
- 🐱 Adorable cat meow for all notifications
- 🎨 Enhanced styling with emojis and better formatting
- 🧠 Intelligent categorization of notifications (success, error, warning, etc.)
- 🛑 Special stop notifications with the same adorable cat meow
- 🍎 macOS optimized using native notification system
- 🤖 Automatic environment detection - works seamlessly in SSH, CI, and pipe environments
# Install globally
npm install -g cat-ccnotify-hook
# Run the installer
cat-ccnotify-installThis will automatically:
- Install the package globally
- Create the
~/.claudedirectory if needed - Update
~/.claude/settings.jsonwith the correct hook configuration - Configure Claude Code to use cat notifications
- Type
/hooksin Claude Code - Press
ESCimmediately
-
Clone this repository:
git clone https://github.com/cat-ccnotify/cat-ccnotify-hook.git cd cat-ccnotify-hook -
Install dependencies:
npm install
-
Run the installer:
npm run install-hooks
Test your installation to make sure everything works:
# Simple notification test (recommended)
cat-notify
# Custom notification
cat-notify "My Title" "My custom message"
# Test actual hook functionality with Claude Code data format
cat-notify --notification-hook
cat-notify --stop-hook
# Test hooks via npm command
cat-ccnotify-test
# Or manually test hooks
node hooks/notification-hook.js
echo '{"title":"Test","message":"Session ended"}' | node hooks/stop-hook.cjsYou should see notifications with:
- 🐱 Cat meow sounds
- 📱 Native macOS notifications
- 🎨 Appropriate emojis (✅ for success, ❌ for errors, etc.)
- 📝 Your actual message content
All notifications play the same adorable cat meow sound! 🐱
The system intelligently analyzes your notification content and automatically adds appropriate emojis:
- ✅ Success:
complete,success,passed,done,deployed,published - ❌ Error:
error,failed,crash,exception,cannot,invalid ⚠️ Warning:warning,deprecated,caution,should,might- 💡 Info: General information and status updates
- ⏳ Progress:
running,processing,installing,building,loading - 🔄 Git:
commit,push,pull,merge,branch,repository - 🏗️ Build:
build,compile,bundle,webpack,typescript - 🧪 Test:
test,spec,jest,coverage,assertion - 🚀 Deploy:
deploy,release,production,staging,live - 📦 NPM:
npm,yarn,package,dependency,install - 📄 File:
file,directory,write,read,created,modified
Instead of showing generic messages, you'll see your actual notification content:
- "✅ Tests Passed - All 25 tests completed successfully!"
- "❌ Git Push Failed - Permission denied to repository"
- "🏗️ Build Complete - TypeScript compilation finished"
Note: All categories use the same adorable cat meow sound. Future versions may include category-specific sounds!
The hooks are automatically configured in ~/.claude/settings.json. You can view the current configuration:
cat ~/.claude/settings.json | jq '.hooks'The hooks are configured in the new Claude Code format:
{
"hooks": {
"Notification": [
{
"type": "command",
"command": "node /path/to/notification-hook.js",
"description": "Cat-themed notification with meow sound"
}
],
"Stop": [
{
"type": "command",
"command": "node /path/to/stop-hook.cjs",
"description": "Cat-themed session end notification"
}
]
}
}After installation or making manual changes:
- Type
/hooksin Claude Code - Press
ESCimmediately to reload settings
You can customize the notification behavior with these environment variables:
# Force console output (echo) instead of system notifications
export CAT_CCNOTIFY_FORCE_CONSOLE=true
# Enable debug logging
export CAT_CCNOTIFY_DEBUG=true🤖 Automatic Environment Detection: The system automatically detects when to use console output in these scenarios:
- SSH connections without X11 forwarding (
SSH_CONNECTIONwithoutDISPLAY) - CI environments (GitHub Actions, GitLab CI, Jenkins, Travis, CircleCI, etc.)
- Non-TTY environments (pipes, redirects, background processes)
Examples:
# SSH connection - automatically uses console output
ssh user@server
claude-code # → 🐱 Console notifications
# CI environment - automatically uses console output
# GitHub Actions, GitLab CI, etc.
claude-code # → 🐱 Console notifications
# Pipe usage - automatically uses console output
claude-code | tee output.log # → 🐱 Console notifications
# Normal desktop usage - uses GUI notifications
claude-code # → Native macOS notifications + soundManual override (rarely needed):
# Force console output even in GUI environments
export CAT_CCNOTIFY_FORCE_CONSOLE=true
# Or temporarily
CAT_CCNOTIFY_FORCE_CONSOLE=true claude-codePriority order:
CAT_CCNOTIFY_FORCE_CONSOLE=true(manual override)- Automatic environment detection
- Platform-specific GUI notifications
- Console fallback
cat-ccnotify-hook/
├── package.json # Package configuration and npm scripts
├── README.md # This documentation
├── INSTALL.md # Detailed installation guide
├── PUBLISHING.md # npm publishing instructions
├── jest.config.js # Test configuration
├── .npmignore # npm package exclusions
├── bin/
│ └── cat-notify # Command line testing tool
├── hooks/ # Core hook implementations
│ ├── notification-hook.js # Smart notification processor
│ ├── stop-hook.cjs # Session end handler
│ └── hooks.json # Hook configuration template
├── lib/ # Shared utilities
│ ├── shell-executor.js # Secure command execution (ES)
│ ├── shell-executor.cjs # Secure command execution (CJS)
│ ├── error-handler.js # Comprehensive error handling (ES)
│ └── error-handler.cjs # Comprehensive error handling (CJS)
├── sounds/ # Audio assets
│ └── cat-meow-1-fx-323465.mp3 # Adorable cat meow sound
├── scripts/ # Management tools
│ ├── install-hooks.js # Intelligent installer
│ ├── uninstall-hooks.js # Clean uninstaller
│ └── test-hooks.js # Manual testing utility
└── test/ # Test suite
├── unit/ # Unit tests
│ ├── shell-executor.test.js # Shell execution tests
│ └── error-handler.test.js # Error handling tests
└── e2e/ # End-to-end tests
└── notification-flow.test.js # Full workflow tests
hooks/notification-hook.js: Main notification processor with smart categorizationhooks/stop-hook.cjs: Handles Claude Code session terminationlib/shell-executor.js: Secure execution of macOS commandslib/error-handler.js: Comprehensive error handling and loggingscripts/install-hooks.js: Automatic hook configuration setuptest/: Complete test suite with unit and E2E tests
# Test hooks with different notification types
node hooks/notification-hook.js "Tests Passed" "All 25 tests completed successfully!"
node hooks/notification-hook.js "Build Failed" "TypeScript compilation errors found"
node hooks/notification-hook.js "Git Push" "Successfully pushed to origin/main"
# Test with JSON input
echo '{"title":"Deploy Complete","message":"Application deployed to production"}' | node hooks/notification-hook.js
# Test stop hook
echo '{"title":"Session Ended","message":"Claude Code session terminated"}' | node hooks/stop-hook.cjs
# Run test suite
npm test
npm run test:unit
npm run test:e2e
# Test with debug mode
CAT_CCNOTIFY_DEBUG=true node hooks/notification-hook.js "Debug Test" "Testing with detailed logging"- Add audio files to the
sounds/directory (supported: .mp3, .wav, .m4a, .aiff, .aac) - Update hook files to reference new sounds in the
sendEnhancedNotificationfunction - Test audio playback:
afplay sounds/your-new-sound.mp3 - Test integration:
npm test
- Modify emoji mappings in
enhanceNotificationStyle()function - Add new categories in
analyzeNotificationContent()function - Adjust content patterns to match your workflow
- Test changes: Run notification tests to verify new behavior
# If installed via npm:
cat-ccnotify-uninstall
# If installed locally:
cd /path/to/cat-ccnotify-hook
npm run uninstall-hooks
# Or manually edit ~/.claude/settings.json to remove the notification and stop hook entriesThis will restore Claude Code to use default notifications.
- Claude Code triggers a notification (file saved, command completed, error occurred, etc.)
- Hook receives data via multiple input methods:
- Environment variables (
CLAUDE_NOTIFICATION,NOTIFICATION_TITLE) - JSON data through stdin
- Plain text through stdin
- Command line arguments
- Environment variables (
- Content analysis - AI categorizes the notification (success, error, warning, git, build, etc.)
- Enhancement applied:
- Appropriate emoji added (✅, ❌,
⚠️ , 🏗️, etc.) - Content formatting and truncation
- Context-aware styling
- Appropriate emoji added (✅, ❌,
- Native macOS notification displayed using
osascript - Cat sound plays using
afplay
- Claude Code session ends
- Stop hook triggered with session metadata
- Special notification shown: "🐱 Claude Code - セッション終了: [session info]"
- Cat meow plays to signal session end
The hook intelligently handles various input formats:
// JSON format
{"title":"Build Complete","message":"Compilation successful"}
// Plain text
"Tests passed - 25/25 successful"
// Multi-line
"Git Push Failed\nPermission denied to repository"
// Command args
node notification-hook.js "Title" "Message"For troubleshooting, enable debug mode to see comprehensive logging:
# Enable debug mode for a single test
CAT_CCNOTIFY_DEBUG=true node hooks/notification-hook.js "Debug Test" "Testing notification"
# Set globally for your session
export CAT_CCNOTIFY_DEBUG=true
# View debug logs
tail -f ~/.claude/cat-ccnotify/notification-hook.log
tail -f ~/.claude/cat-ccnotify/stop-hook.log
# View recent debug activity
tail -20 ~/.claude/cat-ccnotify/notification-hook.log- Environment Analysis: All Claude-related environment variables
- Input Processing: Raw stdin, JSON parsing, command line arguments
- Content Analysis: How notifications are categorized
- Enhancement Process: Emoji addition and message formatting
- Execution Flow: Each step of the notification process
- Error Details: Comprehensive error reporting and stack traces
- System Info: Process arguments, working directory, file paths
=== Debug Information ===
Process arguments: ["node", "/path/to/notification-hook.js", "Tests Passed", "All tests successful"]
Env CLAUDECODE: "1"
Using command line arguments: ["Tests Passed", "All tests successful"]
=== Final Result ===
Title: "Tests Passed"
Message: "All tests successful"
Level: "info"
Analyzed notification type: success
Enhanced notification - Title: "✅ Tests Passed", Message: "All tests successful"
- Check audio file:
ls sounds/cat-meow-1-fx-323465.mp3 - Test audio manually:
afplay sounds/cat-meow-1-fx-323465.mp3 - Check macOS sound settings and volume levels
- Verify permissions: macOS may block audio from scripts
- Check notification permissions: System Settings → Notifications → Terminal/iTerm
- Test manually:
osascript -e 'display notification "Test" with title "Test"' - Verify hooks config:
cat ~/.claude/settings.json | grep -A 20 hooks - Check Claude Code version: Ensure you're using a compatible version
-
Verify installation:
which claude cat ~/.claude/settings.json | grep hooks
-
Reload hooks: Type
/hooksin Claude Code, then press ESC -
Enable debug mode:
export CAT_CCNOTIFY_DEBUG=true # Test a notification to generate logs echo '{"title":"Debug","message":"Test"}' | node hooks/notification-hook.js # Check logs tail -f ~/.claude/cat-ccnotify/notification-hook.log
-
Check file permissions:
ls -la ~/.claude/settings.json -
Verify hook paths: Ensure the paths in settings.json point to existing files
- "Command not found": Use full paths in settings.json
- "Permission denied": Check file permissions with
chmod +x hooks/*.js - "Module not found": Ensure all dependencies are installed
- Silent failures: Enable debug mode to see detailed error messages
- Script opens when clicking notification: This is a macOS behavior when notifications are sent from scripts
Issue: Clicking on notifications may open the script file in your default editor.
Why this happens: macOS associates notifications with their source. When sent from a script, clicking the notification opens that script.
Solutions:
-
Ignore the behavior: The notification functionality works perfectly; you can simply ignore clicking on them.
-
Install terminal-notifier (recommended):
# Install via Homebrew brew install terminal-notifier # The hooks will automatically use it if available
-
Change default app for .js files:
- Right-click any .js file → "Get Info"
- Under "Open with", select a different app
- Click "Change All..."
-
Disable notification clicking:
- System Settings → Notifications → Script Editor (or Terminal)
- Turn off "Allow Notifications"
- This prevents the script from opening but may disable other notifications
Note: This is a macOS system behavior, not a bug in cat-ccnotify-hook. The notifications work correctly; the click behavior is just a side effect of how macOS handles script-generated notifications.
# Enable debug mode
export CAT_CCNOTIFY_DEBUG=true
# Or set it permanently in your shell profile
echo 'export CAT_CCNOTIFY_DEBUG=true' >> ~/.zshrc
# View logs (only created when debug mode is enabled)
tail -f ~/.claude/cat-ccnotify/notification-hook.log
tail -f ~/.claude/cat-ccnotify/stop-hook.log
# View all cat-ccnotify logs
tail -f ~/.claude/cat-ccnotify/*.log- macOS (uses
afplayandosascript) - Node.js 16+
- Claude Code CLI installed
- Fork the repository
- Create a feature branch
- Make your changes
- Test thoroughly
- Submit a pull request
MIT License - see LICENSE file for details.
- Cat sound effects from freesound.org
- Built for the Claude Code CLI by Anthropic
- Inspired by the need for more delightful notifications
Made with 💝 and 🐱 for Claude Code users who love cats!