Files
archy/For Others/README.md
T
DorianandClaude Opus 4.6 b96d96b654 docs: add overnight automation guide and setup script for others
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>
2026-03-04 08:31:41 +00:00

9.2 KiB

Claude Code Overnight Automation

Run Claude Code headlessly overnight to execute a full task checklist — with rate-limit resilience, macOS sleep prevention, and a stop hook that prevents Claude from quitting until every task is done.

How It Works

loop.sh (orchestrator)
  |
  +--> Reads plan.md for unchecked [ ] tasks
  +--> Pipes prompt.md into `claude -p` (headless mode)
  |      |
  |      +--> Claude reads your plan, specs, and project rules
  |      +--> Implements tasks one by one
  |      +--> Runs typecheck/lint/test after each
  |      +--> Commits, marks [x], moves to next
  |      |
  |      +--> Claude tries to stop
  |             |
  |             +--> Stop Hook intercepts
  |                    +--> Checks plan.md for remaining [ ] tasks
  |                    +--> If incomplete: BLOCKS the stop (Claude continues)
  |                    +--> If all done: allows stop
  |
  +--> Detects rate limits in output
  |      +--> Sleeps 1 hour, retries (up to 5x)
  |      +--> After 5 retries: schedules macOS launchd job to resume later
  |
  +--> Loops N iterations (default 10)
  +--> Exits when all tasks checked or iterations exhausted

The "Ralph Wiggum" Stop Hook

The secret sauce. Claude Code supports a Stop hook — a shell script that runs every time Claude tries to end its session. By returning {"decision":"block"}, the hook prevents Claude from stopping. Combined with --dangerously-skip-permissions, Claude becomes a fully autonomous task executor that won't quit until the job is done.

Sleep Prevention

On macOS, caffeinate -i prevents idle sleep during long runs. A hook starts it when Claude begins and kills it when Claude finishes.

Rate Limit Resilience

If Claude hits API rate limits:

  1. Inline retry: Sleep 1 hour, then retry the same iteration
  2. Scheduled retry: After 5 failed retries, create a macOS launchd plist that auto-runs the loop later
  3. The plist self-destructs after executing

Prerequisites

  • Claude Code CLI (claude command available in PATH)
  • macOS (for caffeinate and launchd — see Linux notes below)
  • Git (the script commits after each task)
  • A project with package.json or similar build tooling

Quick Start

# 1. Clone or copy this folder into your project
cp -r "For Others/templates" ~/my-project/loop

# 2. Run the setup script (creates hooks, updates settings)
cd ~/my-project
bash "path/to/For Others/setup.sh"

# 3. Edit your task list
vim loop/plan.md

# 4. Edit your prompt (project-specific rules)
vim loop/prompt.md

# 5. Start the overnight run
./loop/loop.sh

Or just run the setup script — it walks you through everything:

bash "For Others/setup.sh"

File Structure

After setup, your project will have:

your-project/
  loop/
    loop.sh          # Main orchestrator (run this)
    prompt.md        # Instructions piped to Claude each iteration
    plan.md          # Task checklist ([ ] = todo, [x] = done)
    loop.log         # Full output log (auto-created)

~/.claude/
  hooks/
    prevent-sleep.sh           # Starts caffeinate on session start
    stop-hook-autonomous.sh    # Blocks stop until tasks complete
    allow-sleep.sh             # Kills caffeinate on session end
  settings.json                # Hook registrations (auto-updated by setup)

Configuration

All config is via environment variables (set before running loop.sh or export in your shell):

Variable Default Description
CLAUDE_AUTONOMOUS 1 Set to 0 to disable the stop hook (Claude can quit freely)
ITERATION_COUNT 10 Max loop iterations
ITERATION_DELAY 30 Seconds to pause between iterations
RATE_LIMIT_WAIT 3600 Seconds to sleep when rate limited (1 hour)
MAX_RATE_LIMIT_RETRIES 5 Retries before scheduling launchd
CLAUDE_BIN claude Path to Claude CLI binary
PROMPT_FILE loop/prompt.md Path to prompt file
LOG_FILE loop/loop.log Path to log file

Examples

# Quick test run (2 iterations, 10s delay, no stop hook)
CLAUDE_AUTONOMOUS=0 ITERATION_COUNT=2 ITERATION_DELAY=10 ./loop/loop.sh

# Full overnight run (20 iterations, 1 min between)
ITERATION_COUNT=20 ITERATION_DELAY=60 ./loop/loop.sh

# Use a custom prompt
PROMPT_FILE=my-prompt.md ./loop/loop.sh

Writing Your Plan

loop/plan.md is a markdown checklist. Each line starting with - [ ] is a pending task:

