A complete, agent-agnostic scaffold for building software autonomously with a test-gated agent loop.
Progress lives in files and git, not in the model's context window. Each iteration starts fresh; the agent re-derives state by reading the spec, plan, and code. One task per iteration. The gate is truth.
This template was distilled from the LibreDB build — an embedded, FoundationDB-style multi-model database built mostly autonomously with ~200 tests at full coverage — and aligned with current research on long-running agents:
- Recursive Language Models (RLM) — context as an external environment; programmatic decomposition
- RLM paper (arXiv)
- LangChain Dynamic Subagents — orchestration as code (
task(), loops,Promise.all) - Claude Code Dynamic Workflows — scripts that fan out subagents at scale
- Claude Code Workflows docs
- Cursor: Scaling long-running autonomous coding — planner/worker separation, fresh context per cycle
- Claude Code Agent Teams — subagent definitions for specialized teammates
This template is the reference method of the Open-Spek
standard: it is the machinery that turns a Spek — the
complete knowledge required to create software — into a verified implementation. The first
end-to-end proof is open-spek/jsonq: a type-safe JSON
query engine whose every line was generated by this loop from a frozen Spek (252 tests,
100 percent coverage), with the full friction log preserved in its
loop/TEMPLATE-FEEDBACK.md.
| Layer | Purpose |
|---|---|
| Human inputs | Frozen spec, manifesto, design, toolchain, phases, acceptance criteria |
| Loop machinery | Prompt, plan, progress log, runner script, completion marker |
| Guardrails | Honesty contract, TDD gate, one-task-per-iteration, no interactive pauses |
| Scale patterns | Dynamic workflows / subagents for fan-out inside a milestone (optional) |
The template contains no application code — only documentation, placeholders, and scripts that drive the agent.
./loop/scripts/scaffold.sh /path/to/my-new-project "My Project"
cd /path/to/my-new-project
git init && git add . && git commit -m "chore: initialize loop engineering scaffold"Complete the checklist in docs/SETUP-CHECKLIST.md. At minimum:
- Write
MANIFESTO.md— what the project is and refuses to be - Lock
docs/DESIGN.md— engineering decisions and acceptance criteria - Choose toolchain and define the gate in
docs/TOOLCHAIN.md - Copy and fill
CLAUDE.md(orAGENTS.mdfor other agents) - Run planning mode once to produce
loop/IMPLEMENTATION_PLAN.md - Set milestone acceptance criteria in
loop/ACCEPTANCE.md
cp loop/config/loop.env.example loop/config/loop.env
# Edit: AGENT_CMD, GATE_CMD, COMPLETION_SENTINEL, etc.# Sandbox strongly recommended (Docker, clean branch, no uncommitted human edits)
./loop/scripts/loop.sh 50Watch the first 5–10 iterations closely. Steer by inputs (prompt, spec, plan), not by hand-fixing agent output.
When .loop/COMPLETE appears and you verify the gate yourself:
- Tag or merge the milestone
- Update
HANDOFF.md, regenerateIMPLEMENTATION_PLAN.mdfor the next phase - Update
loop/ACCEPTANCE.mdandloop/config/loop.envcompletion sentinel - Run the loop again
.
├── README.md ← you are here
├── CLAUDE.md.template → copy to CLAUDE.md (Claude Code)
├── AGENTS.md.template → copy to AGENTS.md (other coding agents)
├── MANIFESTO.md.template → copy to MANIFESTO.md
├── docs/
│ ├── DESIGN.md.template → copy to docs/DESIGN.md
│ ├── TOOLCHAIN.md.template → copy to docs/TOOLCHAIN.md
│ ├── ARCHITECTURE.md.template → optional; grows with the project
│ ├── BRAINSTORM.md.template → human brainstorm before DESIGN.md
│ ├── MILESTONE-PLAYBOOK.md → human workflow between loop runs
│ └── SETUP-CHECKLIST.md → human pre-flight checklist
├── loop/
│ ├── LOOP-ENGINEERING.md → full operating manual (read before running)
│ ├── PROMPT.md.template → build-mode iteration prompt
│ ├── PROMPT-PLANNING.md.template → planning-mode prompt
│ ├── IMPLEMENTATION_PLAN.md.template
│ ├── PROGRESS.md.template
│ ├── HANDOFF.md.template
│ ├── ACCEPTANCE.md.template
│ ├── TEMPLATE-FEEDBACK.md.template → human-owned friction log (feeds this template)
│ ├── config/loop.env.example
│ └── scripts/
│ ├── loop.sh → generic agent loop runner
│ ├── gate.sh.example → gate script template
│ └── scaffold.sh → copy template into new project
├── .claude/
│ ├── workflows/README.md → when to use dynamic workflows inside a milestone
│ └── agents/*.template → subagent role definitions
└── examples/README.md → the reference builds (jsonq, LibreDB)
┌─────────────────────────────────────────────────────────────┐
│ HUMAN (between milestones) │
│ brainstorm → manifesto → design → toolchain → phases │
│ → acceptance criteria → implementation plan │
└──────────────────────────┬──────────────────────────────────┘
│ frozen inputs
▼
┌─────────────────────────────────────────────────────────────┐
│ LOOP (within a milestone) │
│ fresh context → orient → ONE task → TDD → gate → commit │
│ → tick plan → log progress → exit → repeat │
└──────────────────────────┬──────────────────────────────────┘
│ optional, inside hard tasks
▼
┌─────────────────────────────────────────────────────────────┐
│ DYNAMIC WORKFLOWS / SUBAGENTS (RLM-style fan-out) │
│ agent writes orchestration script → task() per unit │
│ → synthesize → return result to iteration │
└─────────────────────────────────────────────────────────────┘
Loop Engineering predates Open-Spek — it was distilled from the LibreDB build — and it runs without a complete Spek: the human input above only needs to be a locked design, not a ratified Spek. Open-Spek later adopted this template as its reference method, not because the loop is Open-Spek, but because a ratified Spek plus this loop produced jsonq as the standard's first proof. The two compose; neither requires the other.
You engineer the inputs and the environment; the loop does the keystrokes.
Status: Claude Code is the only supported runner today. The non-Claude paths below are the intended design, not the working state — see
docs/AGENT-AGNOSTIC.mdfor confirmed defects, the fix plan, and the acceptance bar before other agents are supported.
The runner defaults to Claude Code (claude -p). Configure AGENT_CMD in loop/config/loop.env for others:
| Agent | Typical invocation | Notes |
|---|---|---|
| Claude Code | claude -p |
--dangerously-skip-permissions for unattended runs |
| Cursor Agent | cursor agent or IDE-driven |
Use same PROMPT.md; run iterations manually or via automation |
| Codex CLI | project-specific | Map to equivalent non-interactive prompt flag |
| Gemini CLI | project-specific | Ensure fresh process per iteration |
| OpenCode / others | project-specific | Same file layout; swap AGENT_CMD |
Requirements for any agent:
- Fresh context per iteration (new process, not accumulated chat)
- Non-interactive mode for unattended runs
- Tool access to read/write files, run shell (gate), git commit
- Optional: workflow/subagent support for fan-out patterns
- Run on a dedicated branch in a clean working tree
- Never edit the repo while the loop runs — pause first
- Use iteration caps and budget limits
- Keep the per-iteration timeout (
LOOP_ITERATION_TIMEOUT) — hung agent processes (e.g. usage limits mid-iteration) are otherwise invisible to the runner - Block destructive tools (
rm, force push) in agent config - Prefer Docker / sandbox for
--dangerously-skip-permissionsequivalents - Completion is a marker file (
.loop/COMPLETE), never grep of prose
MIT — use freely. Attribution appreciated but not required.