Autonomous agent loop for Claude Code. Decomposes a spec into tasks, executes them one per iteration with crash recovery and handoff context.
Inspired by snarktank/ralph, rebuilt from scratch with filesystem-based state, bash task management, and agent-controlled exit signals.
.project/
PROMPT.md # Agent instructions (the system prompt for each iteration)
SPEC.md # Your project spec (replace with your own)
task # Bash task runner — manages task state via the filesystem
loop # Python loop runner — calls `claude --print` in a loop
tasks/ # Task files live here (one .md per task)
FS-001.md # Example tasks from a sample "filestats" spec
FS-002.md
FS-003.md
FS-004.md
.claude/
commands/
spec-to-tasks.md # Claude Code custom command: /spec-to-tasks
Replace .project/SPEC.md with your own project description. Keep it concrete — what to build, what technologies, what's in/out of scope.
Run the custom command inside Claude Code:
/spec-to-tasks
This reads your spec and decomposes it into individual task files in .project/tasks/, each with frontmatter (id, priority, complexity, dependencies) and acceptance criteria.
python3 .project/loopEach iteration, the agent:
- Reads
HANDOFF.md(orSPEC.mdon first run) for context - Picks the next task (respecting priority and dependencies)
- Implements it, runs quality checks
- Commits, writes a handoff for the next iteration
- Writes a
STOPfile when all tasks are done (or if blocked/needs clarification)
Options:
--max N Max iterations (default: 50)
--delay N Seconds between iterations (default: 3)
--model NAME Model override (e.g. claude-sonnet-4-20250514)
--verbose Show assistant text as it streams
Logs go to .project/logs/ (raw JSONL + human-readable summaries per iteration).
You don't have to use the loop. The task runner works standalone:
.project/task next # Next available task (priority + deps)
.project/task list # All tasks by status
.project/task FS-001 # View task details
.project/task FS-001 progress # Mark in-progress
.project/task FS-001 done # Mark complete (moves to tasks/done/)---
id: PREFIX-NNN
priority: N
complexity: s|m|l
depends: [PREFIX-001, PREFIX-002]
---
# Task title
Description with enough context for a fresh agent.
## Acceptance Criteria
- [ ] Specific, verifiable criterion
- [ ] Another criterionState is managed by the filesystem: FOO-001.md = open, FOO-001.progress.md = in-progress, done/FOO-001.md = completed.
- No database, no server. State lives in markdown files and filenames. You can inspect and edit everything with a text editor.
- One task per iteration. The agent does one thing, commits, and hands off context via
HANDOFF.md. This keeps each context window focused and makes progress visible. - Crash recovery. If an iteration dies mid-task, the
.progress.mdfile remains. The next iteration picks it back up automatically. - Exit signals. The agent writes a
.project/STOPfile to communicate completion (DONE:), blockers (BLOCKED:), or questions (CLARIFY:). The loop reads this and exits with the appropriate code.
- Claude Code CLI installed and on your
PATH - Python 3.11+ (for the loop runner)
- Git (the agent commits after each task)
- Copy this scaffold into your repo
- Replace
.project/SPEC.mdwith your spec - Delete the example
FS-*.mdtask files - Run
/spec-to-tasksin Claude Code to generate your tasks - Run
python3 .project/loopand watch it go