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>
268 lines
9.2 KiB
Markdown
268 lines
9.2 KiB
Markdown
# 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)
|
|
- Install: https://docs.anthropic.com/en/docs/claude-code
|
|
- Must be logged in: run `claude login` first
|
|
- **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
|
|
|
|
```bash
|
|
# 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
|
|
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
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
```markdown
|
|
## 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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.
|