@loop-lang/loop 0.2.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/assets/AGENTS.md CHANGED
@@ -1,12 +1,12 @@
1
- # AGENTS.md — authoring Loop (`.loop`) flows
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
- **Loop** flows. When a user asks you to design a staged, self-correcting, or human-gated
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
7
  run it with `loop-run run file.loop`.
8
8
 
9
- Loop is a small natural-language DSL. A `.loop` file describes the *movement* of an AI
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
@@ -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
@@ -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
@@ -122,10 +134,23 @@ Walk these quickly, naming the keyword each time so they learn it:
122
134
  6. **Human gates** → `a human approves the plan first` / `a human reviews before stopping`
123
135
  — default none unless the work is risky.
124
136
  7. **Git** → state the safe default ("branch, commit when the goal is met, never push to
125
- `main`"); ask if they want a PR, a worktree, or to work in place.
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.
126
149
 
127
150
  Offer the defaults inline (*"I'll add a tests + security pass, gate the migration, a
128
- 6-try guard, work on a branch — sound right?"*) so the whole interview is one exchange.
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.
129
154
  Then **write the `.loop`**, always with a real `done when` and a thrash guard, **print
130
155
  its flow** (below), and offer to run it.
131
156
 
@@ -162,10 +187,19 @@ the user explicitly asks for the headless runner.)
162
187
  1. **Read the file.** (Or, if the `loop` CLI is installed: `loop parse <file> --json` to
163
188
  get the structured spec.)
164
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.
165
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.
166
197
  - **act** — make the edits. Honor the policy: for `ask me before <X>`, ask the user
167
198
  before doing X (migrations, pushes, etc.); auto classes you may do directly.
168
- - **observe** — run the `done when` command (or named test) and read pass/fail.
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.
169
203
  - on **fail** → **reflect** on why (use the failure output), then **plan again** (the
170
204
  back-edge). Repeat.
171
205
  - **stop** when `done when` passes, or after the thrash guard's N tries (state the
@@ -270,8 +304,41 @@ and honor the policy: if `push when done` is set and the current branch is `main
270
304
 
271
305
  ---
272
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
+
273
340
  ## Reference
274
341
 
275
342
  The full language reference is in `AGENTS.md` and `docs/MANUAL.md` of the loop-lang repo;
276
- the CLI (`loop run|viz|export|parse`) and the VSCode extension are alternative ways to run
343
+ the CLI (`loop-run run|viz|parse`) and the VSCode extension are alternative ways to run
277
344
  the same `.loop` files.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@loop-lang/loop",
3
- "version": "0.2.0",
4
- "description": "Install Loop (.loop) into any repo so Claude Code — or any agent — can author and run self-correcting, human-gated coding loops.",
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
- // /loopflow skill) or headless via the full @loop/runtime CLI.
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,7 +17,7 @@ usage:
17
17
 
18
18
  init options:
19
19
  --dir <path> install into <path> (default: current directory)
20
- --global install the /loopflow skill into ~/.claude/skills (not the repo)
20
+ --global install the /loopflow skill into ~/.claude/skills (done automatically on \`npm install -g\`)
21
21
  --no-skill don't install the Claude Code /loopflow skill
22
22
  --no-example don't write examples/fix_test.loop
23
23
  --no-claude-md don't write the CLAUDE.md pointer (written by default)
@@ -29,7 +29,7 @@ init options:
29
29
  after init:
30
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; }
@@ -70,8 +70,8 @@ async function main(argv) {
70
70
  return;
71
71
  }
72
72
 
73
- if (["run", "parse", "export", "viz", "show", "ls"].includes(cmd)) {
74
- console.error(`\`loop ${cmd}\` runs in your agent (the /loopflow skill) or via the full runtime CLI (@loop/runtime).\nThis package installs Loop — try \`loop init\`. See \`loop help\`.`);
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\`.`);
75
75
  process.exit(2);
76
76
  }
77
77
 
package/src/init.mjs CHANGED
@@ -17,6 +17,7 @@ export function pointer({ skill }) {
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
+ "**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.",
20
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");
@@ -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
+ }