LoopFlow, the tutorial
-Stop babysitting the agent.
+LoopFlow is a small natural-language DSL for loop engineering. A .loop file describes a self-correcting, human-gated coding workflow โ its objective, the context it may read, the actions it may take, how it verifies itself, and when it stops. This page teaches the whole language from the first line to full A-to-Z pipelines, every section grounded in a real example you can run.
# run in chat: /loopflow run rate-limit.loop
-# (the agent knows LoopFlow from AGENTS.md โ your repo's memory)
+ โ the one .loop that drove the run above โ the whole job, written once
git:
work on a branch
commit when the goal is met
open a pull request
@@ -245,10 +264,8 @@ LoopFlow, the tutorial
also: run a security check
when it fails: reflect, then plan again
after 6 tries: stop and warn "thrashing"
- Left: a dozen messages, and it still pushed to main. Right: the whole job, written once โ it runs, verifies, and stops only when it's really done.
@@ -272,6 +289,7 @@What is a loop basic
done whenwhenโฆ / after N triesThese five are the core syntax โ the engine. Everything else in the language either composes loops into bigger workflows (pipeline, flow, for each) or configures a run (the rest of the syntax) โ you'll meet those after the core.
Here are all five decisions as one real loop โ every line is one of the rows above:
loop "fix the failing test": # the work
goal: the cart total is correct with a coupon # Objective
@@ -370,7 +388,7 @@ vs Claude Code's /loop and /goal<
Getting started setup
That's the why. From here down is the deep dive โ set LoopFlow up once, then learn the language line by line.
- Prerequisites: Node 18+, the Claude Code CLI (LoopFlow drives it), and a git repo to work in. The primary way to use LoopFlow is a Claude Code chat โ type /loopflow and the assistant writes and runs the loop with you, watching every step and answering gates inline. (Prefer to write .loop files by hand? The VS Code extension is there too โ see below โ but the chat is the recommended path.) One command installs everything:
+ Prerequisites: Node 18+, the Claude Code CLI (LoopFlow drives it), and a git repo to work in. The primary way to use LoopFlow is a Claude Code chat โ type /loopflow and the assistant writes and runs the loop with you, watching every step and answering gates inline. (Prefer to write .loop files by hand? The VS Code extension is there too โ see Running a loop โธ In VS Code โ but the chat is the recommended path.) One command installs everything:
1 ยท Install with npm
From your repo, run the installer. In one step it writes the /loopflow skill and AGENTS.md (the full language reference) into the project:
@@ -412,16 +430,7 @@ 2 ยท Run your first loop โ in a Claude Code chat
- Optional ยท author by hand in VS Code if you prefer an editor
-The chat above is the main way to use LoopFlow. If you'd rather write .loop files by hand, the optional LoopFlow VS Code extension helps โ Extensions โธ search โLoopFlowโ โธ Install โ then open any .loop file:
-
-
- Syntax highlighting for the whole language โ
goal,done when, gates,flow,for each,git:.
- - Completion + formatting โ keyword snippets so you type a loop from muscle memory, not a cheat sheet. -
- A โถ Run button on every loop (the LoopFlow: Run this loop CodeLens) โ and you choose where it runs via the
loop.runModesetting: open an interactive Claude Code session, or a headless output-panel trace.
- - New from template (command palette โ LoopFlow: New from template) โ scaffold a ready-to-edit
.loopbundle.
- - A soft linter that nudges, never blocks โ "this loop has no way to verify it's done", "add a thrash guard". -
Same file, same engine: prompt the agent to generate a loop, or open VS Code and write the .loop yourself. The chat is the first-class way to run; the extension is the first-class way to author by hand.
Prefer to write .loop files by hand in an editor? The optional LoopFlow VS Code extension โ highlighting, completion, a โถ Run button, and New from template โ is covered under Running a loop โธ In VS Code. The chat is the first-class way to run; the extension is the first-class way to author by hand.
git: block, LoopFlow works on a branch and commits when the goal is met, and never pushes to main/master โ see the git keyword.Rather learn hands-on?
@@ -555,6 +564,29 @@Composing โ pipeline, flow, for each scaling u
The full grammar โ pipelines, flow chains, and for each iteration, with worked examples โ is in the manual and the keyword reference.
+
+
+ The rest of the syntax beyond the core
+ The five decisions (plus the cycle) are the whole engine. Everything else in the language either composes loops into bigger workflows or configures a run โ none of it changes how a single loop thinks. Here's the rest at a glance; each construct links to its keyword reference page.
+
+ Construct What it does
+ Compose โ scale one loop into many
+ pipeline ยท stageRun stages in order; a failing stage halts the rest. An epic โ a pipeline, a story โ a stage. More โ
+ flow ยท run / then runChain whole .loop files; each step's summary carries forward (with the result of picks a specific earlier step).
+ for each โฆ inRun a template loop once per item in a YAML/Markdown plan โ A-to-Z over every story.
+ Augment a loop
+ use skills:Named skills the loop may invoke during plan/act โ coordinate proven skills instead of one mega-prompt.
+ remember inCross-run memory: read past lessons on start, append the run's outcome on stop, so the loop improves over time.
+ also:Extra finishing passes run after the goal is met (skipped on failure).
+ plan from "file"Execute a plan you wrote instead of one the agent generates.
+ Ops & reuse โ configure the run
+ git:Version-control policy โ branch / commit cadence / push / PR. Never pushes to main by default.
+ models:Tier the model by phase โ a fast model to plan/reflect, a strong one to act.
+ use the X methodImport a reusable preset (its own .loop) that another repo can share.
+ schedule: ยท target: ยท notify:The config tier โ when it runs, where it runs, and who to tell when it's done.
+
+
+
@@ -704,7 +736,14 @@ Starter templates โ don't write from scratch c
- Running a loop intermediate
+ Running a loop how to run
+ Three ways to work with a .loop โ write it, then run it. Same file, same engine:
+
+ What you want Use How
+ 1 ยท Write the loop by hand the VS Code extension โ syntax highlighting, completion, a soft linter open a .loop in VS Code
+ 2 ยท Run it in Claude Code recommended the /loopflow skill โ watch every step, answer gates inline /loopflow run <file>
+ 3 ยท Run it headless the CLI โ CI, scripts, cron, no chat in the loop loop-run run <file>
+
Every command below runs the same kind of file โ here's the one referenced throughout this section:
# examples/fix_test.loop
loop "fix the failing checkout tax test":
@@ -718,6 +757,17 @@ In a Claude Code chat recommended โ the main w
/loopflow "fix the failing checkout tax test" # write a .loop from a request
/loopflow run examples/fix_test.loop # run it, right here in the chat
You stay in the chat the whole time: you watch each step, you answer the gate, and the loop ends on a real green test โ not the assistant saying "done". This is the only mode where a long interactive discovery works, because the human is already in the loop.
+
+ In VS Code optional โ author by hand
+ Reach for the extension when you'd rather write .loop files by hand in an editor. Install it from Extensions โธ search "LoopFlow" โธ Install, then open any .loop file:
+
+ - Syntax highlighting, hover docs, and context-aware tab-completion for every construct โ including the latest vocabulary (
use skills, remember in, flow, for each, and done when the skill "โฆ" approves / scores N or more).
+ - A โถ Run CodeLens above each definition. You choose where it runs via
loop.runMode: ask (prompt each time), session (open a Claude Code session in the integrated terminal โ watch every step, answer gates in chat), or output (headless, streamed into the VS Code output panel with native gate dialogs).
+ - A soft linter that nudges, never blocks: "this loop has no way to verify it's done", "add a thrash guard".
+ - New Loop from template โ from File โธ New Fileโฆ, an Explorer folder right-click, or the Command Palette โ scaffolds a best-practice loop (bugfix, feature, security, โฆ the full library) into your workspace,
# TODO lines marked.
+
+ Same file, same engine: the chat is the first-class way to run; the extension is the first-class way to author by hand.
+
Headless CLI
loop-run run examples/ship_feature.loop # drive Claude Code, glyph trace
loop-run run examples/ship_feature.loop --live # โฆplus a live browser dashboard
@@ -736,15 +786,6 @@ Watch it run โ live dashboard interm
live=true # /loopflow shows the live dashboard during in-session runs
The page streams over Server-Sent Events (each event carries an id; the server replays on connect and dedupes on reconnect), is self-contained โ no external assets โ and binds to 127.0.0.1 only.
- In VS Code optional โ for hand-authoring
- Secondary to the chat โ reach for the extension only when you want to write .loop files by hand in an editor. It turns a plain text file into a real authoring surface: it knows the grammar, catches a loop that can't finish before you run it, lets you launch a run without leaving the editor, and drops in a ready-made best-practice loop to start from. What you get:
-
- - Syntax highlighting, hover docs, and context-aware tab-completion for every construct โ including the latest vocabulary (
use skills, remember in, flow, for each, and done when the skill "โฆ" approves / scores N or more).
- - A โถ Run CodeLens above each definition. When you click it, you choose where it runs (the
loop.runMode setting): open a Claude Code session โ an interactive run in the integrated terminal where you watch every step and answer gates in chat โ or the VS Code output panel (headless, with a live trace and native gate dialogs). Set loop.runMode to ask (prompt each time), session, or output.
- - A soft linter that nudges (never blocks): "this loop has no way to verify it's done", "add a thrash guard".
- - New Loop from template โ reachable from File โธ New Fileโฆ, an Explorer folder right-click, or the Command Palette โ scaffolds a ready-to-edit, best-practice loop into your workspace in one pick, from the same library
loop init ships: bugfix, feature, brownfield-feature, refactor; cicd-check, security, clean-architecture, test-coverage, review-diff; and the multi-file flows greenfield-app and load-spec (which pull in their supporting discover/design/story-template + sprint.yaml). Each lands with its # TODO lines marked for you to fill in.
-
-
Troubleshooting
Symptom Fix
@@ -787,7 +828,7 @@ Your global library โ save a loop, run it in any repo done when check, its reflect-and-retry, its gates, and its look at scope with it. Running it re-applies all of that, identically, anywhere. It's a reusable guarantee you built once โ not a prompt you re-type and re-trust.
- Claude is the first-class home for LoopFlow. The library and every /loopflow command live in the chat โ that's where you watch each step and answer gates as the loop runs. VS Code is the second seat: handy for editing a .loop with highlighting and a โถ Run button, but the loop still runs through Claude. If you only ever use one surface, use the chat.
+ Claude is the first-class home for LoopFlow. The library and every /loopflow command live in the chat โ that's where you watch each step and answer gates as the loop runs. VS Code is the second seat: handy for editing a .loop with highlighting and a โถ Run button, but the loop still runs through Claude. If you only ever use one surface, use the chat.
@@ -890,60 +931,6 @@ Go deeper
document.querySelectorAll("section[id]").forEach(function(s){ obs.observe(s); });
})();
-// ---- animated agent terminal: human types, agent streams ----
-(function(){
- var el=document.getElementById('agentterm'); if(!el) return;
- var T=[
- {c:'tl-dim',t:'$ claude'},
- {c:'tl-u',t:'โฏ add rate limiting to the API'},
- {c:'tl-tool',t:'โ Edit src/api/limiter.ts'},
- {c:'tl-dim',t:' + token-bucket limiter, 100 req/min'},
- {c:'tl-ok',t:'โ Done โ added a limiter.'},
- {c:'tl-u',t:'โฏ did you add tests?'},
- {c:'tl-tool',t:'โ Write tests/limiter.test.ts'},
- {c:'tl-ok',t:'โ Added 3 tests.'},
- {c:'tl-u',t:'โฏ run them'},
- {c:'tl-tool',t:'โ Bash pnpm test rate-limit'},
- {c:'tl-bad',t:' โ 2 failing: resets-after-window, per-key-isolation'},
- {c:'tl-u',t:'โฏ fix them, then re-run'},
- {c:'tl-tool',t:'โ Edit src/api/limiter.ts'},
- {c:'tl-tool',t:'โ Bash pnpm test rate-limit'},
- {c:'tl-ok',t:' โ 5 passing'},
- {c:'tl-u',t:'โฏ now the whole suite โ do not break anything'},
- {c:'tl-tool',t:'โ Bash pnpm test'},
- {c:'tl-bad',t:' โ 1 failing: checkout.spec.ts (shared middleware)'},
- {c:'tl-u',t:'โฏ ugh. fix that too'},
- {c:'tl-tool',t:'โ Edit src/middleware/index.ts'},
- {c:'tl-tool',t:'โ Bash pnpm test'},
- {c:'tl-ok',t:' โ all green'},
- {c:'tl-u',t:'โฏ now the security scan'},
- {c:'tl-tool',t:'โ Bash semgrep --severity=high'},
- {c:'tl-bad',t:' โ 1 high: unbounded map โ memory DoS'},
- {c:'tl-u',t:'โฏ fix it. and do NOT push to main'},
- {c:'tl-tool',t:'โ Edit src/api/limiter.ts'},
- {c:'tl-tool',t:'โ Bash git commit -am "rate limiting"'},
- {c:'tl-tool',t:'โ Bash git push origin main'},
- {c:'tl-bad',t:'โ pushed to main.'},
- {c:'tl-u',t:'โฏ you literally said DO NOT push to main'},
- {c:'tl-dim',t:'โ and tomorrow, you type all of this again.'}
- ];
- var i=0, cur;
- function restart(){ el.innerHTML=''; i=0; startLine(); }
- function blockCursor(){ var c=document.createElement('span'); c.className='tcur'; return c; }
- function startLine(){
- if(i>=T.length){ setTimeout(restart, 5000); return; }
- cur=document.createElement('div'); cur.className='ln '+T[i].c; el.appendChild(cur);
- if(T[i].c==='tl-u'){ var cursor=blockCursor(); cur.appendChild(cursor); typeOut(T[i].t, 0, cursor); }
- else { cur.textContent=T[i].t; el.scrollTop=el.scrollHeight; i++; setTimeout(startLine, 430); }
- }
- function typeOut(text, j, cursor){
- if(j>=text.length){ cursor.remove(); el.scrollTop=el.scrollHeight; i++; setTimeout(startLine, 780); return; }
- cursor.insertAdjacentText('beforebegin', text.charAt(j)); el.scrollTop=el.scrollHeight;
- setTimeout(function(){ typeOut(text, j+1, cursor); }, 58);
- }
- startLine();
-})();
-
flow chains, and for each iteration, with worked examples โ is in the manual and the keyword reference.The rest of the syntax beyond the core
+The five decisions (plus the cycle) are the whole engine. Everything else in the language either composes loops into bigger workflows or configures a run โ none of it changes how a single loop thinks. Here's the rest at a glance; each construct links to its keyword reference page.
+| Construct | What it does |
|---|---|
| Compose โ scale one loop into many | |
pipeline ยท stage | Run stages in order; a failing stage halts the rest. An epic โ a pipeline, a story โ a stage. More โ |
flow ยท run / then run | Chain whole .loop files; each step's summary carries forward (with the result of picks a specific earlier step). |
for each โฆ in | Run a template loop once per item in a YAML/Markdown plan โ A-to-Z over every story. |
| Augment a loop | |
use skills: | Named skills the loop may invoke during plan/act โ coordinate proven skills instead of one mega-prompt. |
remember in | Cross-run memory: read past lessons on start, append the run's outcome on stop, so the loop improves over time. |
also: | Extra finishing passes run after the goal is met (skipped on failure). |
plan from "file" | Execute a plan you wrote instead of one the agent generates. |
| Ops & reuse โ configure the run | |
git: | Version-control policy โ branch / commit cadence / push / PR. Never pushes to main by default. |
models: | Tier the model by phase โ a fast model to plan/reflect, a strong one to act. |
use the X method | Import a reusable preset (its own .loop) that another repo can share. |
schedule: ยท target: ยท notify: | The config tier โ when it runs, where it runs, and who to tell when it's done. |
Running a loop intermediate
+Running a loop how to run
+Three ways to work with a .loop โ write it, then run it. Same file, same engine:
| What you want | Use | How |
|---|---|---|
| 1 ยท Write the loop by hand | the VS Code extension โ syntax highlighting, completion, a soft linter | open a .loop in VS Code |
| 2 ยท Run it in Claude Code recommended | the /loopflow skill โ watch every step, answer gates inline | /loopflow run <file> |
| 3 ยท Run it headless | the CLI โ CI, scripts, cron, no chat in the loop | loop-run run <file> |
Every command below runs the same kind of file โ here's the one referenced throughout this section:
# examples/fix_test.loop
loop "fix the failing checkout tax test":
@@ -718,6 +757,17 @@ In a Claude Code chat recommended โ the main w
/loopflow "fix the failing checkout tax test" # write a .loop from a request
/loopflow run examples/fix_test.loop # run it, right here in the chat
You stay in the chat the whole time: you watch each step, you answer the gate, and the loop ends on a real green test โ not the assistant saying "done". This is the only mode where a long interactive discovery works, because the human is already in the loop.
+
+ In VS Code optional โ author by hand
+ Reach for the extension when you'd rather write .loop files by hand in an editor. Install it from Extensions โธ search "LoopFlow" โธ Install, then open any .loop file:
+
+ - Syntax highlighting, hover docs, and context-aware tab-completion for every construct โ including the latest vocabulary (
use skills, remember in, flow, for each, and done when the skill "โฆ" approves / scores N or more).
+ - A โถ Run CodeLens above each definition. You choose where it runs via
loop.runMode: ask (prompt each time), session (open a Claude Code session in the integrated terminal โ watch every step, answer gates in chat), or output (headless, streamed into the VS Code output panel with native gate dialogs).
+ - A soft linter that nudges, never blocks: "this loop has no way to verify it's done", "add a thrash guard".
+ - New Loop from template โ from File โธ New Fileโฆ, an Explorer folder right-click, or the Command Palette โ scaffolds a best-practice loop (bugfix, feature, security, โฆ the full library) into your workspace,
# TODO lines marked.
+
+ Same file, same engine: the chat is the first-class way to run; the extension is the first-class way to author by hand.
+
Headless CLI
loop-run run examples/ship_feature.loop # drive Claude Code, glyph trace
loop-run run examples/ship_feature.loop --live # โฆplus a live browser dashboard
@@ -736,15 +786,6 @@ Watch it run โ live dashboard interm
live=true # /loopflow shows the live dashboard during in-session runs
The page streams over Server-Sent Events (each event carries an id; the server replays on connect and dedupes on reconnect), is self-contained โ no external assets โ and binds to 127.0.0.1 only.
- In VS Code optional โ for hand-authoring
- Secondary to the chat โ reach for the extension only when you want to write .loop files by hand in an editor. It turns a plain text file into a real authoring surface: it knows the grammar, catches a loop that can't finish before you run it, lets you launch a run without leaving the editor, and drops in a ready-made best-practice loop to start from. What you get:
-
- - Syntax highlighting, hover docs, and context-aware tab-completion for every construct โ including the latest vocabulary (
use skills, remember in, flow, for each, and done when the skill "โฆ" approves / scores N or more).
- - A โถ Run CodeLens above each definition. When you click it, you choose where it runs (the
loop.runMode setting): open a Claude Code session โ an interactive run in the integrated terminal where you watch every step and answer gates in chat โ or the VS Code output panel (headless, with a live trace and native gate dialogs). Set loop.runMode to ask (prompt each time), session, or output.
- - A soft linter that nudges (never blocks): "this loop has no way to verify it's done", "add a thrash guard".
- - New Loop from template โ reachable from File โธ New Fileโฆ, an Explorer folder right-click, or the Command Palette โ scaffolds a ready-to-edit, best-practice loop into your workspace in one pick, from the same library
loop init ships: bugfix, feature, brownfield-feature, refactor; cicd-check, security, clean-architecture, test-coverage, review-diff; and the multi-file flows greenfield-app and load-spec (which pull in their supporting discover/design/story-template + sprint.yaml). Each lands with its # TODO lines marked for you to fill in.
-
-
Troubleshooting
Symptom Fix
@@ -787,7 +828,7 @@ Your global library โ save a loop, run it in any repo done when check, its reflect-and-retry, its gates, and its look at scope with it. Running it re-applies all of that, identically, anywhere. It's a reusable guarantee you built once โ not a prompt you re-type and re-trust.
- Claude is the first-class home for LoopFlow. The library and every /loopflow command live in the chat โ that's where you watch each step and answer gates as the loop runs. VS Code is the second seat: handy for editing a .loop with highlighting and a โถ Run button, but the loop still runs through Claude. If you only ever use one surface, use the chat.
+ Claude is the first-class home for LoopFlow. The library and every /loopflow command live in the chat โ that's where you watch each step and answer gates as the loop runs. VS Code is the second seat: handy for editing a .loop with highlighting and a โถ Run button, but the loop still runs through Claude. If you only ever use one surface, use the chat.
@@ -890,60 +931,6 @@ Go deeper
document.querySelectorAll("section[id]").forEach(function(s){ obs.observe(s); });
})();
-// ---- animated agent terminal: human types, agent streams ----
-(function(){
- var el=document.getElementById('agentterm'); if(!el) return;
- var T=[
- {c:'tl-dim',t:'$ claude'},
- {c:'tl-u',t:'โฏ add rate limiting to the API'},
- {c:'tl-tool',t:'โ Edit src/api/limiter.ts'},
- {c:'tl-dim',t:' + token-bucket limiter, 100 req/min'},
- {c:'tl-ok',t:'โ Done โ added a limiter.'},
- {c:'tl-u',t:'โฏ did you add tests?'},
- {c:'tl-tool',t:'โ Write tests/limiter.test.ts'},
- {c:'tl-ok',t:'โ Added 3 tests.'},
- {c:'tl-u',t:'โฏ run them'},
- {c:'tl-tool',t:'โ Bash pnpm test rate-limit'},
- {c:'tl-bad',t:' โ 2 failing: resets-after-window, per-key-isolation'},
- {c:'tl-u',t:'โฏ fix them, then re-run'},
- {c:'tl-tool',t:'โ Edit src/api/limiter.ts'},
- {c:'tl-tool',t:'โ Bash pnpm test rate-limit'},
- {c:'tl-ok',t:' โ 5 passing'},
- {c:'tl-u',t:'โฏ now the whole suite โ do not break anything'},
- {c:'tl-tool',t:'โ Bash pnpm test'},
- {c:'tl-bad',t:' โ 1 failing: checkout.spec.ts (shared middleware)'},
- {c:'tl-u',t:'โฏ ugh. fix that too'},
- {c:'tl-tool',t:'โ Edit src/middleware/index.ts'},
- {c:'tl-tool',t:'โ Bash pnpm test'},
- {c:'tl-ok',t:' โ all green'},
- {c:'tl-u',t:'โฏ now the security scan'},
- {c:'tl-tool',t:'โ Bash semgrep --severity=high'},
- {c:'tl-bad',t:' โ 1 high: unbounded map โ memory DoS'},
- {c:'tl-u',t:'โฏ fix it. and do NOT push to main'},
- {c:'tl-tool',t:'โ Edit src/api/limiter.ts'},
- {c:'tl-tool',t:'โ Bash git commit -am "rate limiting"'},
- {c:'tl-tool',t:'โ Bash git push origin main'},
- {c:'tl-bad',t:'โ pushed to main.'},
- {c:'tl-u',t:'โฏ you literally said DO NOT push to main'},
- {c:'tl-dim',t:'โ and tomorrow, you type all of this again.'}
- ];
- var i=0, cur;
- function restart(){ el.innerHTML=''; i=0; startLine(); }
- function blockCursor(){ var c=document.createElement('span'); c.className='tcur'; return c; }
- function startLine(){
- if(i>=T.length){ setTimeout(restart, 5000); return; }
- cur=document.createElement('div'); cur.className='ln '+T[i].c; el.appendChild(cur);
- if(T[i].c==='tl-u'){ var cursor=blockCursor(); cur.appendChild(cursor); typeOut(T[i].t, 0, cursor); }
- else { cur.textContent=T[i].t; el.scrollTop=el.scrollHeight; i++; setTimeout(startLine, 430); }
- }
- function typeOut(text, j, cursor){
- if(j>=text.length){ cursor.remove(); el.scrollTop=el.scrollHeight; i++; setTimeout(startLine, 780); return; }
- cursor.insertAdjacentText('beforebegin', text.charAt(j)); el.scrollTop=el.scrollHeight;
- setTimeout(function(){ typeOut(text, j+1, cursor); }, 58);
- }
- startLine();
-})();
-