Comprehensive standalone guide + setup script so anyone can replicate the Claude Code overnight automation system for their own projects. Includes loop.sh, hook templates, plan/prompt templates, and an interactive setup script. No project-specific content included. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
66 lines
2.0 KiB
Bash
Executable File
66 lines
2.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# ============================================================================
|
|
# "Ralph Wiggum" Stop Hook — Prevents Claude from stopping until all tasks
|
|
# in plan.md are complete.
|
|
#
|
|
# How it works:
|
|
# - Runs every time Claude tries to stop (end its session)
|
|
# - Reads plan.md and counts unchecked [ ] tasks
|
|
# - If tasks remain AND CLAUDE_AUTONOMOUS=1: returns {"decision":"block"}
|
|
# which tells Claude to keep going
|
|
# - If all tasks done or autonomous mode off: allows the stop
|
|
#
|
|
# Requires: CLAUDE_AUTONOMOUS=1 environment variable to activate
|
|
# ============================================================================
|
|
set -euo pipefail
|
|
|
|
# Determine project directory
|
|
BASE="${CLAUDE_PROJECT_DIR:-}"
|
|
if [[ -z "$BASE" ]] && command -v jq &>/dev/null; then
|
|
BASE=$(jq -r '.cwd // empty' 2>/dev/null || true)
|
|
fi
|
|
[[ -z "$BASE" ]] && BASE="$(pwd)"
|
|
|
|
PLAN_FILE="${CLAUDE_PLAN_FILE:-plan.md}"
|
|
ALT_FILES="loop/plan.md todo.md loop/todo.md"
|
|
AUTO_SLEEP_HOOK="$HOME/.claude/hooks/allow-sleep.sh"
|
|
|
|
# Find the plan file
|
|
plan=""
|
|
for f in "$PLAN_FILE" $ALT_FILES; do
|
|
[[ -z "$f" ]] && continue
|
|
if [[ "$f" == /* ]]; then
|
|
path="$f"
|
|
else
|
|
path="$BASE/$f"
|
|
fi
|
|
if [[ -f "$path" ]]; then
|
|
plan="$path"
|
|
break
|
|
fi
|
|
done
|
|
|
|
# If autonomous mode is off or no plan file found, allow stop
|
|
if [[ -z "${CLAUDE_AUTONOMOUS:-}" ]] || [[ "$CLAUDE_AUTONOMOUS" == "0" ]]; then
|
|
[[ -x "$AUTO_SLEEP_HOOK" ]] && "$AUTO_SLEEP_HOOK" || true
|
|
exit 0
|
|
fi
|
|
|
|
if [[ -z "$plan" ]] || [[ ! -f "$plan" ]]; then
|
|
[[ -x "$AUTO_SLEEP_HOOK" ]] && "$AUTO_SLEEP_HOOK" || true
|
|
exit 0
|
|
fi
|
|
|
|
# Count incomplete tasks (standard markdown checkbox: - [ ] or * [ ])
|
|
incomplete=$(grep -c -E '^\s*[-*]?\s*\[\s*\]' "$plan" 2>/dev/null || echo 0)
|
|
|
|
if [[ "${incomplete:-0}" -gt 0 ]]; then
|
|
# Block the stop — Claude must continue
|
|
echo '{"decision":"block","reason":"Plan has '"$incomplete"' incomplete task(s). Continue with the next item."}'
|
|
exit 0
|
|
fi
|
|
|
|
# All tasks complete — allow stop and allow sleep
|
|
[[ -x "$AUTO_SLEEP_HOOK" ]] && "$AUTO_SLEEP_HOOK" || true
|
|
exit 0
|