Skip to content

open-spek/loop

Repository files navigation

Loop Engineering Project Template

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:

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.


What you get

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.


Quick start

1. Scaffold a new project

./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"

2. Human work (before the loop)

Complete the checklist in docs/SETUP-CHECKLIST.md. At minimum:

  1. Write MANIFESTO.md — what the project is and refuses to be
  2. Lock docs/DESIGN.md — engineering decisions and acceptance criteria
  3. Choose toolchain and define the gate in docs/TOOLCHAIN.md
  4. Copy and fill CLAUDE.md (or AGENTS.md for other agents)
  5. Run planning mode once to produce loop/IMPLEMENTATION_PLAN.md
  6. Set milestone acceptance criteria in loop/ACCEPTANCE.md

3. Configure the runner

cp loop/config/loop.env.example loop/config/loop.env
# Edit: AGENT_CMD, GATE_CMD, COMPLETION_SENTINEL, etc.

4. Run the build loop

# Sandbox strongly recommended (Docker, clean branch, no uncommitted human edits)
./loop/scripts/loop.sh 50

Watch the first 5–10 iterations closely. Steer by inputs (prompt, spec, plan), not by hand-fixing agent output.

5. Close a milestone, start the next

When .loop/COMPLETE appears and you verify the gate yourself:

  1. Tag or merge the milestone
  2. Update HANDOFF.md, regenerate IMPLEMENTATION_PLAN.md for the next phase
  3. Update loop/ACCEPTANCE.md and loop/config/loop.env completion sentinel
  4. Run the loop again

Directory map

.
├── 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)

Mental model

┌─────────────────────────────────────────────────────────────┐
│  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.


Agent compatibility

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.md for 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:

  1. Fresh context per iteration (new process, not accumulated chat)
  2. Non-interactive mode for unattended runs
  3. Tool access to read/write files, run shell (gate), git commit
  4. Optional: workflow/subagent support for fan-out patterns

Safety

  • 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-permissions equivalents
  • Completion is a marker file (.loop/COMPLETE), never grep of prose

License

MIT — use freely. Attribution appreciated but not required.

About

Reference method of the Open-Spek standard: a test-gated autonomous agent loop that turns a Spek into verified code.

Topics

Resources

License

Stars

2 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages