Reeds: Autonomous Development Loops for Claude Code
· 5 min read
Running Claude Code on a complex task usually means babysitting it. You give it a prompt, it works, then it stops to ask something or waits for approval. For a single task, that’s fine. For a whole backlog, it gets old fast.
Two tools help with different parts of this. Ralph, created by Geoffrey Huntley (@GeoffreyHuntley), is just a bash loop that keeps feeding an agent the same prompt file until it says it’s done. Beads handles task management with dependency tracking, so you are not juggling a pile of markdown checklists.
Reeds stitches those together as a Claude Code plugin. No external loop script, no manual juggling. It uses Claude Code’s hook system to keep work moving without you constantly restarting it.
Why Combine Ralph and Beads? #
Ralph is dead simple: a while true loop that keeps invoking an agent. The agent works until it thinks it’s done, exits, and the loop starts it again. It’s named after Ralph Wiggum from The Simpsons, which fits.
The catch is task management. Ralph assumes one prompt file. Once you have multiple tasks with dependencies, you need a way to track what’s done, what’s ready, and what’s blocked.
Beads solves that. It keeps a dependency-aware task graph. You add tasks, mark dependencies, and ask what’s ready next. No more scrolling through a giant plan to figure out where you left off.
Reeds combines the two: Ralph’s persistent loop pattern plus Beads’ structured task management. Claude works through your backlog one task at a time, respects dependencies, and keeps going until it runs out of work.
How It Works #
It’s pretty simple. Three slash commands control the loop, and a stop hook keeps it going.
Starting a Loop #
/reeds-start --max-iterations 20
This creates a state file at .claude/reeds-state.local.md with YAML frontmatter:
---
iteration: 0
max_iterations: 20
---
Then it prints a prompt telling Claude how to run the loop.
Claude’s Work Cycle #
Once started, Claude loops like this:
bd ready --limit 1- Get the next available task from Beadsbd show <task-id>- Read task details- Implement the task
bd close <task-id> --reason "..."- Mark complete- Repeat
If bd ready returns no tasks, Claude prints “REEDS COMPLETE” to signal termination.
The Stop Hook #
This is the key part. Claude Code supports “Stop” hooks that run when Claude tries to exit. Reeds registers one that intercepts the exit and decides whether to allow it.
The hook is about 122 lines of bash and does:
- Parses the conversation transcript to find Claude’s last output
- Checks for the “REEDS COMPLETE” signal
- If NOT found: increments the iteration counter and returns a JSON block:
{
"decision": "block",
"reason": "Continue autonomous development. Current iteration: 5/20..."
}
- If found: removes the state file and allows exit
That "decision": "block" with a "reason" re-invokes Claude with that reason as the new prompt. That creates the loop without any external process or polling.
Termination Conditions #
The loop ends when:
- Claude outputs “REEDS COMPLETE” (no more tasks)
- Max iterations reached
- User runs
/reeds-cancel - State file is missing or corrupted
Operational Notes #
You do not need a separate bash loop. Reeds keeps the loop inside Claude Code’s hook system, so there is no extra terminal or background process to manage.
Task flow comes from Beads. Instead of re-reading a big plan and guessing what’s done, Claude queries a structured graph and gets a single ready task each cycle.
State is stored in .claude/reeds-state.local.md. If anything looks off, open it to check the iteration counter and max limit.
There are a few defensive checks in the hook:
- Symlink detection to prevent attacks
- Path traversal prevention
- Safe temp file creation with
mktemp - Atomic file updates using
mv
These matter because hooks are parsing transcripts and modifying state files.
Plugin Structure #
Reeds is a Claude Code plugin:
.claude-plugin/
plugin.json # Plugin manifest
commands/
reeds-start.md # /reeds-start [--max-iterations N]
reeds-status.md # /reeds-status
reeds-cancel.md # /reeds-cancel
hooks/
hooks.json # Hook registration
stop-hook.sh # The loop logic (~122 lines)
scripts/
setup-reeds.sh # Initialization (~112 lines)
The commands are markdown files with embedded instructions. The hook is bash. The manifest ties everything together.
When To Use This #
Reeds makes sense when you have:
- A backlog of well-defined tasks in Beads
- Tasks that Claude can complete without human input
- Time to let it run (autonomy means you’re not watching every step)
It’s not a great fit when:
- Tasks require frequent human judgment
- You need to review each change before proceeding
- Your task graph has complex interdependencies that need human sequencing
You trade oversight for throughput. Know which one you need.
Getting Started #
The plugin is at github.com/r-dh/reeds. Install it as a Claude Code plugin, populate your Beads task graph, and run /reeds-start.
You’ll also need Beads installed and configured. The bd commands need to work in your environment.
The Broader Pattern #
Reeds shows a useful trick about Claude Code’s extensibility. The stop hook mechanism wasn’t designed for autonomous loops, but it works well for them. You can intercept Claude’s exit, inspect what happened, and decide whether to continue.
This pattern goes beyond task automation. Any workflow where “keep going until X” makes sense could use a similar approach: code review cycles, test-fix loops, documentation passes. The hook system is more flexible than it might initially appear. It is not magic, just persistence with a shorter leash.
Ralph’s insight was that agents don’t need complex orchestration, they just need persistence. Beads’ insight was that task management needs structure, not prose. Reeds combines both using tools that already exist in Claude Code.
Sometimes the best automation is just wiring together what you already have.