Files
claudetools/.claude/scripts/check-messages.sh
Mike Swanson ebd1d174fb fix: auto-create .claude/current-mode if missing for coordination hooks
The UserPromptSubmit hook requires .claude/current-mode to determine work mode
and gate coordination lock checks. This file is machine-local (gitignored) but
had no initialization logic for fresh clones, causing hooks to fail.

Changes:
- check-messages.sh: Added auto-creation logic with "general" as default
- CLAUDE.md: Documented auto-initialization behavior
- ONBOARDING.md: Added machine-local configuration section
- session-logs/2026-05-19-session.md: Documented investigation and fix

Impact:
- Fixes coordination hooks on all machines
- Prevents first-clone hook failures
- No manual setup required
- Backwards compatible

Resolves: "cood hook seems to be broken on all my machines"

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-19 09:47:28 -07:00

93 lines
4.1 KiB
Bash

#!/usr/bin/env bash
# UserPromptSubmit hook — injects unread coord messages and (in dev mode) active locks.
SESSION="$(hostname)/claude-main"
API="http://172.16.3.30:8001"
SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
MODE_FILE="${SCRIPT_DIR}/current-mode"
# --- Initialize mode file if missing -----------------------------------------
# The mode file is machine-local (gitignored) and required by this hook.
# If missing, create it with "general" as the default mode.
if [ ! -f "$MODE_FILE" ]; then
echo "general" > "$MODE_FILE"
echo "[INFO] Created .claude/current-mode with default mode: general" >&2
fi
# Read short username alias from identity.json (if present)
IDENTITY_FILE="${SCRIPT_DIR}/identity.json"
USER_ALIAS=""
if [ -f "$IDENTITY_FILE" ]; then
USER_ALIAS=$(jq -r '.user // empty' "$IDENTITY_FILE" 2>/dev/null)
fi
# --- Unread messages ---------------------------------------------------------
# Query for messages addressed to full session ID
result=$(curl -s --connect-timeout 3 "${API}/api/coord/messages?to_session=${SESSION}&unread_only=true" 2>/dev/null)
# Also query for messages addressed to the short username alias (e.g. "howard")
result_alias=""
if [ -n "$USER_ALIAS" ] && [ "$USER_ALIAS" != "$SESSION" ]; then
result_alias=$(curl -s --connect-timeout 3 "${API}/api/coord/messages?to_session=${USER_ALIAS}&unread_only=true" 2>/dev/null)
fi
# Merge both result sets (combine .messages arrays, recompute total)
if [ -n "$result_alias" ]; then
alias_msgs=$(echo "$result_alias" | jq '.messages // []' 2>/dev/null)
if [ -n "$alias_msgs" ] && [ "$alias_msgs" != "[]" ] && [ "$alias_msgs" != "null" ]; then
if [ -n "$result" ]; then
result=$(echo "$result" "$result_alias" | jq -s '{total: (.[0].total + .[1].total), messages: (.[0].messages + .[1].messages)}' 2>/dev/null)
else
result="$result_alias"
fi
fi
fi
if [ -n "$result" ]; then
count=$(echo "$result" | jq '.total' 2>/dev/null)
if [ -n "$count" ] && [ "$count" -gt 0 ]; then
echo ""
echo "============================================================"
echo "UNREAD COORD MESSAGES ($count)"
echo "============================================================"
echo "$result" | jq -r '.messages[] | "FROM: \(.from_session)\nDATE: \(.created_at)\nSUBJECT: \(.subject)\n\nMESSAGE:\n\(.body)\n---"'
echo "============================================================"
echo ""
# Fire a Windows toast so the user sees it even if not watching the terminal
toast_body=$(echo "$result" | jq -r '[.messages[] | .from_session + ": " + .subject] | join(", ")' | tr -d '\r')
notify_ps1=$(cygpath -w "${SCRIPT_DIR}/scripts/notify.ps1" 2>/dev/null || echo "${SCRIPT_DIR}/scripts/notify.ps1" | sed 's|^/\([a-zA-Z]\)/|\1:/|')
powershell.exe -NonInteractive -NoProfile -Command \
"& '$notify_ps1' -Title 'ClaudeTools: $count new message(s)' -Message '$toast_body'" \
>/dev/null 2>&1 &
# Mark all fetched messages as read immediately
echo "$result" | jq -r '.messages[].id' | tr -d '\r' | while read -r id; do
curl -s -X PUT "${API}/api/coord/messages/${id}/read" >/dev/null 2>&1
done
fi
fi
# --- Active locks (dev mode only) -------------------------------------------
current_mode=""
[ -f "$MODE_FILE" ] && current_mode=$(cat "$MODE_FILE" | tr -d '[:space:]')
if [ "$current_mode" = "dev" ]; then
locks=$(curl -s --connect-timeout 3 "${API}/api/coord/locks" 2>/dev/null)
if [ -n "$locks" ]; then
lock_count=$(echo "$locks" | jq '.total' 2>/dev/null)
if [ -n "$lock_count" ] && [ "$lock_count" -gt 0 ]; then
echo ""
echo "============================================================"
echo "[WARNING] ACTIVE LOCKS ($lock_count) — check before editing"
echo "============================================================"
echo "$locks" | jq -r '.locks[] | "[DEV MODE] LOCK: \(.project_key) / \(.resource)\n Held by: \(.session_id)\n Reason: \(.description // "none")\n Expires: \(.expires_at // "unknown")\n---"'
echo "============================================================"
echo ""
fi
fi
fi
exit 0