# Loop

> Use when autonomously implementing a spec task-by-task. Each loop iteration picks one task, TDDs it, commits, exits. Progress persists in git. Triggers: loop, AFK mode, autonomous loop.

- Skill: `neumie/loop` (Agent Skill, multi-file: 8 files)
- Install (CLI): `npx skillmds@latest add neumie/loop`
- Raw SKILL.md: https://api.skillmd.com/api/skills/neumie/loop/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Productivity
- Author: neumie (https://skillmd.com/u/neumie)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/neumie/loop

---


# Implementation Loop

Autonomous implementation loop. Each iteration gets fresh context, picks one task from the spec, implements it, runs feedback loops, commits, and exits. Progress lives in git history, not conversation memory.

## Setup

These commands run automatically when the skill loads — output replaces each line below:

- Available specs: !`for d in docs/plans/*/; do { [ -f "$d/spec.md" ] || [ -f "$d/prd.md" ]; } && basename "$d"; done 2>/dev/null || true`
- Project files: !`ls package.json Makefile Cargo.toml go.mod pyproject.toml setup.py 2>/dev/null || true`
- Tests directory: !`ls tests/ 2>/dev/null || true`

### 1. Select a spec

From the spec list:

- If the user passed a name (e.g. `/loop auth-system`), use `docs/plans/auth-system/spec.md` (fall back to `prd.md` when `spec.md` is missing — legacy plan dirs)
- If there's exactly one spec, use it
- If there are multiple, ask the user which one to use
- If there are none, tell the user to run `/spec-create` first

Store the selected spec path as `SPEC_FILE` for use in the prompt template.

### 2. Detect feedback loops

Map the detected project files to feedback commands:

- `package.json` → `npm run test`, `npm run typecheck`, `npm run lint`
- `Makefile` → `make test`, `make check`
- `Cargo.toml` → `cargo test`, `cargo check`
- `go.mod` → `go test ./...`, `go vet ./...`
- `pyproject.toml` / `setup.py` → `pytest`, `mypy`
- `tests/` directory in this repo → `bash tests/test-skills.sh`, `bash tests/test-structure.sh`

Build the feedback loop commands list from what's actually available.

### 3. Create the plans directory

```bash
mkdir -p docs/plans/<name>
```

### 4. Generate the prompt

Prefer the prompt generator script because it uses the shared loop engine's
feedback detector:

```bash
bash skills/loop/loop/scripts/prompt.sh <name>
```

If running from an installed skill path, resolve `{{SKILL_SCRIPTS}}` as in
step 5 and run `bash {{SKILL_SCRIPTS}}/prompt.sh <name>`.

The script writes `docs/plans/<name>/prompt.md`, sources `lib/feedback.sh`,
and renders feedback commands from `almanac_loop_feedback_markdown()`.
Use the template below only as a fallback when the script is unavailable.

Write `docs/plans/<name>/prompt.md` (e.g. `docs/plans/auth-system/prompt.md`) using the template below, filling in the detected feedback loops and the spec path:

```markdown
# INPUTS

Pull @{{SPEC_FILE}} into your context.

You've been passed the last 10 LOOP commits (SHA, date, full message). Review these to understand what work has been done.

# TASK QUEUE

Before decomposing the spec, check whether an explicit queue exists. Detect in this order:

1. **Local ticket files.** If `docs/plans/<name>/issues/` contains `*.md` files, that directory is your queue. New tickets use `status: ready-for-agent|ready-for-human`; legacy tickets use `status: open` plus `type: AFK|HITL`.
2. **GitHub issues.** Else if `gh issue list --search 'label:"loop(<name>)" state:open'` returns at least one issue, that's your queue. (Use `--search`, not `--label` — the parenthesised label name breaks the `--label` filter.) New agent tickets also carry `ready-for-agent`; legacy tickets may have no readiness label.
3. **No queue.** Skip to TASK BREAKDOWN below and decompose the spec yourself.

If a queue is present:

- Pick the **lowest-numbered** agent-ready local ticket (or **oldest** agent-ready GitHub issue) whose blockers are all done or closed. Treat legacy `status: open` + `type: AFK` files and legacy GitHub queue issues without any readiness label as agent-ready. Never pick `ready-for-human` or legacy `type: HITL`.
- Its `## What to build` and `## Acceptance criteria` define your scope. The spec is reference; the slice/issue is authoritative.
- Do NOT decompose the spec again — TASK BREAKDOWN below is for the no-queue case only.
- If every queued task is blocked by something incomplete, output `<promise>ABORT</promise>`.

# TASK BREAKDOWN

(Run this section ONLY if TASK QUEUE found no queue. Otherwise the slice/issue you picked IS your task; skip ahead to EXPLORATION.)

Break down the spec into tasks.

Pick the smallest unit of work that pins one meaningful behavior. Don't outrun your headlights — but don't underrun them either.

- **Behavior changes** (new features, schema, business logic): one task = one behavior, written test-first.
- **Mechanical refactors** (renames, threading a parameter through callers, search-and-replace across many files): the whole refactor is ONE task. Batch all related edits across all affected files into a single commit. The existing test suite is the verification — don't split a rename into one commit per call site.

If you can't articulate a behavior the task pins, you're mid-refactor — bundle it.

# TASK SELECTION

If TASK QUEUE found a task, that's your task. Otherwise pick the next task from your TASK BREAKDOWN that hasn't been completed (check LOOP commits for completed work).

If all tasks are complete, output <promise>COMPLETE</promise>.

# EXPLORATION

Explore the repo and fill your context window with relevant information that will allow you to complete the task.

# EXECUTION

Follow the `implement` skill for this one selected task: verify readiness and blockers, implement at the agreed seam, run feedback loops, review the diff, and update queue state. The selected task is already resolved — do not choose another ticket.

# FEEDBACK LOOPS

Before committing, run ALL feedback loops. Fix any failures before proceeding.

{{FEEDBACK_COMMANDS}}

# COMMIT

Follow the `implement` skill's strict checkbox and queue-update protocol. Then make the git commit. The commit message must:

1. Start with `LOOP(<name>):` prefix (e.g. `LOOP(auth-system):`)
2. Include task completed + spec reference
3. Key decisions made
4. Files changed
5. Blockers or notes for next iteration

Keep it concise but informative for the next iteration.

# REPORT

After committing, append a self-report to `docs/plans/<name>/agent-reports.log`. The overseer reads recent reports each tick and may emit steering directives based on what you flag. Be honest — concerns and uncertainties are more useful than reassurance.

Append exactly this block (replace `<HEAD-sha>` with the SHA of the commit you just made, e.g. `git rev-parse HEAD`):

```
===== sha=<HEAD-sha> ts=<ISO-8601-timestamp> =====
## concerns
- <anything about the code, tests, or approach that feels off; or "(none)">
## errors
- <runtime errors, test failures, lint issues, or retries you hit; or "(none)">
## uncertainties
- <spec ambiguities, missing context, or assumptions you made and want validated; or "(none)">
```

If the iteration was a CI fix or a steered iteration, mention that in concerns so the overseer has context.

# FINAL RULES

ONLY WORK ON A SINGLE TASK.
```

Replace `{{FEEDBACK_COMMANDS}}` with the detected commands as a markdown list
matching `almanac_loop_feedback_markdown()`, e.g.:
```markdown
- `npm run test` to run the tests
- `npm run typecheck` to run the type checker
```

### 5. Tell the user how to run it

Print:

```
Loop ready for <name>.

  Interactive CLI:
    almanac loop
    # or: bash {{SKILL_SCRIPTS}}/loop.sh

  Single iteration (HITL):
    bash {{SKILL_SCRIPTS}}/once.sh <name>

  Autonomous (AFK):
    bash {{SKILL_SCRIPTS}}/afk.sh <name> <iterations>

  Example — run 10 iterations:
    bash {{SKILL_SCRIPTS}}/afk.sh auth-system 10
```

Where `{{SKILL_SCRIPTS}}` is the absolute path to this skill's scripts. Resolve in this order:

1. `~/.agents/skills/almanac/loop/scripts` — set by `almanac install codex` or `almanac install pi`; use this in Codex or Pi.
2. `~/.claude/skills/almanac/loop/scripts` — set by `almanac install claude-code`; use this in Claude Code.
3. `$ALMANAC_HOME/skills/loop/loop/scripts` — fallback when invoked outside an installed provider.

Print the literal provider install path in user-facing instructions (`~/.agents/...` for Codex/Pi, `~/.claude/...` for Claude Code) so users can run the scripts directly.

## Modes

### AFK Mode (`afk.sh`)

Fully autonomous. Runs N iterations, each in a fresh agent context. Stops when:
- All tasks complete (`<promise>COMPLETE</promise>`)
- A task is blocked (`<promise>ABORT</promise>`)
- Iteration limit reached
- `.loop-stop` file exists in the working directory (graceful stop — see below)
- Overseer detects HIGH drift (writes `.loop-stop` automatically — see Overseer below)

**Provider selection:** set `LOOP_PROVIDER=codex` or `LOOP_PROVIDER=claude` to force an agent. If unset, the scripts use Codex when running inside Codex, otherwise Claude Code when available, otherwise Codex.

**Model override:** set `LOOP_MODEL` (e.g. `LOOP_PROVIDER=codex LOOP_MODEL=gpt-5.5 bash afk.sh <name> 10` or `LOOP_MODEL=claude-opus-4-7 bash afk.sh <name> 10`); unset uses the selected provider's default.

**Thinking override:** set `LOOP_EFFORT` to control model thinking level. Codex receives this as `model_reasoning_effort`; Claude Code receives it as `--effort`. Supported common values: `low`, `medium`, `high`, `xhigh`; Claude Code also supports `max`.

**Codex output:** Codex raw session output is quiet by default and written to `docs/plans/<name>/loop-codex-*.log`; the terminal shows concise agent progress messages, the final assistant message, and the log path. Set `LOOP_CODEX_VERBOSE=1` to stream Codex's full session output.

**Interactive launcher:** run `almanac loop` (or `loop.sh` directly) to select spec, mode, provider, model, thinking level, iteration count, and overseer behavior from prompts. It delegates to `once.sh` or `afk.sh` with the corresponding `LOOP_PROVIDER`, `LOOP_MODEL`, `LOOP_EFFORT`, and `LOOP_NO_OVERSEE` environment values.

**Auto-push:** the overseer pushes any unpushed LOOP commits to `origin` at the start of each tick (default 15 min, configurable via `LOOP_OVERSEE_INTERVAL`). This batches commits so CI runs at overseer cadence rather than per-iteration — avoids clogging CI when iterations are minutes apart. End-of-loop also pushes as a safety net. Sets upstream automatically on first push and repairs mismatched upstreams such as `origin/main`.

**Overseer:** a parallel process wakes every `LOOP_OVERSEE_INTERVAL` seconds (default 900 = 15 min) and runs a sequential tick:

1. **Push** (shell). Pushes any local commits ahead of upstream. Logs to `docs/plans/<name>/overseer.log`.

2. **Wait for CI** (shell, only if step 1 actually pushed). Polls `gh run list` every `LOOP_CI_POLL_INTERVAL` seconds (default 30) for the run matching the pushed `headSha`, blocking until status leaves `in_progress|queued|waiting|requested|pending`. Times out after `LOOP_CI_WAIT_TIMEOUT` seconds (default 1800 = 30 min). Exits early on `.loop-stop`. While the overseer waits, main-loop iterations keep running — only the overseer thread is blocked.

3. **CI verdict** (shell, no Claude call). Reads `gh run list --limit 1`. On `conclusion=failure|cancelled|timed_out|action_required|startup_failure`, writes `.loop-ci-failed` (run URL, ID, workflow name, branch, timestamp). On `conclusion=success`, clears the marker. Also runs once at script start to pick up pre-existing failures from prior sessions or manual pushes.

4. **Drift review** (selected agent call). Reviews recent `LOOP(<name>)` commits, **the tail of `docs/plans/<name>/agent-reports.log`** (last ~8KB of agent self-reports — concerns, errors, uncertainties), **and any task queue** (slice files in `docs/plans/<name>/issues/` or open GitHub issues with the `loop(<name>)` label) against the spec. Detects:

   - Repeated tasks, off-spec work, ABORT loops, vague commits, scope creep, test rot, recurring concerns the agents aren't solving on their own.
   - **Queue overclaim** — checkboxes flipped to `[x]` (or `status: done` set, or issues closed) without the corresponding code in those commits. For each recently-flipped checkbox, the overseer reads the slice/issue criterion and the commits that flipped it, and judges whether the diff actually fulfills the criterion. If not, the steer directs the next iteration to roll back the checkbox / status / issue closure.
   - **Queue staleness** — criteria clearly fulfilled by recent commits but checkbox still `[ ]`.

   Outputs `DRIFT_LEVEL: low|medium|high`, `REASON: …`, `STEER: …`. On HIGH drift writes `.loop-stop`. When `STEER` is non-`none`, writes the directive to `.loop-steer`.

Effective drift-review cadence is `LOOP_OVERSEE_INTERVAL + (CI duration if pushed)`. Steps 2-3 silently no-op if `gh` is missing, the repo has no remote, or no run materialized for the pushed SHA.

Disable the whole overseer with `LOOP_NO_OVERSEE=1` — that also disables overseer-cadence push, CI wait, CI monitoring, and steer; only the end-of-loop push remains.

**Iteration prompt prefixes:** at the start of each iteration, `afk.sh` may prepend up to two directives to the iteration prompt:

- **Fix-CI** — when `.loop-ci-failed` exists. The spawned agent is told to skip new task work, read the marker, fetch logs via `gh run view`, repair, and commit with `LOOP(<name>): fix CI — …`. Persistent: cleared automatically by the next overseer tick once CI is green again.
- **Overseer steer** — when `.loop-steer` exists. The spawned agent is told the overseer reviewed recent reports + commits and emitted concrete advice (wrong assumption, scope correction, alternate approach, etc.). One-shot: `afk.sh` removes the file after consumption. The overseer can re-emit it next tick if the underlying issue persists.

Both can stack — a steered fix-CI iteration is valid.

**Agent self-reports:** the iteration prompt template instructs the spawned agent to append a structured block to `docs/plans/<name>/agent-reports.log` after committing — `concerns`, `errors`, `uncertainties` per iteration. This is the primary signal the overseer uses to decide whether to issue a steer beyond what the commits alone reveal. Agents are told to be honest — flagged uncertainties are more useful than reassurance.

### HITL Mode (`once.sh`)

Single iteration with human in the loop. Runs one pass — you review the result before continuing. Good for:
- First iteration (sanity check)
- After an ABORT (diagnose and unblock)
- When you want to steer

## Monitoring

While AFK mode runs, you can watch progress:

```bash
git log --grep="LOOP(auth-system)" --oneline
```

Each `LOOP(<name>):` commit message contains what was done and notes for the next iteration. The name prefix means multiple specs can run against the same repo without confusing each other's progress.

## When to stop

- All tasks done → loop exits with "Loop complete" + auto-push.
- Something's wrong → loop exits with "Loop aborted" + auto-push.
- Graceful stop mid-run → `touch .loop-stop` in the working directory. The loop exits at the start of the next iteration, pushes commits, removes the file. Use this instead of Ctrl+C — Ctrl+C skips the auto-push and may leave LOOP commits stranded locally.
- You see bad commits → Ctrl+C, review, and `git push` manually if you want to keep them.
- Context is confused → kill it, fix the issue, restart (fresh context = fresh start).

