> ## Documentation Index
> Fetch the complete documentation index at: https://loop-js.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# What is loop.js

> Loop.js is the framework for loop engineering — state a goal, the engine drives judged Rounds until an independent verdict settles it

**Loop.js is the framework for loop engineering.**

You state a **Goal** and what "done" means. The engine drives **Rounds** — an Execute agent
works with fresh context, then a separate, skeptical **Verify** agent judges the result
against the bar — until the Goal **settles**. Only that verdict, never the worker's own
claim, ends the loop. Run it from a terminal, put it on a schedule, or embed it in a
product: same engine, same guarantees.

```ts theme={null}
import { Loop } from "@loop.js/core"

const loop = Loop.define({
  goal: "Build a playable 2D platformer",
  verify: "It builds clean, `bun test` passes, and the game boots to a controllable character",
  limits: { rounds: 20, usd: 10 },
})

const run = loop.run()                        // self-drives; iterate to observe
for await (const e of run) {
  if (e.type === "verdict") console.log(e.round, e.ok, e.reason)
}

const exit = await run.done()
// { settled: true, verdict } — the judge said done, not the worker
```

## What's in the box

|                      |                                                                                                                                                                    |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **A judged loop**    | state a Goal, get Rounds driven to a settle — from the [CLI](/cli/run), a schedule, or the typed API (`Loop.define` / `loop.run` / an [event stream](/api/events)) |
| **A separate judge** | a read-only [Verify agent](/concepts/loop) judges every Round; only its verdict settles the Loop                                                                   |
| **State on disk**    | fresh context every Round, memory read back from disk — survives crashes and schedules                                                                             |
| **Declared guards**  | [`rounds` / `usd` / `timeout`](/concepts/limits) — tight by default; every ending is a typed Exit with its own exit code                                           |
| **One writer**       | the Lock (compare-and-set + heartbeat) makes any trigger cadence overlap-safe                                                                                      |
| **Real schedulers**  | [`loop cron`](/cli/cron) installs into crontab / launchd / Task Scheduler — or **Modal** in the cloud; no daemon, ever                                             |

## One Round, four beats

1. **Execute** — an agent works toward the Goal inside the work tree (`./workspace` by default).
2. **Handoff** — the agent leaves a note for the next Round: what it did, what it believes is left.
3. **Verify** — a separate agent, read-only by default, judges the work against the bar. Its
   verdict is `ok`, or not-ok **with a mandatory reason**, or a give-up when the Goal can
   never pass.
4. **Persist** — the verdict and the Round's events land on disk (the Record and journal),
   so the next Round — or a crash, or next week's scheduled run — picks up exactly here.

Only a Verify verdict settles a Loop. Limits — Rounds, dollars, wall clock — are runaway
guards: they end a Run, they never mean "done".

## Why writer ≠ grader

An agent grading its own work passes it. loop.js separates the roles structurally: Verify
runs with its own prompt, its own (cheaper, if you like) model, and read-only by default —
the write tools are denied at the adapter, not by prompt discipline. It reads the Execute agent's handoff
digest first and escalates only when suspicious: inspecting the work tree, running the
build, checking the transcript.

## No daemon

loop.js runs nothing in the background. `loop run` drives Rounds in the foreground and
exits; [`loop cron`](/cli/cron) installs Entries into a real scheduler — crontab, launchd,
Task Scheduler, or Modal — and a fired Entry simply runs `loop run` again. State lives on
disk, so the loop is exactly as durable as your filesystem.

<CardGroup cols={2}>
  <Card title="Quickstart" icon="rocket" href="/quickstart">
    Scaffold a project and drive your first Goal to settled.
  </Card>

  <Card title="What is loop engineering" icon="infinity" href="/loop-engineering">
    The practice loop.js is built for — and where it stands in it.
  </Card>
</CardGroup>
