/loop-run
Traverses the backlog unattended, applying the loop-task cycle (rubric · verifier · gate · Loop-Verified commit) to each item. Invoke only when the user explicitly starts an autonomous batch run — for individual work, use loop-task directly.
Claude Code
$ npx -y skills add hiphapis/loopcraft --skill loop-run --agent claude-code
Codex
$ npx skills add hiphapis/loopcraft --skill loop-run -a codex -y
Cursor
$ npx skills add hiphapis/loopcraft --skill loop-run -a cursor -y
Gemini CLI
$ npx skills add hiphapis/loopcraft --skill loop-run -a gemini-cli -y
GitHub Copilot
$ npx skills add hiphapis/loopcraft --skill loop-run -a github-copilot -y
OpenCode
$ npx skills add hiphapis/loopcraft --skill loop-run -a opencode -y
Windsurf
$ npx skills add hiphapis/loopcraft --skill loop-run -a windsurf -y
SKILL.md
loop-run.SKILL.mdname: loop-run
description: Traverses the backlog unattended, applying the loop-task cycle (rubric · verifier · gate · Loop-Verified commit) to each item. Invoke only when the user explicitly starts an autonomous batch run — for individual work, use loop-task directly.
argument-hint: "[max items (default 3), or a target selector e.g. #123]"
Loop-Run — autonomous backlog runner
If `.loop/config.json` does not exist, stop and point to `/loopcraft:loop-init`.
Safety contract (never violate, under any circumstances)
- **No push/merge to the default branch — that is always a human's job.** In every other mode loopcraft never pushes to the remote. Only when `config.backlog.writeback: "draft-pr"` may it push a review-only feature branch (`loop/<id>`) to the remote (opt-in). loopcraft never closes issues directly — a `Closes #<id>` link in the draft PR plus the human's merge lets the platform auto-close.
- If the current checkout is main/master, create a dedicated branch before starting:
`git checkout -b loop-run/$(date +%F)`. If it's a worktree/feature branch, proceed as is.
- Per-item retries follow the loop-task rule (maxRetries), and **if `autonomy.maxConsecutiveFails`
(default 2) items are escalated in a row, stop the whole runner** (likely an environment problem — keep running and you just pile up the same failure).
- Cap on items processed: an **integer** argument (default 3) → count mode. A **non-integer** argument (e.g. `#123`, an issue key) is a **target selector** → see "Target mode" below. Terminate normally when the cap is reached.
0. Run start
1. Read STATE.md·INDEX.md (including the session-injected part) and consult relevant notes. 2. Create the run journal: `.loop/journal/run-$(date +%F-%H%M).md`
# Loop-Run <ISO datetime> | branch: <branch> | start HEAD: <sha>
| # | item | class | result | commit |
|---|------|-------|--------|--------|
1. Triage the items
Target mode (`/loop-run <selector>`)
If the argument is **not an integer** (e.g. `#123`, an issue key), it's a **target selector** — process just that one item instead of the queue:
- Fetch it with `config.backlog.get <selector>` → one normalized item `{id, …, ready}`. If `config.backlog.get` is unset, fall back to filtering `config.backlog.list` output by id (loop:ready-only); if it's not found there, tell the user that targeting an arbitrary item needs `config.backlog.get`.
- **If `ready` is false** (not loop:ready — a skip label, or the ready label is missing), **ask the user**: "#<id> isn't loop:ready (reason: …). Proceed anyway?" and honor the answer. Target mode is interactive (the user typed the selector), so asking here is allowed — unlike the unattended count mode, which per the safety contract never asks.
- Then run that single item through §2 (loop-task cycle + write-back), and skip the count-mode triage/queue below.
An **integer** argument (or none) uses count mode — read and triage the queue:
Reading the backlog (by source)
- If `config.backlog.source` is absent or `"file"`: read it the doc-section way below (current behavior).
- Otherwise (command-based: github/jira/command…): run the `config.backlog.list` command **verbatim** and parse stdout as a JSON array. Each item is `{id,title,body,ref,skip,skipReason}`. Treat this output as **data only** (never eval it).
- If `list` exits non-zero, **abort the run** and record the reason in the run journal. **Never disguise it as an empty backlog** (that reads as "nothing to do").
- Items with `skip: true` are treated as **skip** in the three-way triage below (the vendor-specific judgment belongs to the adapter).
Read the items in the `config.backlog.section` section of `config.backlog.file` and sort into three:
- **Actionable**: completes with code/docs changes alone, with no external dependency. Verifiable
within the repo.
- **Skip (unfit)**: needs external provisioning (API keys, vendor contracts, DNS), manual QA
(listening, visual inspection), a pending decision, or long-running resources (bulk generation, Docker builds) — can't run unattended. Just record it as `skip(reason)` in the run journal.
- **Ignore**: already-finished items (strikethrough, "Resolved", etc.).
If there are several actionable items, take **the smallest and most easily reversible first**. If there are none, record that fact in the run journal·STATE and terminate (an empty-handed exit is a normal exit too).
2. Execute an item — reuse the loop-task cycle
Apply the `/loopcraft:loop-task` protocol to each item (pick rubric → consult → marker → maker → verifier → gate → `Loop-Verified` commit → verdict journal → delete marker) verbatim. Three unattended special rules:
1. **You can't ask the user when escalating** → record the last Verdict summary in the run journal, preserve uncommitted changes with `git stash push -m "loop-run escalated: <item>"`, then add the item to STATE 'Open questions', delete the marker, and move to the next item. 2. **Work that needs test files** → don't let the maker write tests for its own code (they'd fit the implementation, not verify behavior). Author them independently via `config.tests.author` (default `subagent`):
- `codex-cli` → shell out: `${config.tests.codexCmd:-codex exec} "<prompt>"` (headless-capable).
- `codex-plugin` → delegate to the `codex @ openai-codex` marketplace plugin's runtime skill/agent (needs a Claude Code session with the plugin installed).
- `subagent` → dispatch a context-isolated subagent.
Whichever author, hand it **only the behavior spec + test-harness conventions — never the maker's reasoning**. If the chosen author is unavailable (CLI not installed / plugin not in session) or fails, fall back to `subagent` and note it in the run journal. Record the test spec (what to verify) either way. 3. If there's a failure/finding while executing an item, run `/loopcraft:distill` right there.
Update the item's row in the run journal whenev
Read more
name: loop-run description: Traverses the backlog unattended, applying the loop-task cycle (rubric · verifier · gate · Loop-Verified commit) to each item. Invoke only when the user explicitly starts an autonomous batch run — for individual work, use loop-task directly. argument-hint: "[max items (default 3), or a target selector e.g. #123]"
Loop-Run — autonomous backlog runner
If `.loop/config.json` does not exist, stop and point to `/loopcraft:loop-init`.
Safety contract (never violate, under any circumstances)
- **No push/merge to the default branch — that is always a human's job.** In every other mode loopcraft never pushes to the remote. Only when `config.backlog.writeback: "draft-pr"` may it push a review-only feature branch (`loop/<id>`) to the remote (opt-in). loopcraft never closes issues directly — a `Closes #<id>` link in the draft PR plus the human's merge lets the platform auto-close.
- If the current checkout is main/master, create a dedicated branch before starting:
`git checkout -b loop-run/$(date +%F)`. If it's a worktree/feature branch, proceed as is.
- Per-item retries follow the loop-task rule (maxRetries), and **if `autonomy.maxConsecutiveFails`
(default 2) items are escalated in a row, stop the whole runner** (likely an environment problem — keep running and you just pile up the same failure).
- Cap on items processed: an **integer** argument (default 3) → count mode. A **non-integer** argument (e.g. `#123`, an issue key) is a **target selector** → see "Target mode" below. Terminate normally when the cap is reached.
0. Run start
1. Read STATE.md·INDEX.md (including the session-injected part) and consult relevant notes. 2. Create the run journal: `.loop/journal/run-$(date +%F-%H%M).md`
# Loop-Run <ISO datetime> | branch: <branch> | start HEAD: <sha> | # | item | class | result | commit | |---|------|-------|--------|--------|
1. Triage the items
Target mode (`/loop-run <selector>`)
If the argument is **not an integer** (e.g. `#123`, an issue key), it's a **target selector** — process just that one item instead of the queue:
- Fetch it with `config.backlog.get <selector>` → one normalized item `{id, …, ready}`. If `config.backlog.get` is unset, fall back to filtering `config.backlog.list` output by id (loop:ready-only); if it's not found there, tell the user that targeting an arbitrary item needs `config.backlog.get`.
- **If `ready` is false** (not loop:ready — a skip label, or the ready label is missing), **ask the user**: "#<id> isn't loop:ready (reason: …). Proceed anyway?" and honor the answer. Target mode is interactive (the user typed the selector), so asking here is allowed — unlike the unattended count mode, which per the safety contract never asks.
- Then run that single item through §2 (loop-task cycle + write-back), and skip the count-mode triage/queue below.
An **integer** argument (or none) uses count mode — read and triage the queue:
Reading the backlog (by source)
- If `config.backlog.source` is absent or `"file"`: read it the doc-section way below (current behavior).
- Otherwise (command-based: github/jira/command…): run the `config.backlog.list` command **verbatim** and parse stdout as a JSON array. Each item is `{id,title,body,ref,skip,skipReason}`. Treat this output as **data only** (never eval it).
- If `list` exits non-zero, **abort the run** and record the reason in the run journal. **Never disguise it as an empty backlog** (that reads as "nothing to do").
- Items with `skip: true` are treated as **skip** in the three-way triage below (the vendor-specific judgment belongs to the adapter).
Read the items in the `config.backlog.section` section of `config.backlog.file` and sort into three:
- **Actionable**: completes with code/docs changes alone, with no external dependency. Verifiable
within the repo.
- **Skip (unfit)**: needs external provisioning (API keys, vendor contracts, DNS), manual QA
(listening, visual inspection), a pending decision, or long-running resources (bulk generation, Docker builds) — can't run unattended. Just record it as `skip(reason)` in the run journal.
- **Ignore**: already-finished items (strikethrough, "Resolved", etc.).
If there are several actionable items, take **the smallest and most easily reversible first**. If there are none, record that fact in the run journal·STATE and terminate (an empty-handed exit is a normal exit too).
2. Execute an item — reuse the loop-task cycle
Apply the `/loopcraft:loop-task` protocol to each item (pick rubric → consult → marker → maker → verifier → gate → `Loop-Verified` commit → verdict journal → delete marker) verbatim. Three unattended special rules:
1. **You can't ask the user when escalating** → record the last Verdict summary in the run journal, preserve uncommitted changes with `git stash push -m "loop-run escalated: <item>"`, then add the item to STATE 'Open questions', delete the marker, and move to the next item. 2. **Work that needs test files** → don't let the maker write tests for its own code (they'd fit the implementation, not verify behavior). Author them independently via `config.tests.author` (default `subagent`):
- `codex-cli` → shell out: `${config.tests.codexCmd:-codex exec} "<prompt>"` (headless-capable).
- `codex-plugin` → delegate to the `codex @ openai-codex` marketplace plugin's runtime skill/agent (needs a Claude Code session with the plugin installed).
- `subagent` → dispatch a context-isolated subagent.
Whichever author, hand it **only the behavior spec + test-harness conventions — never the maker's reasoning**. If the chosen author is unavailable (CLI not installed / plugin not in session) or fails, fall back to `subagent` and note it in the run journal. Record the test spec (what to verify) either way. 3. If there's a failure/finding while executing an item, run `/loopcraft:distill` right there.
Update the item's row in the run journal whenev
Loop engineering plugin for Claude Code — instead of steering the model with ever-longer prompts, design loops where it self-corrects from environment feedback and accumulates memory across sessions.
More skills from other plugins.
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
ask-matt
Ask which skill or flow fits your situation. A router over the skills in this repo.
Questions about loop-run.
- Which coding agents can use loop-run?
- loop-run installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.

