A loop template for building iterative agent harnesses. Copy loop.sh, edit the prompts, run it.
1. Ralph Loop
while true:
Plan → Build → Verify → (fail? re-plan) → ... → Done
Each iteration starts a fresh agent with a clean context window. State lives in the filesystem, not in the agent's memory. All phases — prompts, verification gates, post-processing — live in a single .sh file.
The loop runs agents in headless mode (codex exec, claude -p) from inside a main Claude Code session. The main agent spawns background loops as tasks or cronjobs. This means:
- The loop runs autonomously — no human in the loop
- The main agent stays free to observe, analyze, and intervene
- Multiple loops can run in parallel on different tasks
Every agent iteration appends to a working record (JSONL in working-records/). Records capture what the agent attempted, what failed, and what changed. The agent's context window is disposable — the working record is not.
The main agent reads working-records/ from background loops, then improves the harness itself:
┌─────────────────────────────────────────────┐
│ Main Agent (Claude Code session) │
│ │
│ reads working-records/ ──► edits loop.sh │
│ ▲ │ │
│ │ ▼ │
│ ┌────┴────────────────────────────────┐ │
│ │ Background Loop (cronjob/task) │ │
│ │ Plan → Build → Verify → re-plan │ │
│ │ │ │ │
│ │ └──► writes working-records/ │ │
│ └─────────────────────────────────────┘ │
└─────────────────────────────────────────────┘
loop.sh enforces a strict cycle order:
setup()runs once, then the cycle starts.Planruns whenoutput/plan.jsonis missing or when all tasks are already complete.Buildruns and repeatedly executes exactly one task per iteration.Verifychecks required artifacts and schema invariants.- On verify fail, the loop archives
output/plan.jsonasworking-records/plan_cycle_<N>.json, removes it, then re-plans next cycle with errors. - On verify pass, configured post-phases run and then the loop exits.
The build contract is one-task-per-iteration:
- read
output/plan.jsonandoutput/progress.txtfirst - execute the first remaining task where
passesisfalse - mark that single task as
passes: true - append cumulative findings to
output/progress.txt - finish the build iteration
loop.sh — self-contained loop template (prompts + engine in one file)
working-records/ — JSONL logs from loop iterations (gitignored)
output/ — runtime artifacts produced by the loop (gitignored)
.claude/skills/looprinter-interview/ — interactive harness configuration skill
output/plan.json— object containingtasksarray; each task hasid,title,description,targetFile,passes, andnotes.output/progress.txt— cumulative findings and notes; must be non-empty forverify().working-records/*.jsonl— line-delimited records for each phase/output cycle.working-records/plan_cycle_*.json— archived snapshots ofoutput/plan.jsonwhen verify fails.
# Run directly
./loop.sh codex 50
./loop.sh codex-spark
./loop.sh claude 30
# Run as background task from a main Claude Code session
# The main agent monitors working-records/ and edits loop.sh to improve the harnessUse the /looprinter-interview skill to interactively configure a harness — it interviews you about your objective, then generates the prompt functions and verify() gate directly into loop.sh.
Or manually copy loop.sh and edit the functions:
gen_plan_prompt()— what the planning agent should dogen_build_prompt()— what the build agent should do per taskgen_replan_prompt()— how to recover from verification failureverify()— quality gates (exit 0 = pass)setup()— one-time preprocessing before the loopPOST_PHASES+gen_<name>_prompt()— optional phases after verify passes