Claude Code Hooks with Terminal Notifications πŸ””

Get macOS desktop notifications when Claude Code finishes working using the official Claude Code hooks feature.

Claude Code Hooks macOS Terminal Notifier

🎯 What This Does

This setup configures Claude Code hooks to send native macOS notifications when Claude Code completes any task. No wrapper scripts, no complexityβ€”just proper integration with Claude Code's official hooks system.

Claude Code hooks with terminal-notifier

✨ Features

  • πŸ”” Native macOS notifications when Claude Code stops
  • πŸ“‚ Project context included in notifications
  • 🎡 Customizable sounds (default, Glass, Basso, etc.)
  • 🌍 Global setup works across all projects
  • 🎯 Per-project customization available
  • πŸ“¦ Simple one-script setup

πŸš€ Quick Setup

Prerequisites

Installation

  1. Clone this repository:

    git clone https://github.com/centminmod/terminal-notifier-setup.git
    cd terminal-notifier-setup
  2. Run the setup script:

    chmod +x terminal_notifier_setup.sh
    ./terminal_notifier_setup.sh

That's it! πŸŽ‰

πŸ“‹ What The Setup Does

  1. Installs terminal-notifier via Homebrew (if not already installed)
  2. Creates/updates ~/.claude/settings.json with hooks configuration
  3. Backs up your existing settings
  4. Tests the notification system
  5. Provides customization guidance

πŸ”” How It Works

User-Level Hooks (Global)

The setup configures a Stop event hook in ~/.claude/settings.json:

{
  "hooks": {
    "Stop": [
      {
        "matcher": "*",
        "hooks": [
          {
            "type": "command",
            "command": "terminal-notifier -title \"Claude Code\" -subtitle \"Session Complete\" -message \"Finished working in $(basename \"$PWD\")\" -sound default -timeout 10"
          }
        ]
      }
    ]
  }
}

This hook:

  • Triggers when any Claude Code session completes
  • Shows the project name (current directory) in the notification
  • Plays the default system sound
  • Works in all projects automatically

βš™οΈ Customization

Change Notification Sound

Edit ~/.claude/settings.json and modify the sound parameter:

"command": "terminal-notifier -title \"Claude Code\" -subtitle \"Session Complete\" -message \"Finished working in $(basename \"$PWD\")\" -sound Glass -timeout 10"

Available sounds: default, Basso, Blow, Bottle, Frog, Funk, Glass, Hero, Morse, Ping, Pop, Purr, Sosumi, Submarine, Tink

Change Notification Message

Customize the title, subtitle, and message:

"command": "terminal-notifier -title \"πŸ€– Claude\" -subtitle \"Task Done\" -message \"Completed work in $(basename \"$PWD\")\" -sound Glass -timeout 10"

Add Notification Timeout

Make notifications disappear after a specific time:

"command": "terminal-notifier -title \"Claude Code\" -subtitle \"Session Complete\" -message \"Finished working in $(basename \"$PWD\")\" -sound default -timeout 10"

🎯 Per-Project Notifications

For project-specific notifications, create .claude/settings.json in your project directory:

# In your project directory
mkdir -p .claude
cat > .claude/settings.json << 'EOF'
{
  "hooks": {
    "Stop": [
      {
        "matcher": "*",
        "hooks": [
          {
            "type": "command",
            "command": "terminal-notifier -title \"My Project\" -subtitle \"Build Complete\" -message \"Finished working on $(basename \"$PWD\")\" -sound Glass -timeout 10"
          }
        ]
      }
    ]
  }
}
EOF

Project-level hooks override user-level hooks for that specific project.

πŸ“š Advanced Examples

Multiple Hook Types

You can set up hooks for different Claude Code events:

{
  "hooks": {
    "Stop": [
      {
        "matcher": "*",
        "hooks": [
          {
            "type": "command",
            "command": "terminal-notifier -title \"Claude Code\" -subtitle \"Session Complete\" -message \"Finished working in $(basename \"$PWD\")\" -sound default -timeout 10"
          }
        ]
      }
    ],
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "terminal-notifier -title \"Claude Code\" -subtitle \"Running Command\" -message \"Executing bash command...\" -sound Purr -timeout 3"
          }
        ]
      }
    ]
  }
}

Conditional Notifications

Use shell conditionals for smarter notifications:

{
  "type": "command",
  "command": "if [ -f package.json ]; then terminal-notifier -title \"Node.js Project\" -message \"Claude finished working on $(basename \"$PWD\")\" -sound Glass -timeout 10; else terminal-notifier -title \"Claude Code\" -message \"Finished working in $(basename \"$PWD\")\" -sound default -timeout 10; fi"
}

πŸ”§ Troubleshooting

Notifications Not Appearing

  1. Check System Preferences β†’ Notifications
  2. Grant terminal-notifier permission to send notifications
  3. Test manually: terminal-notifier -message "Test"

Settings Not Taking Effect

  1. Restart Claude Code after changing settings
  2. Check JSON syntax in your settings file
  3. Verify file path: ~/.claude/settings.json

Command Not Found

If you get "command not found" errors, ensure terminal-notifier is installed:

brew install terminal-notifier

Permission Denied

Make sure the setup script is executable:

chmod +x terminal_notifier_setup.sh

πŸ” Understanding Claude Code Hooks

Claude Code hooks are event-driven commands that execute at specific points in Claude's lifecycle:

  • PreToolUse: Before Claude uses a tool
  • PostToolUse: After Claude uses a tool
  • Stop: When Claude finishes responding
  • Notification: On Claude Code notifications

Hooks are configured in:

  • ~/.claude/settings.json (user-level, applies globally)
  • <project>/.claude/settings.json (project-level, applies to that project only)

πŸ“– Learn More

🀝 Contributing

  1. Fork this repository
  2. Create a feature branch
  3. Make your changes
  4. Test on macOS
  5. Submit a pull request

πŸ“ License

MIT License - see LICENSE file for details.