Last active
December 24, 2025 13:28
-
-
Save 2357gi/b80b37098cc9104aac5c1b1fb00a15d2 to your computer and use it in GitHub Desktop.
claude-notification.sh
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # Claude Code hook script for rich macOS notifications | |
| # This script receives notification events from Claude Code via stdin (JSON format) | |
| # and sends rich macOS notifications with custom icons and context | |
| # Read JSON input from stdin | |
| input=$(cat) | |
| # Parse notification details | |
| notification_type=$(echo "$input" | jq -r '.notification_type // "unknown"') | |
| message=$(echo "$input" | jq -r '.message // "Claude Code needs your input"') | |
| cwd=$(echo "$input" | jq -r '.cwd // ""') | |
| # Extract directory name for display | |
| dir_name=$(basename "$cwd") | |
| # Build rich notification message with context | |
| case "$notification_type" in | |
| "permission_prompt") | |
| subtitle="⚠️ 許可が必要です" | |
| rich_message=$'ツールの実行許可を求めています\n📁 '"$dir_name" | |
| ;; | |
| "tool_permission_prompt") | |
| subtitle="🔧 ツール実行許可" | |
| rich_message=$'ツールの実行を待っています\n📁 '"$dir_name" | |
| ;; | |
| "user_question_prompt") | |
| subtitle="❓ 質問があります" | |
| rich_message=$'あなたの回答を待っています\n📁 '"$dir_name" | |
| ;; | |
| "idle_prompt") | |
| subtitle="⏸️ 入力待ち" | |
| rich_message=$'次の指示を待っています\n📁 '"$dir_name" | |
| ;; | |
| *) | |
| subtitle="[$notification_type]" | |
| rich_message=$''"$message"$'\n📁 '"$dir_name" | |
| ;; | |
| esac | |
| # Claude Code icon path | |
| ICON_PATH="$HOME/.claude/icons/claude-ai-icon.png" | |
| # Get tmux environment information | |
| PANE_ID="${TMUX_PANE}" | |
| SESSION_NAME=$(tmux display-message -p '#{session_name}' 2>/dev/null || echo "") | |
| # Extract tmux socket path from $TMUX variable (format: /path/to/socket,pid,session_id) | |
| TMUX_SOCKET=$(echo "$TMUX" | cut -d',' -f1) | |
| # Detect execution environment | |
| ENVIRONMENT="unknown" | |
| if [ "$CLAUDE_CODE_ENTRYPOINT" = "claude-vscode" ]; then | |
| ENVIRONMENT="vscode" | |
| WORKSPACE_PATH="${VSCODE_CWD:-$PWD}" | |
| elif [ -n "$VSCODE_CLI" ]; then | |
| ENVIRONMENT="vscode" | |
| WORKSPACE_PATH="${VSCODE_CWD:-$PWD}" | |
| elif [ -n "$PANE_ID" ] && [ -n "$SESSION_NAME" ] && [ -n "$TMUX_SOCKET" ]; then | |
| ENVIRONMENT="tmux" | |
| else | |
| ENVIRONMENT="generic" | |
| fi | |
| # Debug logging | |
| if [ -n "$CLAUDE_DEBUG" ]; then | |
| echo "$(date): environment=$ENVIRONMENT, notification_type=$notification_type, message=$message, workspace=$WORKSPACE_PATH, PANE_ID=$PANE_ID" >> /tmp/claude-hook-debug.log | |
| fi | |
| # VSCode environment notification | |
| if [ "$ENVIRONMENT" = "vscode" ]; then | |
| if command -v terminal-notifier >/dev/null 2>&1; then | |
| terminal-notifier \ | |
| -title "Claude Code" \ | |
| -message "$rich_message" \ | |
| -subtitle "$subtitle" \ | |
| -group "claude-code-vscode" \ | |
| -contentImage "$ICON_PATH" \ | |
| -activate "com.microsoft.VSCode" \ | |
| -execute "$HOME/.claude/hooks/focus-vscode.sh '$WORKSPACE_PATH'" | |
| else | |
| osascript -e "display notification \"$rich_message\" with title \"Claude Code\" subtitle \"$subtitle\"" | |
| osascript -e 'tell application "Visual Studio Code" to activate' 2>/dev/null | |
| fi | |
| exit 0 | |
| fi | |
| # tmux environment notification | |
| if [ "$ENVIRONMENT" = "tmux" ]; then | |
| terminal-notifier \ | |
| -title "Claude Code" \ | |
| -message "$rich_message" \ | |
| -subtitle "$subtitle" \ | |
| -group "claude-code-$SESSION_NAME-$PANE_ID" \ | |
| -contentImage "$ICON_PATH" \ | |
| -activate "com.apple.Terminal" \ | |
| -execute "$HOME/.claude/hooks/focus-tmux-pane.sh '$SESSION_NAME' '$PANE_ID' '$TMUX_SOCKET'" | |
| exit 0 | |
| fi | |
| # Generic fallback - standard macOS notification | |
| if command -v terminal-notifier >/dev/null 2>&1; then | |
| terminal-notifier \ | |
| -title "Claude Code" \ | |
| -message "$rich_message" \ | |
| -subtitle "$subtitle" \ | |
| -contentImage "$ICON_PATH" | |
| else | |
| osascript -e "display notification \"$rich_message\" with title \"Claude Code\" subtitle \"$subtitle\"" | |
| fi | |
| exit 0 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # Focus handler script for tmux pane notifications | |
| # This script is executed when a user clicks on a Claude Code notification | |
| # It activates Terminal.app and focuses the specific tmux session/pane | |
| # Set PATH to ensure tmux is found | |
| export PATH="/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin:$PATH" | |
| SESSION_NAME="$1" | |
| PANE_ID="$2" | |
| TMUX_SOCKET="$3" | |
| # Debug logging (uncomment for troubleshooting) | |
| # echo "$(date): Focusing SESSION_NAME=$SESSION_NAME, PANE_ID=$PANE_ID, TMUX_SOCKET=$TMUX_SOCKET" >> /tmp/claude-hook-debug.log | |
| # echo "$(date): PATH=$PATH" >> /tmp/claude-hook-debug.log | |
| # echo "$(date): tmux location: $(which tmux)" >> /tmp/claude-hook-debug.log | |
| if [ -n "$SESSION_NAME" ] && [ -n "$PANE_ID" ] && [ -n "$TMUX_SOCKET" ]; then | |
| # Use the tmux socket to connect to the server | |
| # Get all tmux clients and switch each one | |
| clients=$(tmux -S "$TMUX_SOCKET" list-clients -F '#{client_tty}' 2>&1) | |
| if [ -n "$clients" ] && [ "$clients" != "error"* ]; then | |
| echo "$clients" | while read -r client_tty; do | |
| # Switch the client to the target session | |
| tmux -S "$TMUX_SOCKET" switch-client -t "$SESSION_NAME" -c "$client_tty" 2>/dev/null | |
| # Select the target pane (use pane ID directly) | |
| tmux -S "$TMUX_SOCKET" select-pane -t "$PANE_ID" 2>/dev/null | |
| done | |
| fi | |
| # Activate Terminal.app | |
| osascript -e 'tell application "Terminal" to activate' 2>/dev/null | |
| else | |
| osascript -e 'tell application "Terminal" to activate' 2>/dev/null | |
| fi | |
| exit 0 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # VSCode focus handler for Claude Code notifications | |
| # Activates the specific VSCode workspace where Claude Code is running | |
| export PATH="/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin:$PATH" | |
| WORKSPACE_PATH="$1" | |
| # Debug logging | |
| if [ -n "$CLAUDE_DEBUG" ]; then | |
| echo "$(date): Focusing VSCode workspace: $WORKSPACE_PATH" >> /tmp/claude-hook-debug.log | |
| fi | |
| # If workspace path is provided, open it with code CLI | |
| if [ -n "$WORKSPACE_PATH" ] && [ -d "$WORKSPACE_PATH" ]; then | |
| if command -v code >/dev/null 2>&1; then | |
| code "$WORKSPACE_PATH" 2>/dev/null | |
| fi | |
| fi | |
| # Always activate VSCode (fallback if code command fails) | |
| osascript -e 'tell application "Visual Studio Code" to activate' 2>/dev/null | |
| exit 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment