Files
msd-core/hooks/gsd-notify.sh
Lex Christopherson 35989f20d7 feat(hooks): add cross-platform completion notification hook
Alerts user when Claude stops (task complete, needs input, etc.)
with context about what completed. Works on Mac (osascript alert),
Linux (notify-send/zenity), and Windows (PowerShell MessageBox).

Follows same optional install pattern as statusline:
- Prompts in interactive mode if existing hook detected
- --force-notify to replace existing
- --no-notify to skip installation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 13:02:01 -06:00

70 lines
2.3 KiB
Bash
Executable File

#!/bin/bash
# GSD Completion Notification Hook
# Cross-platform alert when Claude stops (task complete, needs input, etc.)
input=$(cat)
session_id=$(echo "$input" | jq -r '.session_id // empty')
cwd=$(echo "$input" | jq -r '.cwd // empty')
transcript_path=$(echo "$input" | jq -r '.transcript_path // empty')
# Extract project name
project="Claude Code"
if [[ -n "$cwd" ]]; then
project=$(basename "$cwd")
fi
# Try to get context from GSD state file
message=""
state_file="$cwd/.planning/STATE.md"
if [[ -f "$state_file" ]]; then
phase=$(grep -m1 "^current_phase:" "$state_file" 2>/dev/null | sed 's/^current_phase: *//')
status=$(grep -m1 "^status:" "$state_file" 2>/dev/null | sed 's/^status: *//')
if [[ -n "$phase" && -n "$status" ]]; then
message="Phase $phase: $status"
fi
fi
# Fallback: check todo list for current/completed task
if [[ -z "$message" && -n "$session_id" ]]; then
todo_file=$(ls -t "$HOME/.claude/todos/${session_id}"*.json 2>/dev/null | head -1)
if [[ -f "$todo_file" ]]; then
# Get most recently completed task, or in-progress task
completed=$(jq -r '[.[] | select(.status=="completed")] | last | .content // empty' "$todo_file" 2>/dev/null)
if [[ -n "$completed" ]]; then
message="Completed: $completed"
else
in_progress=$(jq -r '.[] | select(.status=="in_progress") | .content' "$todo_file" 2>/dev/null | head -1)
if [[ -n "$in_progress" ]]; then
message="Paused: $in_progress"
fi
fi
fi
fi
# Fallback: generic message
if [[ -z "$message" ]]; then
message="Ready for input"
fi
# Send notification based on OS
case "$(uname -s)" in
Darwin)
osascript -e "display alert \"GSD: $project\" message \"$message\" as informational" &>/dev/null &
;;
Linux)
if command -v notify-send &>/dev/null; then
notify-send "GSD: $project" "$message" --urgency=normal
elif command -v zenity &>/dev/null; then
zenity --info --title="GSD: $project" --text="$message" &
fi
;;
MINGW*|CYGWIN*|MSYS*)
# Windows via PowerShell
if command -v powershell.exe &>/dev/null; then
powershell.exe -Command "Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.MessageBox]::Show('$message', 'GSD: $project', 'OK', 'Information')" &>/dev/null &
fi
;;
esac
exit 0