@loop-lang/loop 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +69 -13
- package/assets/AGENTS.md +60 -11
- package/assets/skill/SKILL.md +142 -35
- package/package.json +3 -2
- package/src/cli.mjs +12 -10
- package/src/init.mjs +7 -6
- package/src/postinstall.mjs +33 -0
package/README.md
CHANGED
|
@@ -1,34 +1,90 @@
|
|
|
1
1
|
# @loop-lang/loop
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Loop** is a small natural-language DSL for *loop engineering* — a `.loop` file describes a
|
|
4
|
+
self-correcting, human-gated coding workflow: its goal, what it may read, how it verifies
|
|
5
|
+
itself, when it stops, and where a human steps in. Your agent then **runs that loop**,
|
|
6
|
+
cycling plan → act → observe and reflecting on failures until the goal is met.
|
|
7
|
+
|
|
8
|
+
This package drops Loop into any repo so **Claude Code — or any agent** — can author and run
|
|
9
|
+
`.loop` files.
|
|
4
10
|
|
|
5
11
|
```sh
|
|
6
12
|
npx @loop-lang/loop init
|
|
7
13
|
```
|
|
8
14
|
|
|
9
|
-
|
|
15
|
+
## What a `.loop` looks like
|
|
16
|
+
|
|
17
|
+
```loop
|
|
18
|
+
loop "fix the failing checkout tax test":
|
|
19
|
+
goal: the tax line on the cart is correct
|
|
20
|
+
look at: src/cart, and the last failure
|
|
21
|
+
done when "pnpm test checkout" passes
|
|
22
|
+
also: a security scan
|
|
23
|
+
after 6 tries: stop and warn "still red — needs a human"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Plain words, but precise: `done when` is how the loop checks itself, `also:` adds a quality
|
|
27
|
+
pass once the goal is met, and the guard stops a thrashing loop instead of looping forever.
|
|
28
|
+
Bigger jobs scale up to a **`pipeline`** (an epic → ordered stages) or a **`flow`** (a chain
|
|
29
|
+
of whole `.loop` files — discover → design → build each story).
|
|
30
|
+
|
|
31
|
+
## What `init` scaffolds
|
|
10
32
|
|
|
11
|
-
- **`AGENTS.md`** — the full
|
|
12
|
-
|
|
33
|
+
- **`AGENTS.md`** — the full language reference. Any agent that opens the repo (Claude Code,
|
|
34
|
+
Cursor, Copilot, Codex…) now knows how to write a `.loop`.
|
|
35
|
+
- **`.claude/skills/loopflow`** — the Claude Code **`/loopflow`** skill (author + run loops
|
|
36
|
+
natively in a chat). *Invoked as `/loopflow`, not `/loop` — the latter is Claude Code's
|
|
37
|
+
built-in scheduler.*
|
|
38
|
+
- **`CLAUDE.md`** pointer — a standing nudge so Claude Code reaches for a `.loop` instead of
|
|
39
|
+
doing the work ad hoc. (Written by default; `--no-claude-md` to skip.)
|
|
13
40
|
- **`examples/fix_test.loop`** — a starter loop to run.
|
|
14
41
|
|
|
15
|
-
|
|
42
|
+
## The `/loopflow` skill — a guided tour
|
|
43
|
+
|
|
44
|
+
You don't need to know the language first. In a Claude Code chat, just describe the work:
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
/loopflow build a rate limiter — done when the burst test passes, and run a security pass
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
The skill **interviews you** — it scopes the purpose first (a one-test fix? a feature? a
|
|
51
|
+
whole app?), offers the quality passes worth adding (tests, security, code review, clean
|
|
52
|
+
architecture), then writes the `.loop` *in front of you*, naming each keyword as it goes.
|
|
53
|
+
By the end of one loop you've learned the language by building. Then it runs the loop right
|
|
54
|
+
in the chat, so you watch every step and answer any gate inline.
|
|
55
|
+
|
|
56
|
+
Already have a `.loop`? Run it directly:
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
/loopflow run examples/fix_test.loop
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Options
|
|
16
63
|
|
|
17
64
|
```
|
|
18
65
|
loop init [--dir <path>] [--global] [--no-skill] [--no-example]
|
|
19
|
-
[--claude-md] [--cursor] [--copilot] [--all-agents] [--force]
|
|
66
|
+
[--no-claude-md] [--cursor] [--copilot] [--all-agents] [--force]
|
|
20
67
|
```
|
|
21
68
|
|
|
22
69
|
- `--global` — install the skill into `~/.claude/skills` instead of the repo.
|
|
23
|
-
- `--
|
|
70
|
+
- `--no-claude-md` — skip the `CLAUDE.md` pointer (written by default).
|
|
71
|
+
- `--cursor` / `--copilot` / `--all-agents` — also drop memory pointers for those agents.
|
|
72
|
+
- `--no-skill` / `--no-example` — skip the skill or the starter loop.
|
|
24
73
|
- `--force` — overwrite an existing skill / example.
|
|
25
74
|
|
|
26
|
-
Re-running `init` is safe: the `AGENTS.md` block is managed between markers and updated in
|
|
75
|
+
Re-running `init` is safe: the `AGENTS.md` block is managed between markers and updated in
|
|
76
|
+
place, never duplicated.
|
|
77
|
+
|
|
78
|
+
## After install
|
|
79
|
+
|
|
80
|
+
- **Claude Code:** open a chat in the repo → `/loopflow run examples/fix_test.loop`, or just
|
|
81
|
+
describe the work and let the skill write the `.loop`.
|
|
82
|
+
- **Any agent:** it reads `AGENTS.md` and authors + runs loops the same way.
|
|
83
|
+
- **Headless:** install the full runtime to run loops from the CLI with `loop run <file>`.
|
|
27
84
|
|
|
28
|
-
|
|
85
|
+
## Learn more
|
|
29
86
|
|
|
30
|
-
-
|
|
31
|
-
|
|
32
|
-
- **Headless:** install the full runtime for `loop run <file>`.
|
|
87
|
+
The [loop-lang repo](https://github.com/tickets-forge-dev/loop-lang) — tutorial, full keyword
|
|
88
|
+
reference, and the playable Loop Lab.
|
|
33
89
|
|
|
34
|
-
|
|
90
|
+
Apache-2.0.
|
package/assets/AGENTS.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
# AGENTS.md — authoring
|
|
1
|
+
# AGENTS.md — authoring LoopFlow (`.loop`) flows
|
|
2
2
|
|
|
3
3
|
This file teaches an AI assistant (Claude Code, Copilot, Cursor, etc.) how to write
|
|
4
|
-
**
|
|
4
|
+
**LoopFlow** flows. When a user asks you to design a staged, self-correcting, or human-gated
|
|
5
5
|
coding workflow — "set up a loop to fix X", "turn this epic into a pipeline", "automate
|
|
6
6
|
this multi-step task" — author a `.loop` file using the grammar below, then let the user
|
|
7
|
-
run it with `loop run file.loop`.
|
|
7
|
+
run it with `loop-run run file.loop`.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
LoopFlow is a small natural-language DSL. A `.loop` file describes the *movement* of an AI
|
|
10
10
|
coding loop: its objective, the context it may read, the actions it's allowed, how it
|
|
11
11
|
verifies itself, when it stops, and where a human steps in. The five knobs —
|
|
12
12
|
**objective, context, actions, verification, stopping rules** — are first-class instead
|
|
@@ -19,6 +19,16 @@ bug fixes with a test, refactors gated by a check, an epic broken into stories,
|
|
|
19
19
|
migration with a verification step. Don't write one for a one-off question or a trivial
|
|
20
20
|
edit — just do those directly.
|
|
21
21
|
|
|
22
|
+
Before building a loop, run the four-condition test — build one only when all four hold:
|
|
23
|
+
|
|
24
|
+
1. **Does the task repeat?** A one-time task is just a normal prompt.
|
|
25
|
+
2. **Is there a clear definition of "done"?** You must be able to verify completion — a
|
|
26
|
+
`done when` predicate (a test, a command, or a review skill). No check, no loop.
|
|
27
|
+
3. **Can you afford the iterations?** A loop re-prompts itself until done; that costs tokens.
|
|
28
|
+
Keep the `done when` check fast and add an `after N tries` thrash guard.
|
|
29
|
+
4. **Does the loop have the tools to verify itself?** It needs a way to implement *and* check
|
|
30
|
+
its own work — the predicate command or the review skill must actually be runnable.
|
|
31
|
+
|
|
22
32
|
**Interview the user before writing it.** Walk the five decisions, asking the
|
|
23
33
|
high-leverage questions and offering defaults for the rest: (1) the **goal**;
|
|
24
34
|
(2) the **`done when`** check (test / command / scan finds-nothing / human);
|
|
@@ -48,6 +58,8 @@ look at: <files>, and the last failure context the agent reads before acting (
|
|
|
48
58
|
allow edits automatically, but ask me before <classes> action policy
|
|
49
59
|
each cycle: plan, then act, then observe the repeated steps (any subset, in order)
|
|
50
60
|
also: <pass>, <pass> extra finishing passes run after the goal is met
|
|
61
|
+
use skills: <a>, <b> named skills the loop may invoke during plan/act
|
|
62
|
+
remember in "<file.md>" cross-run memory: read lessons on start, append an outcome on stop
|
|
51
63
|
reflect turn a failure into context for the next plan (the back-edge)
|
|
52
64
|
|
|
53
65
|
when it passes and the goal is met: stop
|
|
@@ -59,7 +71,7 @@ a human approves the plan first (human authors/approves the plan before a
|
|
|
59
71
|
a human reviews before stopping (human judges the result before the loop stops)
|
|
60
72
|
a human approves before <action> (a blocking gate before a stage, e.g. deploy)
|
|
61
73
|
|
|
62
|
-
plan from
|
|
74
|
+
plan from "<file>" (read the plan from a file you control instead of generating it)
|
|
63
75
|
|
|
64
76
|
use the <method> method schedule: <when> runner: <agent> target: <dir> (config tier)
|
|
65
77
|
models: fast <model>, strong <model> model tiering: plan/reflect/also→fast, act→strong (cascades; override e.g. `act fast`, `all strong`)
|
|
@@ -72,11 +84,49 @@ done when the test "billing.spec.ts::apostrophe" passes # a named test
|
|
|
72
84
|
done when "pnpm test" passes # a shell command, exit 0
|
|
73
85
|
done when "semgrep --severity=high" finds nothing # a shell command, empty output
|
|
74
86
|
done when a human confirms "looks right at 375px" # a human check
|
|
87
|
+
done when the skill "email-review" approves # a review skill: approved / not
|
|
88
|
+
done when the skill "email-review" scores 8 or more # a review skill: numeric threshold
|
|
75
89
|
```
|
|
76
90
|
|
|
77
91
|
The command in a predicate runs in the user's shell with their privileges (like an npm
|
|
78
92
|
script). It IS meant to be a real command. Prefer a fast, deterministic check.
|
|
79
93
|
|
|
94
|
+
The **skill** predicate bridges an abstract goal to a verifiable one: when "done" isn't a
|
|
95
|
+
test or a command (a good email, a sound design), have a review skill return an
|
|
96
|
+
approved/rejected verdict or a numeric score. Build that review skill manually first and
|
|
97
|
+
confirm it judges well, then wire it in as the loop's check.
|
|
98
|
+
|
|
99
|
+
### `use skills` — coordinate proven skills
|
|
100
|
+
|
|
101
|
+
Instead of one giant prompt, a loop can name skills it may call while planning and acting:
|
|
102
|
+
|
|
103
|
+
```loop
|
|
104
|
+
loop "decide whether to cancel the morning run":
|
|
105
|
+
goal: a clear go / no-go call the runner trusts
|
|
106
|
+
use skills: check-weather, analyze-workout
|
|
107
|
+
done when the skill "workout-review" approves
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
This is **skill-driven development**: build and battle-test each skill on its own first,
|
|
111
|
+
then have the loop coordinate them. Don't invent a loop around skills that don't exist yet —
|
|
112
|
+
prove the skill manually, then wire it in (as an execution skill via `use skills:`, or as a
|
|
113
|
+
verifier via `done when the skill "…" approves`). See `examples/skills_memory.loop`.
|
|
114
|
+
|
|
115
|
+
### `remember in` — cross-run memory
|
|
116
|
+
|
|
117
|
+
A loop forgets everything between runs unless you give it a memory file. `remember in` makes
|
|
118
|
+
the loop read the file's lessons into its first plan and append a dated outcome entry when it
|
|
119
|
+
stops — so it improves run over run instead of repeating mistakes.
|
|
120
|
+
|
|
121
|
+
```loop
|
|
122
|
+
loop "...":
|
|
123
|
+
goal: ...
|
|
124
|
+
remember in "morning-run.memory.md"
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
`reflect` is *within-run* memory (a failure feeds the next plan); `remember` is its
|
|
128
|
+
*across-run* counterpart. The file is plain markdown — readable and editable by a human.
|
|
129
|
+
|
|
80
130
|
### `flow` — chaining loops across files
|
|
81
131
|
|
|
82
132
|
A `flow` sequences multiple `.loop` files. Each step runs the whole file (plan→act→observe
|
|
@@ -232,18 +282,17 @@ loop "add a healthcheck endpoint":
|
|
|
232
282
|
## Show the flow — every time it changes
|
|
233
283
|
|
|
234
284
|
Whenever you create or edit a `.loop`, print its flow so the user sees the shape.
|
|
235
|
-
Run `loop show file.loop`, or render the compact ASCII yourself: the cycle
|
|
285
|
+
Run `loop-run show file.loop`, or render the compact ASCII yourself: the cycle
|
|
236
286
|
(`plan → act → observe`), the `↺` reflect back-edge, the `✓ done when` check, the
|
|
237
287
|
`⛔` thrash guard, and any `👤` gates. For a pipeline, list stages in order; for a
|
|
238
|
-
flow, show the file chain. `loop ls` lists every loop in the repo.
|
|
288
|
+
flow, show the file chain. `loop-run ls` lists every loop in the repo.
|
|
239
289
|
|
|
240
290
|
## Running what you wrote
|
|
241
291
|
|
|
242
|
-
- `loop run file.loop` — execute it on Claude Code (plan/act/observe, reflect on failure,
|
|
292
|
+
- `loop-run run file.loop` — execute it on Claude Code (plan/act/observe, reflect on failure,
|
|
243
293
|
verify with `done when`, pause at human gates).
|
|
244
|
-
- `loop show file.loop` — print the loop's flow as compact ASCII (and `loop ls` to list them).
|
|
245
|
-
- `loop viz file.loop` — open a visual HTML schematic of the flow.
|
|
246
|
-
- `loop export file.loop` — emit an Archon workflow YAML (optional interop).
|
|
294
|
+
- `loop-run show file.loop` — print the loop's flow as compact ASCII (and `loop-run ls` to list them).
|
|
295
|
+
- `loop-run viz file.loop` — open a visual HTML schematic of the flow.
|
|
247
296
|
|
|
248
297
|
## Authoring checklist
|
|
249
298
|
|
package/assets/skill/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
3
|
-
description: Create and run Loop (.loop) flows — a natural-language DSL for loop engineering. Use when the user wants to author, write, run, or execute a self-correcting or human-gated AI coding loop, turn an epic into a pipeline, fix a bug "as a loop", or mentions a .loop file or "loop engineering".
|
|
2
|
+
name: loopflow
|
|
3
|
+
description: Create and run Loop (.loop) flows — a natural-language DSL for loop engineering. Use when the user wants to author, write, run, or execute a self-correcting or human-gated AI coding loop, turn an epic into a pipeline, fix a bug "as a loop", build a feature or whole app "as a loop", learn what Loop is or how to use it, or mentions a .loop file or "loop engineering". Invoked as /loopflow (the name avoids colliding with the built-in /loop scheduler).
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Loop
|
|
@@ -40,6 +40,8 @@ look at: <files>, and the last failure context to read before acting
|
|
|
40
40
|
allow edits automatically, but ask me before <classes> action policy
|
|
41
41
|
each cycle: plan, then act, then observe the repeated steps (any subset, in order)
|
|
42
42
|
also: <pass>, <pass> extra finishing passes after the goal is met
|
|
43
|
+
use skills: <a>, <b> named skills the loop may invoke during plan/act
|
|
44
|
+
remember in "<file.md>" cross-run memory: read lessons on start, append an outcome on stop
|
|
43
45
|
when it fails: reflect on <focus>, then plan again
|
|
44
46
|
when it passes and the goal is met: stop
|
|
45
47
|
when blocked: ask a human
|
|
@@ -47,6 +49,14 @@ after <N> tries: stop and warn "<message>" thrash guard
|
|
|
47
49
|
a human approves the plan first human plan gate
|
|
48
50
|
a human reviews before stopping human review gate
|
|
49
51
|
a human approves before <action> stage gate (in a stage)
|
|
52
|
+
|
|
53
|
+
# config tier (top of file): how the loop is powered & scheduled
|
|
54
|
+
use the <method> method pull a preset (e.g. BMAD) as the base
|
|
55
|
+
models: fast <m>, strong <m> model tiering — plan/reflect/also→fast, act→strong
|
|
56
|
+
(cascades; override e.g. `act fast`, `all strong`)
|
|
57
|
+
schedule: <when> run unattended on a cadence
|
|
58
|
+
runner: <agent> which agent executes the loop
|
|
59
|
+
target: <dir> operate on another directory/repo
|
|
50
60
|
```
|
|
51
61
|
|
|
52
62
|
Predicates:
|
|
@@ -55,6 +65,8 @@ done when the test "file.spec.ts::name" passes
|
|
|
55
65
|
done when "pnpm test" passes # shell command, exit 0
|
|
56
66
|
done when "semgrep --severity=high" finds nothing # empty output
|
|
57
67
|
done when a human confirms "looks right"
|
|
68
|
+
done when the skill "email-review" approves # a review skill: approved / not
|
|
69
|
+
done when the skill "email-review" scores 8 or more # a review skill: numeric threshold
|
|
58
70
|
```
|
|
59
71
|
|
|
60
72
|
Rules: indentation is structural (two spaces); `loop`/`pipeline` at column 0; comments
|
|
@@ -62,36 +74,89 @@ start with `#`. An epic → a `pipeline`; each story → a `stage`.
|
|
|
62
74
|
|
|
63
75
|
---
|
|
64
76
|
|
|
65
|
-
## Creating a .loop —
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
the
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
77
|
+
## Creating a .loop — be a guide, not a guesser
|
|
78
|
+
|
|
79
|
+
Most people reaching for this skill don't yet know what Loop can do. Your job is to
|
|
80
|
+
**guide them to the right loop for their purpose** — and teach the language by writing
|
|
81
|
+
it in front of them. Never silently guess the loop; interview first, then author. Ask
|
|
82
|
+
one topic at a time, and always offer a default so a confident user can accept it all
|
|
83
|
+
in one reply.
|
|
84
|
+
|
|
85
|
+
### Step 0 — scope the purpose first (ask this before anything else)
|
|
86
|
+
|
|
87
|
+
Open with **"What do you want the loop to accomplish?"** and show the range, so the
|
|
88
|
+
user sees what's possible and picks a scale:
|
|
89
|
+
|
|
90
|
+
| Scale | Example purpose | Shape in Loop |
|
|
91
|
+
|-------|-----------------|---------------|
|
|
92
|
+
| **Tiny** | "Make this one failing test pass." | a single `loop` |
|
|
93
|
+
| **Small** | "Fix this bug across a few files; gate the migration." | a `loop` + policy + gate |
|
|
94
|
+
| **Medium** | "Build the checkout feature — a few stories, each tested." | a `pipeline` of `stage`s |
|
|
95
|
+
| **Large** | "Build a whole app, A-to-Z." | a `flow`: discover → design → build each story |
|
|
96
|
+
|
|
97
|
+
Name the shape their answer implies (*"that's a **pipeline** — a sequence of stages"*)
|
|
98
|
+
so the vocabulary attaches to their own goal. This one question turns a vague request
|
|
99
|
+
into a scoped loop and teaches the three top-level forms at once.
|
|
100
|
+
|
|
101
|
+
### Step 1 — do they already have a plan?
|
|
102
|
+
|
|
103
|
+
Ask **"Do you have a spec, plan, ticket, or epic already?"**
|
|
104
|
+
- **Yes** → point `look at:` at it; if it's an epic / story list, turn each story into a
|
|
105
|
+
`stage` of a `pipeline` (or `for each` over the plan file).
|
|
106
|
+
- **No, and it's medium/large** → begin the flow with a **discovery loop** whose
|
|
107
|
+
`done when` is "the plan file exists and validates" — it interviews them, writes the plan.
|
|
108
|
+
- **No, and it's small** → skip planning; go straight to the loop.
|
|
109
|
+
|
|
110
|
+
### Step 2 — which quality passes? (offer the menu — don't wait to be asked)
|
|
111
|
+
|
|
112
|
+
This is what makes Loop worth running. Proactively offer the quality sub-loops:
|
|
113
|
+
|
|
114
|
+
> "Want the loop to enforce quality every cycle too? Common ones: **tests** (write/keep
|
|
115
|
+
> green), **security** (a scan that must find nothing), **code review**, **clean
|
|
116
|
+
> architecture** (boundary checks). I can add these as `also:` finishing passes on one
|
|
117
|
+
> loop, or as their own gated `stage`s in a pipeline."
|
|
118
|
+
|
|
119
|
+
Translate their picks into syntax in front of them so they see the mapping:
|
|
120
|
+
- tests → `done when "<test cmd>" passes`
|
|
121
|
+
- security → `also: a security scan`, or `done when "semgrep --severity=high" finds nothing`
|
|
122
|
+
- review / architecture → `also: <pass>`, or a `stage` with `a human approves before <X>`
|
|
123
|
+
|
|
124
|
+
### Step 3 — the remaining decisions (defaults offered, one reply to accept)
|
|
125
|
+
|
|
126
|
+
Walk these quickly, naming the keyword each time so they learn it:
|
|
127
|
+
1. **Goal** → `goal:` — "what does *done* look like?" Required; never guess this one.
|
|
128
|
+
2. **Verification** → `done when` — a test passing, a command passing, a scan finding
|
|
129
|
+
nothing, or a human confirming. The most important line; always pin it down.
|
|
130
|
+
3. **Context** → `look at:` — offer to infer the files from the repo; append `and the last failure`.
|
|
131
|
+
4. **Actions** → policy — "anything risky to gate: migrations, pushes, deploys?" Default:
|
|
132
|
+
`allow edits automatically`, nothing else gated.
|
|
133
|
+
5. **Stopping** → `after N tries: stop and warn` (default 6) + `when it fails: reflect … then plan again`.
|
|
134
|
+
6. **Human gates** → `a human approves the plan first` / `a human reviews before stopping`
|
|
135
|
+
— default none unless the work is risky.
|
|
136
|
+
7. **Git** → state the safe default ("branch, commit when the goal is met, never push to
|
|
137
|
+
`main`"); ask if they want a PR, a worktree, or to work in place. (Full grammar below.)
|
|
138
|
+
8. **Models (LLM policy)** → `models:` — which model does the work. Default: one model
|
|
139
|
+
throughout (the session's). Offer **tiering** for cost/speed: `models: fast <model>,
|
|
140
|
+
strong <model>` → plan/reflect/also run on *fast*, act runs on *strong*; cascades, and
|
|
141
|
+
you can override per phase (`act fast`, `all strong`).
|
|
142
|
+
9. **Schedule / runner / target (config tier — only if automating)** → ask only when the
|
|
143
|
+
loop runs unattended or against another repo: `schedule: <when>` (run on a cadence),
|
|
144
|
+
`runner: <agent>` (which agent executes), `target: <dir>` (operate on another directory).
|
|
145
|
+
Skip silently for a normal in-session loop.
|
|
146
|
+
|
|
147
|
+
Don't forget the menu in Step 2 also covers `use the <method> method` — pull a whole
|
|
148
|
+
preset (e.g. BMAD) instead of hand-picking passes.
|
|
149
|
+
|
|
150
|
+
Offer the defaults inline (*"I'll add a tests + security pass, gate the migration, a
|
|
151
|
+
6-try guard, work on a branch, one model throughout, no schedule — sound right?"*) so the
|
|
152
|
+
whole interview is one exchange. Name every topic once even when you default it, so the
|
|
153
|
+
user knows the knob exists and can override it.
|
|
154
|
+
Then **write the `.loop`**, always with a real `done when` and a thrash guard, **print
|
|
155
|
+
its flow** (below), and offer to run it.
|
|
156
|
+
|
|
157
|
+
> **Teach by building.** As you write each clause, say what it is (*"`done when` is how
|
|
158
|
+
> the loop checks itself"*). By the end of one loop the user has seen the whole language —
|
|
159
|
+
> that is the point of authoring it here, in the open, rather than headless.
|
|
95
160
|
|
|
96
161
|
## Show the flow — every time it changes
|
|
97
162
|
|
|
@@ -122,10 +187,19 @@ the user explicitly asks for the headless runner.)
|
|
|
122
187
|
1. **Read the file.** (Or, if the `loop` CLI is installed: `loop parse <file> --json` to
|
|
123
188
|
get the structured spec.)
|
|
124
189
|
2. **Execute the loop's semantics, narrating each step:**
|
|
190
|
+
- **memory** — if the loop has `remember in "<file>"`, read that file first (skip if it
|
|
191
|
+
doesn't exist yet) and let its lessons inform your first plan. When the loop stops,
|
|
192
|
+
append a dated entry: `## <date> — <outcome>` with the goal, attempts, and the run's
|
|
193
|
+
lesson (your last reflection). This is how the loop improves across runs.
|
|
125
194
|
- **plan** — inspect the `look at:` files; decide the smallest change toward the goal.
|
|
195
|
+
If the loop declares `use skills:`, you may invoke those named skills (via the Skill
|
|
196
|
+
tool) to do the work — coordinate them rather than re-deriving everything inline.
|
|
126
197
|
- **act** — make the edits. Honor the policy: for `ask me before <X>`, ask the user
|
|
127
198
|
before doing X (migrations, pushes, etc.); auto classes you may do directly.
|
|
128
|
-
- **observe** — run the `done when`
|
|
199
|
+
- **observe** — run the `done when` check and read pass/fail. For a command or named test,
|
|
200
|
+
run it. For `the skill "<name>" approves` / `scores N or more`, invoke that review skill
|
|
201
|
+
on the work and read back its verdict (approved/rejected, or a score vs. the threshold) —
|
|
202
|
+
this is how an abstract goal gets a verifiable check.
|
|
129
203
|
- on **fail** → **reflect** on why (use the failure output), then **plan again** (the
|
|
130
204
|
back-edge). Repeat.
|
|
131
205
|
- **stop** when `done when` passes, or after the thrash guard's N tries (state the
|
|
@@ -223,15 +297,48 @@ Two protections are unconditional and cannot be overridden by any `git:` block:
|
|
|
223
297
|
|
|
224
298
|
### In-chat runner note
|
|
225
299
|
|
|
226
|
-
When you run a loop *inside this conversation* (the `/
|
|
300
|
+
When you run a loop *inside this conversation* (the `/loopflow` skill), you are the git
|
|
227
301
|
operator — you execute plan/act/observe yourself. Before acting, check the `git:` block
|
|
228
302
|
and honor the policy: if `push when done` is set and the current branch is `main` or
|
|
229
303
|
`master`, refuse with a clear message rather than pushing.
|
|
230
304
|
|
|
231
305
|
---
|
|
232
306
|
|
|
307
|
+
## Global library — save a loop, reuse it in any project
|
|
308
|
+
|
|
309
|
+
The user keeps a personal library of loops at **`~/.claude/loopflow/`** — one
|
|
310
|
+
`<name>.loop` per saved loop. It lives beside the installed skill, so a loop saved once is
|
|
311
|
+
runnable from **every** repo. The library is driven entirely from this chat; there is no
|
|
312
|
+
terminal command for it. Create the directory on first save (`mkdir -p ~/.claude/loopflow`).
|
|
313
|
+
|
|
314
|
+
Four operations — recognize them from `/loopflow <verb>` or from plain language:
|
|
315
|
+
|
|
316
|
+
- **save** — *"save this as `<name>`"*, *"save it to my library"*, `/loopflow save …`
|
|
317
|
+
Write the loop's `.loop` source to `~/.claude/loopflow/<name>.loop`. Take `<name>` from
|
|
318
|
+
the user; if they don't give one, slugify the loop's name (`"fix the auth test"` →
|
|
319
|
+
`fix-the-auth-test`). **If that file already exists, show the saved version and confirm
|
|
320
|
+
before overwriting.** Report the path you wrote.
|
|
321
|
+
|
|
322
|
+
- **list** — `/loopflow list`, *"what loops do I have saved"*
|
|
323
|
+
List every `*.loop` in `~/.claude/loopflow/`. For each, print `name — <goal>` (add the
|
|
324
|
+
one-line shape when it helps). An empty or missing dir → say it's empty and how to save one.
|
|
325
|
+
|
|
326
|
+
- **run** — `/loopflow run <name>`, *"run my security loop here"*
|
|
327
|
+
Read `~/.claude/loopflow/<name>.loop` and run it **in the current repo**, exactly as in
|
|
328
|
+
*Running a .loop (in this session)* above. A bare `<name>` means the library; a path or a
|
|
329
|
+
name ending in `.loop` is a local file, so the library never shadows a loop in the repo.
|
|
330
|
+
If `<name>` isn't in the library, say so and offer `list`.
|
|
331
|
+
|
|
332
|
+
- **remove** — `/loopflow remove <name>`, *"delete my `<name>` loop"*
|
|
333
|
+
Delete `~/.claude/loopflow/<name>.loop` after confirming. If it doesn't exist, say so.
|
|
334
|
+
|
|
335
|
+
These are plain files — the user may also open or edit them directly. Saving is a copy, so
|
|
336
|
+
removing a library entry never touches the original loop in a repo.
|
|
337
|
+
|
|
338
|
+
---
|
|
339
|
+
|
|
233
340
|
## Reference
|
|
234
341
|
|
|
235
342
|
The full language reference is in `AGENTS.md` and `docs/MANUAL.md` of the loop-lang repo;
|
|
236
|
-
the CLI (`loop run|viz|
|
|
343
|
+
the CLI (`loop-run run|viz|parse`) and the VSCode extension are alternative ways to run
|
|
237
344
|
the same `.loop` files.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loop-lang/loop",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Install
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Install LoopFlow (.loop) into any repo so Claude Code — or any agent — can author and run self-correcting, human-gated coding loops.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"publishConfig": { "access": "public" },
|
|
7
7
|
"type": "module",
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"scripts": {
|
|
14
14
|
"sync-assets": "node scripts/sync-assets.mjs",
|
|
15
15
|
"prepack": "node scripts/sync-assets.mjs",
|
|
16
|
+
"postinstall": "node src/postinstall.mjs",
|
|
16
17
|
"test": "node scripts/sync-assets.mjs && node --test test/*.test.mjs"
|
|
17
18
|
}
|
|
18
19
|
}
|
package/src/cli.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// @loop-lang/loop — the installer CLI. `loop init` drops Loop into a repo so any
|
|
3
3
|
// agent can author + run .loop files. Running loops happens in your agent (the
|
|
4
|
-
// /
|
|
4
|
+
// /loopflow skill) or headless via the full @loop-lang/runtime CLI.
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { dirname, join, resolve } from "node:path";
|
|
7
7
|
import { init } from "./init.mjs";
|
|
@@ -17,19 +17,19 @@ usage:
|
|
|
17
17
|
|
|
18
18
|
init options:
|
|
19
19
|
--dir <path> install into <path> (default: current directory)
|
|
20
|
-
--global install the /
|
|
21
|
-
--no-skill don't install the Claude Code /
|
|
20
|
+
--global install the /loopflow skill into ~/.claude/skills (done automatically on \`npm install -g\`)
|
|
21
|
+
--no-skill don't install the Claude Code /loopflow skill
|
|
22
22
|
--no-example don't write examples/fix_test.loop
|
|
23
|
-
--claude-md
|
|
23
|
+
--no-claude-md don't write the CLAUDE.md pointer (written by default)
|
|
24
24
|
--cursor also write .cursor/rules/loop.md
|
|
25
25
|
--copilot also write .github/copilot-instructions.md
|
|
26
26
|
--all-agents CLAUDE.md + Cursor + Copilot pointers
|
|
27
27
|
--force overwrite the skill / example if they already exist
|
|
28
28
|
|
|
29
29
|
after init:
|
|
30
|
-
• Claude Code: open a chat in the repo and say /
|
|
30
|
+
• Claude Code: open a chat in the repo and say /loopflow run examples/fix_test.loop
|
|
31
31
|
• any agent: it reads AGENTS.md and can author + run .loop files
|
|
32
|
-
• headless: install @loop/runtime for loop run <file>`;
|
|
32
|
+
• headless: install @loop-lang/runtime for loop-run run <file>`;
|
|
33
33
|
|
|
34
34
|
function flag(argv, name) { return argv.includes(name); }
|
|
35
35
|
function opt(argv, name) { const i = argv.indexOf(name); return i >= 0 ? argv[i + 1] : undefined; }
|
|
@@ -45,7 +45,9 @@ async function main(argv) {
|
|
|
45
45
|
if (cmd === "init") {
|
|
46
46
|
const agents = [];
|
|
47
47
|
if (flag(argv, "--all-agents")) agents.push("claude", "cursor", "copilot");
|
|
48
|
-
|
|
48
|
+
// CLAUDE.md pointer is on by default (gives Claude Code a standing "author a .loop"
|
|
49
|
+
// nudge); --no-claude-md opts out. --claude-md still accepted as an explicit yes.
|
|
50
|
+
if (!flag(argv, "--no-claude-md") && !agents.includes("claude")) agents.push("claude");
|
|
49
51
|
if (flag(argv, "--cursor") && !agents.includes("cursor")) agents.push("cursor");
|
|
50
52
|
if (flag(argv, "--copilot") && !agents.includes("copilot")) agents.push("copilot");
|
|
51
53
|
|
|
@@ -62,14 +64,14 @@ async function main(argv) {
|
|
|
62
64
|
console.log(`\n Loop installed into ${targetDir}\n`);
|
|
63
65
|
for (const s of steps) console.log(` ✓ ${s}`);
|
|
64
66
|
console.log(`\n Next:`);
|
|
65
|
-
console.log(` • In a Claude Code chat here: /
|
|
67
|
+
console.log(` • In a Claude Code chat here: /loopflow run examples/fix_test.loop`);
|
|
66
68
|
console.log(` • Or describe the work and the agent writes the .loop for you.`);
|
|
67
69
|
console.log(` • Any other agent reads AGENTS.md and can do the same.\n`);
|
|
68
70
|
return;
|
|
69
71
|
}
|
|
70
72
|
|
|
71
|
-
if (["run", "parse", "
|
|
72
|
-
console.error(`\`loop ${cmd}\` runs in your agent (the /
|
|
73
|
+
if (["run", "parse", "viz", "show", "ls"].includes(cmd)) {
|
|
74
|
+
console.error(`\`loop ${cmd}\` runs in your agent (the /loopflow skill) or via the full runtime CLI: \`loop-run ${cmd}\` (install @loop-lang/runtime).\nThis package installs Loop — try \`loop init\`. See \`loop help\`.`);
|
|
73
75
|
process.exit(2);
|
|
74
76
|
}
|
|
75
77
|
|
package/src/init.mjs
CHANGED
|
@@ -11,13 +11,14 @@ const MARK_END = "<!-- loop:end -->";
|
|
|
11
11
|
/** Short pointer dropped into an agent's memory file so it knows Loop lives here. */
|
|
12
12
|
export function pointer({ skill }) {
|
|
13
13
|
const run = skill
|
|
14
|
-
? "run it — in Claude Code via the `/
|
|
14
|
+
? "run it — in Claude Code via the `/loopflow` skill (installed at `.claude/skills/loopflow`; note: it's `/loopflow`, not the built-in `/loop` scheduler), or headless with `loop run <file>`"
|
|
15
15
|
: "run it headless with `loop run <file>`";
|
|
16
16
|
return [
|
|
17
17
|
"## Loop (`.loop`)",
|
|
18
18
|
"",
|
|
19
19
|
"This repo uses **Loop** — a small natural-language DSL for self-correcting, human-gated coding workflows.",
|
|
20
|
-
"
|
|
20
|
+
"**First time you touch Loop in this repo, read [`AGENTS.md`](./AGENTS.md) end to end before authoring or running anything** — it's the full, current grammar that ships with the repo. Don't rely on prior memory of Loop; it may be stale. Read it once per session so your context is up to date.",
|
|
21
|
+
"Whenever the user wants to build, fix, automate, or ship something as a repeatable/self-correcting workflow — a bug fix, a feature, an epic, even a whole app — **default to authoring a `.loop` file** rather than doing the work ad hoc. Use the grammar in [`AGENTS.md`](./AGENTS.md), interview the user for the goal/verification/gates first, then " + run + ".",
|
|
21
22
|
"Every time you create or change a `.loop`, print its flow so the user can see the shape.",
|
|
22
23
|
].join("\n");
|
|
23
24
|
}
|
|
@@ -66,13 +67,13 @@ export async function init(targetDir, opts, assetsDir) {
|
|
|
66
67
|
const verb = await mergeMarkered(join(targetDir, "AGENTS.md"), agentsBody.trim());
|
|
67
68
|
steps.push(`${verb} AGENTS.md (the Loop language reference — any agent)`);
|
|
68
69
|
|
|
69
|
-
// 2. The Claude Code /
|
|
70
|
+
// 2. The Claude Code /loopflow skill.
|
|
70
71
|
if (withSkill) {
|
|
71
72
|
const dst = skill === "global"
|
|
72
|
-
? join(homedir(), ".claude", "skills", "
|
|
73
|
-
: join(targetDir, ".claude", "skills", "
|
|
73
|
+
? join(homedir(), ".claude", "skills", "loopflow")
|
|
74
|
+
: join(targetDir, ".claude", "skills", "loopflow");
|
|
74
75
|
const r = await copyInto(join(assetsDir, "skill"), dst, { force });
|
|
75
|
-
steps.push(`${r === "skipped" ? "skipped (exists)" : "wrote"} ${skill === "global" ? "~/.claude/skills/
|
|
76
|
+
steps.push(`${r === "skipped" ? "skipped (exists)" : "wrote"} ${skill === "global" ? "~/.claude/skills/loopflow" : ".claude/skills/loopflow"} (the /loopflow skill)`);
|
|
76
77
|
}
|
|
77
78
|
|
|
78
79
|
// 3. Opt-in per-agent memory pointers.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Runs after `npm install -g @loop-lang/loop`.
|
|
2
|
+
// On a global install, copies the /loopflow skill to ~/.claude/skills/loopflow
|
|
3
|
+
// so every Claude Code session in every project has access to /loopflow.
|
|
4
|
+
// Skips silently on local installs and when the skill already exists.
|
|
5
|
+
import { cp, mkdir, access } from "node:fs/promises";
|
|
6
|
+
import { homedir } from "node:os";
|
|
7
|
+
import { join, dirname } from "node:path";
|
|
8
|
+
import { fileURLToPath } from "node:url";
|
|
9
|
+
|
|
10
|
+
const isGlobal = process.env.npm_config_global === "true";
|
|
11
|
+
if (!isGlobal) process.exit(0);
|
|
12
|
+
|
|
13
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
const src = join(here, "..", "assets", "skill");
|
|
15
|
+
const dst = join(homedir(), ".claude", "skills", "loopflow");
|
|
16
|
+
|
|
17
|
+
const exists = (p) => access(p).then(() => true, () => false);
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
if (await exists(dst)) {
|
|
21
|
+
console.log(` loop: /loopflow skill already at ~/.claude/skills/loopflow — skipped.`);
|
|
22
|
+
console.log(` Run \`loop init --global --force\` to overwrite.`);
|
|
23
|
+
} else {
|
|
24
|
+
await mkdir(join(homedir(), ".claude", "skills"), { recursive: true });
|
|
25
|
+
await cp(src, dst, { recursive: true });
|
|
26
|
+
console.log(` loop: installed /loopflow skill → ~/.claude/skills/loopflow`);
|
|
27
|
+
console.log(` Open any Claude Code session and type /loopflow to start.`);
|
|
28
|
+
}
|
|
29
|
+
} catch (err) {
|
|
30
|
+
// Non-fatal — don't break the install.
|
|
31
|
+
console.warn(` loop: could not install /loopflow skill: ${err.message}`);
|
|
32
|
+
console.warn(` Run \`loop init --global\` manually to install it.`);
|
|
33
|
+
}
|