cmuxterm

Claude Code Hooks

Set up notifications for Claude Code using cmuxterm hooks

Claude Code Hooks

cmuxterm integrates with Claude Code via hooks to notify you when tasks complete or when Claude needs attention.

Detecting cmuxterm

Before sending notifications, you should detect if you're running inside cmuxterm to avoid conflicts with other terminals.

Detection Methods

1. Check for the socket:

[ -S /tmp/cmuxterm.sock ] && echo "In cmuxterm"

2. Check for the CLI:

command -v cmuxterm &>/dev/null && echo "cmuxterm available"

3. Check the TERM_PROGRAM environment variable:

[ "$TERM_PROGRAM" = "ghostty" ] && [ -S /tmp/cmuxterm.sock ] && echo "In cmuxterm"

cmuxterm 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:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Task",
        "hooks": [
          "/path/to/cmuxterm-notify.sh"
        ]
      }
    ],
    "Stop": [
      "/path/to/cmuxterm-notify.sh"
    ]
  }
}

Notification Hook Script

Create a script that checks for cmuxterm and sends notifications:

#!/bin/bash
# ~/.claude/hooks/cmuxterm-notify.sh
 
# Only proceed if we're in cmuxterm
if [ ! -S /tmp/cmuxterm.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")
        cmuxterm notify \
            --title "Claude Code" \
            --subtitle "Task Complete" \
            --body "Session $SESSION finished"
        ;;
    "PostToolUse")
        if [ "$TOOL_NAME" = "Task" ]; then
            cmuxterm notify \
                --title "Claude Code" \
                --subtitle "Agent Finished" \
                --body "Task agent completed in session $SESSION"
        fi
        ;;
esac

Make it executable:

chmod +x ~/.claude/hooks/cmuxterm-notify.sh

Example Configurations

Notify on All Completions

Get notified whenever Claude Code finishes a task:

{
  "hooks": {
    "Stop": [
      "~/.claude/hooks/cmuxterm-notify.sh"
    ]
  }
}

Notify on Long-Running Tasks

Only notify for Task tool completions (agent subprocesses):

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Task",
        "hooks": ["~/.claude/hooks/cmuxterm-notify.sh"]
      }
    ]
  }
}

Notify on Errors

Add error notifications:

#!/bin/bash
# cmuxterm-notify.sh with error handling
 
if [ ! -S /tmp/cmuxterm.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
    cmuxterm notify \
        --title "Claude Code Error" \
        --body "$ERROR"
elif [ "$EVENT_TYPE" = "Stop" ]; then
    cmuxterm notify \
        --title "Claude Code" \
        --body "Task complete"
fi

Advanced: Conditional Notifications

Only notify if the terminal is not focused:

#!/bin/bash
# cmuxterm-notify.sh with focus detection
 
if [ ! -S /tmp/cmuxterm.sock ]; then
    exit 0
fi
 
# cmuxterm 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
    cmuxterm 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:

#!/bin/bash
# Direct OSC notification (no CLI needed)
 
if [ ! -S /tmp/cmuxterm.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:
mkdir -p ~/.claude/hooks
  1. Create the notification script:
cat > ~/.claude/hooks/cmuxterm-notify.sh << 'EOF'
#!/bin/bash
# cmuxterm notification hook for Claude Code
 
# Skip if not in cmuxterm
[ -S /tmp/cmuxterm.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")
        cmuxterm notify --title "Claude Code" --body "Session complete"
        ;;
    "PostToolUse")
        [ "$TOOL" = "Task" ] && cmuxterm notify --title "Claude Code" --body "Agent finished"
        ;;
esac
EOF
chmod +x ~/.claude/hooks/cmuxterm-notify.sh
  1. Configure Claude Code:
cat > ~/.claude/settings.json << 'EOF'
{
  "hooks": {
    "Stop": ["~/.claude/hooks/cmuxterm-notify.sh"],
    "PostToolUse": [
      {
        "matcher": "Task",
        "hooks": ["~/.claude/hooks/cmuxterm-notify.sh"]
      }
    ]
  }
}
EOF
  1. Restart Claude Code to apply the hooks.

Now you'll receive desktop notifications in cmuxterm whenever Claude Code finishes a task or needs attention.

On this page