--- title: Claude Code Hooks description: Set up notifications for Claude Code using cmux hooks --- # Claude Code Hooks cmux integrates with [Claude Code](https://docs.anthropic.com/en/docs/claude-code) via hooks to notify you when tasks complete or when Claude needs attention. ## Detecting cmux Before sending notifications, you should detect if you're running inside cmux to avoid conflicts with other terminals. ### Detection Methods **1. Check for the socket:** ```bash [ -S /tmp/cmux.sock ] && echo "In cmux" ``` **2. Check for the CLI:** ```bash command -v cmux &>/dev/null && echo "cmux available" ``` **3. Check the TERM_PROGRAM environment variable:** ```bash [ "$TERM_PROGRAM" = "ghostty" ] && [ -S /tmp/cmux.sock ] && echo "In cmux" ``` cmux sets `TERM_PROGRAM=ghostty` since it's built on Ghostty. Use the socket check to distinguish from regular Ghostty. ## Setting Up Hooks Claude Code supports hooks that run on specific events. Add these to your `~/.claude/settings.json`: ```json { "hooks": { "PostToolUse": [ { "matcher": "Task", "hooks": [ "/path/to/cmux-notify.sh" ] } ], "Stop": [ "/path/to/cmux-notify.sh" ] } } ``` ## Notification Hook Script Create a script that checks for cmux and sends notifications: ```bash #!/bin/bash # ~/.claude/hooks/cmux-notify.sh # Only proceed if we're in cmux if [ ! -S /tmp/cmux.sock ]; then exit 0 fi # Parse the hook event from stdin (Claude Code passes JSON) EVENT=$(cat) # Extract event type and details EVENT_TYPE=$(echo "$EVENT" | jq -r '.event // "unknown"') TOOL_NAME=$(echo "$EVENT" | jq -r '.tool_name // ""') SESSION=$(echo "$EVENT" | jq -r '.session_id // ""' | cut -c1-8) case "$EVENT_TYPE" in "Stop") cmux notify \ --title "Claude Code" \ --subtitle "Task Complete" \ --body "Session $SESSION finished" ;; "PostToolUse") if [ "$TOOL_NAME" = "Task" ]; then cmux notify \ --title "Claude Code" \ --subtitle "Agent Finished" \ --body "Task agent completed in session $SESSION" fi ;; esac ``` Make it executable: ```bash chmod +x ~/.claude/hooks/cmux-notify.sh ``` ## Example Configurations ### Notify on All Completions Get notified whenever Claude Code finishes a task: ```json { "hooks": { "Stop": [ "~/.claude/hooks/cmux-notify.sh" ] } } ``` ### Notify on Long-Running Tasks Only notify for Task tool completions (agent subprocesses): ```json { "hooks": { "PostToolUse": [ { "matcher": "Task", "hooks": ["~/.claude/hooks/cmux-notify.sh"] } ] } } ``` ### Notify on Errors Add error notifications: ```bash #!/bin/bash # cmux-notify.sh with error handling if [ ! -S /tmp/cmux.sock ]; then exit 0 fi EVENT=$(cat) EVENT_TYPE=$(echo "$EVENT" | jq -r '.event // "unknown"') ERROR=$(echo "$EVENT" | jq -r '.error // ""') if [ -n "$ERROR" ] && [ "$ERROR" != "null" ]; then cmux notify \ --title "Claude Code Error" \ --body "$ERROR" elif [ "$EVENT_TYPE" = "Stop" ]; then cmux notify \ --title "Claude Code" \ --body "Task complete" fi ``` ## Advanced: Conditional Notifications Only notify if the terminal is not focused: ```bash #!/bin/bash # cmux-notify.sh with focus detection if [ ! -S /tmp/cmux.sock ]; then exit 0 fi # cmux automatically suppresses notifications for focused tabs, # so we can always send - it will handle suppression for us EVENT=$(cat) EVENT_TYPE=$(echo "$EVENT" | jq -r '.event // "unknown"') if [ "$EVENT_TYPE" = "Stop" ]; then cmux notify \ --title "Claude Code" \ --subtitle "Ready" \ --body "Waiting for your input" fi ``` ## Using OSC Sequences Directly If you prefer not to use the CLI, you can emit OSC sequences directly: ```bash #!/bin/bash # Direct OSC notification (no CLI needed) if [ ! -S /tmp/cmux.sock ]; then exit 0 fi EVENT=$(cat) EVENT_TYPE=$(echo "$EVENT" | jq -r '.event // "unknown"') if [ "$EVENT_TYPE" = "Stop" ]; then # OSC 777 notification printf '\e]777;notify;Claude Code;Task complete\a' fi ``` ## Full Example Setup 1. Create the hooks directory: ```bash mkdir -p ~/.claude/hooks ``` 2. Create the notification script: ```bash cat > ~/.claude/hooks/cmux-notify.sh << 'EOF' #!/bin/bash # cmux notification hook for Claude Code # Skip if not in cmux [ -S /tmp/cmux.sock ] || exit 0 EVENT=$(cat) EVENT_TYPE=$(echo "$EVENT" | jq -r '.event // "unknown"') TOOL=$(echo "$EVENT" | jq -r '.tool_name // ""') case "$EVENT_TYPE" in "Stop") cmux notify --title "Claude Code" --body "Session complete" ;; "PostToolUse") [ "$TOOL" = "Task" ] && cmux notify --title "Claude Code" --body "Agent finished" ;; esac EOF chmod +x ~/.claude/hooks/cmux-notify.sh ``` 3. Configure Claude Code: ```bash cat > ~/.claude/settings.json << 'EOF' { "hooks": { "Stop": ["~/.claude/hooks/cmux-notify.sh"], "PostToolUse": [ { "matcher": "Task", "hooks": ["~/.claude/hooks/cmux-notify.sh"] } ] } } EOF ``` 4. Restart Claude Code to apply the hooks. Now you'll receive desktop notifications in cmux whenever Claude Code finishes a task or needs attention.