## Phase 1: Core Features
- [ ] **1.1** — Add user authentication (JWT + refresh tokens)
- [ ] **1.2** — Create user profile page with avatar upload
- [ ] **1.3** — Add settings page with theme toggle

## Phase 2: API
- [ ] **2.1** — REST endpoints for CRUD operations
- [ ] **2.2** — WebSocket support for real-time updates

## Final
- [ ] **FINAL** — Run full test suite, fix any failures, tag release

Claude will:

  1. Find the first - [ ] line
  2. Read the spec from your prompt or a separate spec file
  3. Implement it
  4. Mark it - [x]
  5. Move to the next

Tips for good plans

  • Be specific: "Add JWT auth with refresh tokens, store in httpOnly cookies" > "Add auth"
  • Order matters: Put foundational tasks first (types, utils, config) before features that depend on them
  • Include testing gates: "Run pnpm test and fix failures" as part of each task
  • Keep tasks small: 30-60 minutes of work each. Large tasks lead to context window exhaustion
  • Add a FINAL task: A catchall that runs the full test suite

Writing Your Prompt

loop/prompt.md is what Claude reads at the start of every iteration. Include:

  1. What files to read (your plan, specs, project conventions)
  2. Project-specific rules (coding style, frameworks, constraints)
  3. Per-task workflow (implement → test → commit → mark done)
  4. Hard rules (what to never do, minimum effort before skipping)

See templates/prompt.md for a starting template.

Operating the Loop

Starting

# Foreground (see output live)
./loop/loop.sh

# Background with logging
nohup ./loop/loop.sh > /dev/null 2>&1 &

# With caffeinate (prevents sleep even if hooks fail)
caffeinate -i ./loop/loop.sh

Monitoring

# Watch the log live
tail -f loop/loop.log

# Check progress
grep -c '\- \[x\]' loop/plan.md  # completed
grep -c '\- \[ \]' loop/plan.md  # remaining

# Check git commits
git log --oneline -20

Stopping

  • Let it finish: The loop stops automatically when all tasks are checked
  • Kill it: Ctrl+C or kill %1 — Claude's current task will be interrupted but committed work is preserved
  • Disable stop hook: Set CLAUDE_AUTONOMOUS=0 in the environment before the next iteration

Resuming

Just run ./loop/loop.sh again. It reads plan.md fresh each iteration, so it picks up where it left off (skipping [x] tasks).

Customizing the Prompt

The prompt template has {{PLACEHOLDER}} markers. Replace them with your project's specifics:

Placeholder What to put
{{SPEC_FILE}} Path to your detailed spec (e.g., SPEC.md, docs/plan.md)
{{PROJECT_RULES_FILE}} Path to your coding conventions file
{{PROJECT_RULES}} Inline coding rules (style, frameworks, constraints)

Troubleshooting

Claude exits immediately

  • Make sure claude login has been run
  • Check that claude -p "hello" works in your terminal
  • Verify ~/.claude/hooks/stop-hook-autonomous.sh exists and is executable

Rate limit loop

  • Default wait is 1 hour. Increase RATE_LIMIT_WAIT if your limits are longer
  • Check loop.log for the specific rate limit message
  • Claude Max subscriptions have higher limits than API keys

Mac goes to sleep

  • Run caffeinate -i ./loop/loop.sh as a belt-and-suspenders approach
  • Check that ~/.claude/hooks/prevent-sleep.sh is executable: chmod +x ~/.claude/hooks/prevent-sleep.sh

Tasks not getting marked complete

  • Ensure your plan uses exact format: - [ ] (dash, space, brackets, space)
  • The stop hook matches ^\s*[-*]?\s*\[\s*\] — standard markdown checkboxes

Stop hook not working

  • Verify CLAUDE_AUTONOMOUS=1 is set: echo $CLAUDE_AUTONOMOUS
  • Check hook is registered in ~/.claude/settings.json
  • Test the hook manually: echo '{}' | bash ~/.claude/hooks/stop-hook-autonomous.sh

Linux Notes

The system is macOS-focused but works on Linux with minor changes:

  • Sleep prevention: Replace caffeinate with systemd-inhibit --what=idle --who=claude-loop --why="Overnight automation" sleep infinity & or simply disable sleep via systemctl mask sleep.target
  • Scheduled retry: Replace the launchd plist section in loop.sh with a systemd-run --on-calendar or at command
  • Hooks work identically — they're plain bash scripts

Security Notes

  • --dangerously-skip-permissions gives Claude full system access within the project. Only run on trusted codebases.
  • The loop runs as your user — Claude can read/write anything you can
  • API keys in .env.local are accessible to Claude during the session
  • Review commits after an overnight run before pushing to production
  • Consider running in a VM or container for additional isolation

License

MIT. Use it however you want.