Files
loop-loop/skills/loop-run/SKILL.md
Sheldon Finlay 17e5eb707f feat: agent loop harness with Claude Code plugin support
Generator-evaluator architecture with iterative context-reset for
long-running coding tasks. Ships as a Claude Code plugin — install
with /plugin and use /agent-loop:init, /agent-loop:plan, /agent-loop:run.
2026-03-27 08:03:18 -04:00

6.9 KiB

name, description
name description
run Execute the generator-evaluator loop interactively inside Claude Code. Dispatches subagents with full visibility and intervention capability. Run /agent-loop:init and /agent-loop:plan first.

/run — Execute Agent Loop Inside Claude Code

Run the generator-evaluator loop natively in Claude Code using subagents. Unlike loop.sh (headless), this gives you full visibility into each agent's work and the ability to intervene at any point.

Usage

/agent-loop:run                    # Run until all stories pass or max iterations
/agent-loop:run 3                  # Run at most 3 iterations
/agent-loop:run --skip-eval        # Skip evaluator (generator marks stories done)
/agent-loop:run --story US-003     # Run only a specific story

Prerequisites

  • .loop/config.json exists (run /agent-loop:init first)
  • .loop/prd.json exists with stories (run /agent-loop:plan first)

Instructions

When the user invokes /loop-run, follow this orchestration sequence exactly.

Step 0: Parse Arguments

  • If a number is provided, use it as max iterations. Otherwise read maxIterations from .loop/config.json.
  • If --skip-eval is provided, skip the evaluator pass.
  • If --story <ID> is provided, only work on that specific story.

Step 1: Load State

  1. Read .loop/config.json — get mode, maxIterations, evalRetries, scopeBudgets
  2. Read .loop/prd.json — get the story list and their statuses
  3. Check .loop/progress.md exists; if not, create it from .loop/templates/progress.md.template

Report to the user:

Loop Ready

  • Mode: {mode}
  • Stories: {passed}/{total} complete
  • Max iterations: {N}
  • Eval: {on/off}

Starting loop. You can interrupt me at any time to adjust course.

Step 2: Iteration Loop

For each iteration (1 to max iterations):

2a. Find Next Story

Find the highest-priority story in prd.json where passes is false and blocked is not true. If --story was specified, use that story instead.

If no actionable story remains:

  • If all stories have passes: true → report success and stop
  • If some stories are blocked: true → report which are blocked and suggest /agent-loop:triage
  • Stop the loop

2b. Report Iteration Start

Tell the user:

Iteration {N}/{max} — {story.id}: {story.title}

If the story has [REJECTED] entries in its notes field, summarize the previous feedback so the user has context.

2c. Assemble Generator Prompt

Read these files and concatenate them with --- separators:

  1. .loop/prompts/generator/_base.md
  2. .loop/prompts/generator/{mode}.md

Then substitute these template variables in the assembled text:

  • {{MAX_FILES_TO_READ}} → from config.scopeBudgets.{mode}.maxFilesToRead
  • {{MAX_LINES_TO_WRITE}} → from config.scopeBudgets.{mode}.maxLinesToWrite
  • {{MAX_FILES_TO_MODIFY}} → from config.scopeBudgets.{mode}.maxFilesToModify
  • {{MODE}} → the mode
  • {{ITERATION}} → current iteration number
  • {{MAX_ITERATIONS}} → max iterations
  • {{LOOP_DIR}} → path to .loop/ directory
  • {{PROJECT_ROOT}} → project root path
  • {{CURRENT_STORY_ID}} → the story ID being worked on

2d. Capture Pre-Generator Git State

Run git rev-parse HEAD and save it. This is needed for the evaluator's diff.

2e. Dispatch Generator Agent

Use the Agent tool to launch the generator:

Agent(
  prompt: <assembled generator prompt>,
  description: "Generator: {story.id}",
  subagent_type: "general-purpose",
  mode: "auto"
)

IMPORTANT: Use mode: "auto" so the user can see tool calls but isn't prompted for every action. If the user has expressed a preference for more control, use mode: "default" instead.

Wait for the agent to complete. The Agent tool returns the generator's final output.

2f. Check for Completion Signal

If the generator output contains <promise>COMPLETE</promise>, report all stories complete and stop.

2g. Skip Evaluator (if configured)

If --skip-eval was specified or config.skipEval is true, skip to step 2j.

2h. Assemble Evaluator Prompt

Read these files and concatenate them:

  1. .loop/prompts/evaluator/_base.md
  2. .loop/prompts/evaluator/{mode}.md

Substitute the same template variables as the generator, plus:

  • {{PRE_GENERATOR_SHA}} → the git SHA captured in step 2d
  • {{CURRENT_STORY_ID}} → the story ID

2i. Dispatch Evaluator Agent

Use the Agent tool to launch the evaluator:

Agent(
  prompt: <assembled evaluator prompt>,
  description: "Evaluator: {story.id}",
  subagent_type: "general-purpose",
  mode: "auto"
)

Wait for completion. Parse the verdict from the output:

  • Look for <verdict>PASS</verdict> → story passes
  • Look for <verdict>REJECT</verdict> → story rejected; extract reason from <rejection_reason>...</rejection_reason>
  • No verdict tag found → treat as REJECT (fail-safe)

2j. Update State Based on Verdict

On PASS (or skip-eval):

  1. Update .loop/prd.json — set passes: true for the story
  2. Report to user: ✓ {story.id} PASSED

On REJECT:

  1. Update .loop/prd.json:
    • Keep passes: false
    • Increment rejections count
    • Append [REJECTED] {reason} to notes
  2. Report to user: ✗ {story.id} REJECTED — {reason}
  3. Check if rejections >= evalRetries from config:
    • If yes: set blocked: true in prd.json, append [BLOCKED] to notes
    • Report: ⚠ {story.id} BLOCKED — rejected {N} times, needs human review

2k. Append Progress Entry

Append to .loop/progress.md:

### {story.id} — {story.title}
Date: {current date and time}
Iteration: {N}
Verdict: {PASS/REJECT/SKIP-EVAL}

---

2l. Report Iteration Summary

Show current story counts: {passed}/{total} stories complete

If there are more iterations and more stories, continue to the next iteration.

Step 3: Loop Exit

When the loop ends (all stories done, max iterations, or all remaining blocked), report:

Loop Complete

  • Iterations used: {N}
  • Stories: {passed}/{total} complete, {blocked} blocked
  • {Suggest /agent-loop:triage if anything is blocked or incomplete}

Error Handling

  • If an Agent subagent fails or returns empty output, log a warning and continue to the next iteration. Do NOT stop the loop for a single agent failure.
  • If prd.json cannot be parsed, stop immediately and report the error.
  • If the user interrupts (denies a tool call, says "stop", etc.), gracefully end the loop and report current status.

Key Differences from loop.sh

Feature loop.sh /loop-run
Execution Headless (claude --print) Visible in Claude Code
Intervention Kill the process Deny tool calls, chat mid-loop
Permissions --dangerously-skip-permissions User-controlled
Context Fresh process per agent Fresh Agent subagent per agent
State updates Shell functions Claude Code reads/writes files directly