From pair-loop
Drives an iterative implement→review→fix loop using pair-review councils to review code, triage findings, apply fixes, and repeat until no blockers remain.
How this skill is triggered — by the user, by Claude, or both
Slash command
/pair-loop:loopThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
You are a thin orchestrator. pair-review does the heavy lifting — multi-level,
You are a thin orchestrator. pair-review does the heavy lifting — multi-level, multi-model council reviews with persistence and a web UI. Your job is judgment: what to send for review, how to triage what comes back, what to fix, when to ask the user, and when to stop.
Reviews run through one execution mode: the headless CLI. It is synchronous (no polling), emits JSON, and needs no server. The HTTP API is used for exactly one optional thing: writing triage back so a running web UI shows reality (see Write triage back).
Any text in the user's request beyond the named arguments is the objective — what to build or change. If there is no objective, the loop runs over the changes already in the working tree.
These are not judgment calls:
maxRounds, say so, list the outstanding findings, and (when a server is
up) link the review URL.untracked — which the default scope (unstaged..untracked) does — so
no git add -N (intent-to-add) is needed."ok": false, non-zero
exit) is reported as what it is — never papered over as "no findings".git rev-parse --show-toplevel → REPO_ROOT. All commands run from here.REPO_ROOT/.pair-loop/round-log.md (mkdir -p; add
.pair-loop/ to .gitignore if missing). Record: objective, arguments,
start time. Append to this file after every phase — it is your resume
state if the session compacts.council argument was given, confirm the handle exists:
pair-review --list-councils prints the saved councils. If pair-review
is not on PATH, use npx -y @in-the-loop-labs/pair-review for every CLI
call. An unknown handle → show the available names and ask the user.git status --short that changes exist
before the first review round; if none, tell the user and stop.pair-review --local --headless --json --council <handle> [--scope <range>] --instructions "<round instructions>"
REPO_ROOT. --local with no path uses the current directory.--council to use the repo's default council.--scope). By default a local review covers only uncommitted
working-tree changes plus new files (unstaged..untracked). That is right
only while all the work under review stays uncommitted. If the work under
review already spans commits on a branch, a clean working tree would review as
empty — pass
--scope branch..untracked so every round covers the whole branch
(everything since the base branch) plus the working tree and new files. Add
--base <branch> when the base branch is not auto-detected (a non-default
trunk, or a stacked branch). --scope/--base are local-mode only.{"ok": true, "mode": "local", "run": {...}, "suggestions": [...], "count": N} — exit code 0. Zero suggestions is still
success. Record run.id (the runId) and run.review_id (the
reviewId, used for write-back and the review URL).{"ok": false, "error": {"message": ...}}, exit code 1.Build --instructions per round from, in order: this standing line —
"Do not report praise findings; report only issues." — then the user's
instructions argument, the objective, and this round's directive (see
Convergence judgment). On rounds after the first, add: "Earlier review
rounds already reported issues that have since been fixed or dismissed;
report only issues present in the current code."
Each entry in suggestions: id, file, line_start, line_end, type
(bug|improvement|suggestion|design|performance|security|code-style —
praise is instructed away; ignore it if it appears anyway), severity
(critical|medium|minor), title, body, reasoning, ai_confidence
(0–1).
For each finding, decide one of:
Dedup against your round log: a finding you already dismissed in an earlier round, reappearing unchanged, keeps its dismissal (re-dismiss it in write-back) — unless a fix touched that code since, in which case judge it fresh.
Apply the fixes (directly or via a Task agent for large batches — your call). Run the project's relevant tests for the changed code. A fix that breaks tests is not a fix.
If the pair-review server is running, keep its UI truthful. Probe once per
loop: curl -s http://localhost:7247/health → it is pair-review iff the
response has "service": "pair-review". (7247 is the default and is right
most of the time; if it isn't pair-review, check port in
REPO_ROOT/.pair-review/config.json then ~/.pair-review/config.json, then
give up on write-back for this loop.)
When the server is up, after fixing/dismissing, for each handled finding:
curl -s -X POST http://localhost:<port>/api/reviews/<run.review_id>/suggestions/<id>/status \
-H 'Content-Type: application/json' -d '{"status": "dismissed"}'
"dismissed" and "active" are accepted; "adopted" is reserved
for the human's adopt flow — never send it.reason field on this endpoint — include it:
"Fixed in loop round <n>: ..." or "Dismissed: <why>". Older servers
(still in the wild) ignore it; if you need to confirm support, check that
http://localhost:<port>/api.md?reviewId=<reviewId> documents reason.
When unsupported, the fixed-vs-rejected distinction lives in your round log
and final report.GET /api/reviews/<reviewId>/suggestions and skip findings whose status
is no longer active — the human got there first. Do not resurrect
anything the human dismissed.http://localhost:<port>/local/<reviewId>; PR runs live at
http://localhost:<port>/pr/<owner>/<repo>/<number> (the PR you passed).
Use the one matching the current run — do not hard-code the /local/ form
for a PR loop.
When a compatible pair-review server is already running (same version, same
database) on <port>, a --headless round delegates execution to it, so
that open UI shows the council dialog updating live as the round runs —
point the human there. The liveness gap remains only with no server, with
--no-server, or with an incompatible (version/database-mismatched) server;
in those cases results appear on refresh once the round finishes.No server → skip this entirely; triage lives in the round log and final report, and the persisted run history is visible whenever the user next starts the server.
You decide each round's directive and whether to continue. Principles:
critical finding.summary for the
reviewer's own answer to the ready-to-merge question and quote it in your
report.The loop also works against a GitHub PR:
pair-review <pr-number-or-url> --headless --json [--council <handle>] [--instructions "..."]
This self-bootstraps the PR (fetches metadata, prepares a review worktree)
and requires a GitHub token in ~/.pair-review/config.json. The review's
checkout lives in a pair-review worktree — your fixes belong in whatever
checkout the user asked you to work in; do not edit the pool worktree.
Write-back and the review URL work the same way via run.review_id.
--scope/--base do not apply here — they are local-mode only; a PR review
always covers the PR's full diff.
Every loop ends with a report containing:
npx claudepluginhub in-the-loop-labs/pair-review --plugin pair-loopRuns cross-LLM iterative code reviews with Codex or Gemini CLI peers, applying accepted fixes until consensus on improved code and report.
Iterative code review: runs multiple rounds of deep review, fixes safe findings inline, plans big fixes via /big-plan, defers human decisions. Use for autonomous review-fix cycles before finalizing code.
Runs iterative code review-fix loops with fresh codex reviewers until LGTM, focusing on correctness, logic, and design for pre-merge validation.