https://github.com/ksimback/looper
Design visual, review-gated agent loops for Claude Code before you run them.
https://github.com/ksimback/looper
Last synced: 20 days ago
JSON representation
Design visual, review-gated agent loops for Claude Code before you run them.
- Host: GitHub
- URL: https://github.com/ksimback/looper
- Owner: ksimback
- License: mit
- Created: 2026-06-18T19:44:20.000Z (about 1 month ago)
- Default Branch: main
- Last Pushed: 2026-07-04T18:22:34.000Z (21 days ago)
- Last Synced: 2026-07-04T20:07:35.698Z (21 days ago)
- Language: Python
- Size: 236 KB
- Stars: 575
- Watchers: 1
- Forks: 52
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-claude-code - **looper** - (440 โญ) - Visual planning tool for review-gated Claude Code agent loops before they run. (๐ ๏ธ Tools & Utilities)
README
_ ___ ___ ____ _____ ____
| | / _ \ / _ \| _ \| ____| _ \
| | | | | | | | | |_) | _| | |_) |
| |___ | |_| | |_| | __/| |___| _ <
|_____| \___/ \___/|_| |_____|_| \_\
Design agent loops before you run them.
Goal -> Plan -> Review -> Deliver -> Judge -> Stop clean.
## Example loop diagram
Looper turns a fuzzy automation idea into a reviewable loop shape before any
runner starts changing files. This example comes from
[`examples/ai-workflow-mapping`](examples/ai-workflow-mapping/loop.yaml).
```mermaid
flowchart TD
G["Goal + context
process notes + definition of done"] --> P["Draft plan.md
host: codex / gpt-5"]
P --> PG{"Plan gate
judge: reviewer-1"}
PG -- "revise <= 3" --> P
PG -- "pass" --> D["Write delivery-N.md
map the workflow"]
D --> DG{"Delivery gate
programmatic check + judge"}
DG -- "revise <= 3" --> D
DG -- "pass" --> F["Final output
all gates clean"]
S["State + log
state.json + run-log.md"] -. "records" .-> P
S -. "records" .-> D
Stop["Stop guards
max 12 iterations
no progress x2
budget caps"] -. "watch" .-> PG
Stop -. "watch" .-> DG
```
**A loop design coach for Claude Code.** Looper is a skill that helps you design a *good* agent loop โ a sharp goal, checkable verification, and a second model in the review seat โ then lets you run it in the same session or save it as a portable spec. It is a design layer first: it writes files and hands the current session a clear execution prompt.
Invoke it with `/looper`. It interviews you, critiques your design against built-in best-practice rubrics, lets you wire in a cross-model reviewer or judge (including non-Claude models), shows you the loop as a terminal-friendly ASCII flow preview, and writes out `RUN_IN_SESSION.md`, `loop.yaml`, a compiled `loop.resolved.json`, a human-readable `LOOP.md`, a thin `run-loop.py` you own and edit, plus an empty `loop-workspace/` and a README for the loop.
Maintainer: Kevin Simback ยท GitHub [@ksimback](https://github.com/ksimback) ยท X [@ksimback](https://x.com/ksimback)
License: MIT
---
## Why not just use `/goal` or `/loop`?
Claude Code already ships two pieces that look loop-shaped. They're useful โ and they operate at a different layer than Looper. The short version: **`/goal` and `/loop` *run* a loop; Looper helps you *design* one that's worth running, then gives the current session or an external runner a clear spec to follow.**
### What `/goal` actually does
`/goal` sets a persistent objective for the session. Once set, Claude keeps it as a reference point, checks after each significant action whether the current state satisfies the goal, and keeps working until it does โ so it doesn't stop and ask after every step.
That's genuinely useful for persistence. But three things are missing for serious work:
- **No coaching.** `/goal` takes whatever goal you type, however vague. It won't tell you the goal is unfalsifiable or that "done" was never defined. Garbage goal in, confidently-wrong loop out.
- **Self-evaluation by one model.** The goal condition is judged by the *same model doing the work.* That's precisely the blind spot a review council exists to close โ the model grading its own homework. In practice this self-check skews unreliable (sometimes too lenient, sometimes too conservative).
- **No structure to inspect or reuse.** The goal lives in the session, not as a portable, versionable artifact. There's no typed verification, no explicit gates, no second model.
### What `/loop` actually does
`/loop` is a **scheduler.** You give it an interval and a task; it turns that into a cron job, registers it, and re-fires the prompt or skill on that cadence โ polling CI, watching a deploy, monitoring a background job. (Omit the interval and it self-paces.)
It's the right tool for "run this thing every five minutes until I say stop." It is **not** a loop designer: it doesn't help you decide *what* runs, define success criteria, or bring in a reviewer. It schedules; it doesn't critique.
### Where Looper fits
Looper is the **design layer that sits in front of both.** It produces a well-specified loop โ coached goal, typed verification, a cross-model gate โ then gives you a default in-session handoff prompt plus a portable spec. The same design can be run immediately in the conversation, driven by `/goal` for persistence, fired on a schedule by `/loop`, or run later with Python. Looper doesn't replace them; it gives them something good to run.
| | `/goal` | `/loop` | **Looper** |
| :-- | :-- | :-- | :-- |
| Layer | execution (in-session) | execution (scheduling) | **design (pre-flight)** |
| Coaches your goal | no | no | **yes** |
| Typed, checkable verification | no | no | **yes (programmatic / judge / human)** |
| Reviewer model | same model (self-check) | none | **a different model, by default** |
| Explicit review gates | implicit | none | **plan gate + delivery gate** |
| Termination guards | goal-condition only | interval / until | **iteration + revision + no-progress + budget caps** |
| Portable, versionable artifact | no | the cron job | **`loop.yaml` + resolved spec** |
| Runs the loop | **yes** | **yes** | **yes, by handing the current session a runnable prompt; Python runner optional** |
The honest summary: if you already know your loop is well-designed and you just need it to persist or to fire on a schedule, `/goal` and `/loop` are the right reach. Looper exists for the part those don't touch โ making sure the loop is *worth* persisting before you hand it off, and making sure something other than the author is checking the work.
> Sources for the `/goal` and `/loop` behavior described above: Claude Code skills and commands documentation at code.claude.com/docs. Behavior and version gates change frequently; verify against upstream before shipping.
---
## What Looper provides
Looper provides loop design discipline: a clear goal, context sources,
checkable verification, reviewer/judge gates, termination guards, a portable
spec, a same-session execution handoff, and lightweight run state/log files.
Looper does **not** provide durable orchestration. It does not schedule cron
jobs for you, persist step-level retries across process restarts, manage
sub-agent lifecycles, enforce concurrency controls, or store a production run
history. If you need those guarantees, use Looper to design the loop and hand
the resulting spec to an orchestrator built for durable execution.
## Healthy loop checklist
Before running a loop, Looper pushes you to make these explicit:
- **Goal**: what outcome the loop is trying to produce.
- **Context**: which files, commands, issues, or external sources the loop may
inspect.
- **Actions**: which model, tools, commands, or human handoffs may change state.
- **Feedback**: which programmatic checks, judges, reviewers, or humans decide
whether work is good enough.
- **State**: where the loop records status, decisions, blockers, and outputs.
- **Stop conditions**: success, max iterations, revision caps, no-progress
signals, and budget caps. The external runner enforces wall-clock caps;
token/USD caps are operator-visible advisory limits unless you add accounting
around the configured CLIs.
- **Execution boundary**: current workspace, branch/worktree, external runner,
or a separate durable orchestrator.
---
## Quick start
Install as a global personal skill and slash command.
On Windows PowerShell:
```powershell
irm https://raw.githubusercontent.com/ksimback/looper/main/install.ps1 | iex
```
On macOS/Linux:
```bash
curl -fsSL https://raw.githubusercontent.com/ksimback/looper/main/install.sh | bash
```
If you prefer to inspect each step, use the manual install:
Manual install commands
Windows PowerShell:
```powershell
git clone https://github.com/ksimback/looper "$env:USERPROFILE\.claude\skills\looper"
New-Item -ItemType Directory -Force "$env:USERPROFILE\.claude\commands" | Out-Null
Copy-Item "$env:USERPROFILE\.claude\skills\looper\commands\looper.md" "$env:USERPROFILE\.claude\commands\looper.md" -Force
```
macOS/Linux:
```bash
git clone https://github.com/ksimback/looper "$HOME/.claude/skills/looper"
mkdir -p "$HOME/.claude/commands"
cp "$HOME/.claude/skills/looper/commands/looper.md" "$HOME/.claude/commands/looper.md"
```
Then, in Claude Code:
```text
/looper
```
Looper interviews you, writes the artifacts into a folder called `looper-output`,
and shows you an ASCII flow preview to confirm before anything is finalized. The
installer also creates a private `.venv` inside the skill directory and installs
`PyYAML`, which the helper compiler needs to read `loop.yaml`. It
then offers to run the loop right there in the same Claude Code session.
If you want a different folder name, pass it after `/looper`, for example
`/looper client-onboarding-loop`.
### Easy: run in the same session
The default path is to let Looper continue in the same conversation. It follows
the generated `RUN_IN_SESSION.md` handoff, writes `plan.md`,
`delivery-N.md`, `review-N.md`, `state.json`, and `run-log.md` into the loop
workspace, and stops when the gates pass, a cap is reached, or repeated
no-progress is detected.
### Advanced: run outside the session
Use the Python runner when you want to run the loop later, repeatably, from
another terminal, or outside the LLM session:
```bash
python3 ./looper-output/run-loop.py
```
For local development, this repository root is the skill root. Edit and test it
here, then install or update the global skill by cloning or copying the repo to
`$HOME/.claude/skills/looper` and copying `commands/looper.md` to
`$HOME/.claude/commands/looper.md`.
If Claude Code says `Unknown command: /looper`, check both install locations:
- The skill must exist at your real home directory, for example
`C:\Users\\.claude\skills\looper` on Windows.
- The slash command must exist at `C:\Users\\.claude\commands\looper.md`
on Windows.
- If you see a literal folder named `~` inside your project, your shell did not
expand `~`; rerun the installer or manual PowerShell commands above.
### What Looper writes on your machine
Looper is transparent about its footprint. Outside of the loop folders you ask
it to scaffold, it touches exactly four locations:
- `~/.claude/skills/looper` โ the skill itself (a git checkout).
- `~/.claude/commands/looper.md` โ the `/looper` slash command.
- `~/.claude/skills/looper/.venv` โ a private venv with PyYAML for the helper
compiler.
- `~/.looper/models.json` โ the model registry written by `detect-models` /
`register-model`. It stores invocation metadata only (command names and
argv arrays), never API keys or other credentials; auth stays in each CLI's
own config or keychain.
### Uninstall
Windows PowerShell:
```powershell
Remove-Item -Recurse -Force "$env:USERPROFILE\.claude\skills\looper"
Remove-Item -Force "$env:USERPROFILE\.claude\commands\looper.md"
Remove-Item -Recurse -Force "$env:USERPROFILE\.looper" # optional: model registry
```
macOS/Linux:
```bash
rm -rf "$HOME/.claude/skills/looper"
rm -f "$HOME/.claude/commands/looper.md"
rm -rf "$HOME/.looper" # optional: model registry
```
---
## How it works
1. **Goal** โ you state it; Looper critiques and tightens it.
2. **Verification** โ Looper forces checkable criteria, classified as programmatic (a command returns pass/fail), judge (a model scores a rubric), or human (you sign off).
3. **Host model** โ pick the model that drives the loop.
4. **Council** โ add a reviewer (notes) or judge (verdict); Looper recommends a *different* model family than the host and explains why.
5. **Gates & control** โ confirm where review happens, revision and iteration caps, no-progress signals, budget limits, human checkpoints, and execution boundaries. Looper won't emit a loop with no termination guard.
6. **Confirm** โ review the loop as an ASCII flow preview.
7. **Run or emit** โ Looper writes `RUN_IN_SESSION.md`, `loop.yaml`, `loop.resolved.json`, `run-loop.py`, an empty workspace, and a README. The default is to offer to run the loop in the current session; the Python runner is there for external control.
A council sends your project context to another model's CLI. Looper makes that explicit, applies default redactions, lets you scope what's sent, and asks for consent before the first cross-vendor send. Pick a local model (e.g. via `ollama`) to keep the council in-house.
## License
MIT ยฉ Kevin Simback