Loops

A loop holds one piece of work to a written brief: partyline runs your checks on it, has other models review it, and sends it back until the checks pass and no reviewer has an open P1.

$ ptln loop start --brief brief.md --checks "make test"

A session runs that command, not you. Tell a Claude, Codex or Gemini session running in partyline "use a partyline loop for this"; its session context points it to ptln loop guide, which prints the workflow, the brief template and the report template.

ptln help lists ptln loop under Loops; ptln loop --help prints its usage. Start with ptln loop guide.

Loop or batch

Built byStarted with
Loop (a single run)the session that started itptln loop start --brief <file> --checks "<cmd>"
Batch (two or more ordered steps)builders partyline starts, one step after another on one branchptln loop batch start --brief <step1> --brief <step2> --checks "<cmd>"

Repeat --checks for each command. A check containing a newline or other control character is refused; give each command as its own --checks.

Single runs can be started from Claude and Codex sessions. Gemini sessions can start batches but not single runs, because partyline cannot recognise Gemini's idle input box.

The brief

A brief is Markdown, titled # <title>, with these sections. Each is required and must not be empty.

SectionHolds
## Goalwhat the user will be able to do, in their terms
## Decisionswhat was decided, each with its reason
## Constraintswhat must not change; interfaces others depend on
## Out of scopewhat this run will not do
## Acceptanceone line each: run: <command> must exit 0, file: <path> must exist
## Verificationfor each acceptance item, the check that proves it
## Unknownsopen questions, not assumptions; "None" if there are none

A brief with a missing section, no run: or file: line under Acceptance, or control characters other than newline and tab is refused. A brief can be revised three times before it is approved; after that the loop fails.

Where a loop can run

RuleWhat happens otherwise
Start it inside the git repositorynot in a git repository
One loop per repository, counting its worktreesloop <id> is already running in this repository … one per repository, including its worktrees
Start it from a Claude, Codex or Gemini session running in partylinerefused: the process has no session identity

Loops in different repositories run in parallel.

Rounds

  1. Approval. The brief and checks wait for approval (below). A batch first goes to the reviewers, who read its briefs as a set; a batch with open P1s goes back to its session to revise.
  2. Baseline. Partyline runs the checks before any work, so checks that already fail do not count against the loop.
  3. Build. The session (or, in a batch, a builder) does the work, writes a report and runs ptln loop ready <id> --report <file>.
  4. Checks. Partyline runs the checks and the brief's acceptance lines. A check that newly fails, or any acceptance line that fails, sends the work back without a review.
  5. Review. Each reviewer reads the brief, the report and the diff, read-only, and returns findings. A finding whose quoted code is not in the file it names is dropped.
  6. Result. Any P1 sends the work back to step 3. No new failure and no open P1 ends the loop.

The report needs these sections: Evidence, Hardest decision, Rejected alternatives, Least confident, What an excellent reviewer would criticise.

PriorityMeaningBlocks the loop
P1must be fixed before merge: wrong behaviour, data loss, a security hole, a broken build or testyes
P2should be fixed: a real defect with limited impact, a missing test for real behaviourno
P3worth doing: clarity, small simplificationsno

P2 and P3 findings are passed on with the result, for the PR description.

A loop has six rounds; each ready uses one, whether the checks or the review sent it back. A loop that uses all six, or submits work identical to the previous round's, fails, and you decide what happens next.

A review that is missing a reviewer pauses instead of passing. A reviewer that hit a usage limit resumes by itself after the limit resets; ptln loop resume <id> runs a paused review again. Checks that cannot run (for example a blocked .envrc) also pause the loop rather than counting as a failure.

Disputes

The session disputes a P1 it believes is wrong:

ptln loop dispute <id> <finding> --reason "<evidence>"

A session never rules on its own dispute. Who rules depends on the Decisions setting:

DecisionsSingle runBatch step
loops decide (default)a model that did not build the work rules at once: the arbiter if one is set, else reviewer 1deferred to the end of the batch, then ruled the same way; the step carries on
ask me, disputes: ask meyou rule in the approval popupdeferred to your review at the end of the batch; the step carries on
ask me, disputes: let an AI decideyou rule in the approval popupthe arbiter rules; below 0.8 confidence, or with no valid answer, it is deferred to you

When a loop decides for itself, the model reads the work read-only with the session's reason. Its ruling stands whatever its confidence. If it gives no valid answer, the finding stands and the work is fixed.

A P1 that was dismissed or deferred is not raised again in later rounds.

Jev

Jev (typesafe.ai) gives an outside estimate of whether a disputed finding is right. It is optional and advisory: it does not read the code, and the model ruling on the dispute is told to weigh its estimate and decide from the code.

With no key saved there is no Jev. With a key, when a loop decides a dispute, partyline sends Jev the brief (up to 6,000 characters), the finding and the session's reason, and passes the returned probability to the ruling model. Jev is skipped on any error: no credits, a revoked key, a rate limit, a 15-second timeout. The dispute goes on without it. Jev is used only when loops decide; with "ask me" it is not called.

Decisions

Loops decide by default: nothing waits for you. A brief or batch waiting for approval is approved, and disputes are ruled as above.

Switch Decisions to "ask me" in the loop settings to bring approvals back. Then ‼ on a tab and "N to approve" on the status bar show when something waits; ctrl-\ a opens the approval popup, where approving asks you to type the four-digit code it shows. A session must never approve or operate that popup.

Loop settings

ctrl-\ , opens the loop settings; , in the Loops popup does the same. Every change is saved at once to ~/.partyline/settings.json, or refused with the reason.

RowChoice
Builderthe engine, model and effort that build batch steps; b adds a backup, x removes one
Reviewer 1, 2, …engine, model and effort for each reviewer; b adds a backup; + Add a reviewer adds a slot
Failoveron: switch to the next backup at a usage limit. Off: the review records the limit and fails
Qualitythe standard every prompt carries: built in, or the full path of a plain-text file under 64 KB
Decisionsloops decide (default), or ask me
Disputeswith ask me only: ask me, or let an AI decide
Arbiterengine, model and effort of the model that rules on disputes; with loops decide, reviewer 1 when unset
Jev keyoptional; ⏎ pastes a key, x removes it

Builders, reviewers and the arbiter are Claude or Codex. Claude offers Fable, Opus, Sonnet and Haiku with efforts low to max; Codex offers the models in its own ~/.codex/models_cache.json.

No loop runs until you have chosen a builder and at least one reviewer (and the arbiter, when disputes go to it), each with a model and an effort: partyline does not choose them for you, because both affect token use. A loop started before then is saved, the settings open on your screen, and the loop carries on once they are chosen.

A new batch copies the settings, including the quality standard's text, so a later change does not change a batch already approved. Decisions is the exception: it is read each time a decision is due, so changing it applies to loops already running. --config <file> or --review claude,codex overrides them for one loop or batch. A config file is JSON:

{"builder": ["claude:opus:high", "codex:gpt-5:medium"], "reviewers": [["codex:gpt-5:high", "claude:sonnet:high"], ["claude:opus:max"]], "failover": true}

Each reviewer slot reviews once, trying its models in order when one hits a usage, rate or capacity limit. A limited model is skipped until its reset, or for 12 hours when no reset is given; limits are kept in ~/.partyline/limits.json.

The Jev key is kept in ~/.partyline/jev-key, readable only by you.

Batches

A batch runs on the branch checked out when it is approved; with no branch checked out (a detached HEAD), approval is refused. Each step is built by a builder partyline starts (a contractor, listed on the Loops popup's Contractors tab), then checked and reviewed like a single run. Partyline commits each step that passes, authored as <engine> <model> via partyline and leaving memory/ as it was at HEAD, and starts the next. When the last step passes, any deferred findings are put to you.

ptln loop batch status <id> summarises a batch: each step's state and rounds, its commit range, its report, and which model reviewed each round.

What partyline does to your repository

Partyline commits batch steps that pass, in the batch's own checkout. It never pushes, merges or opens a pull request. For a single run, the session is told to commit and open the PR itself, and to record it with ptln loop pr <id> <url> so the Loops board shows it and its CI.

Builders

A builder runs with your own setup: your engine configuration, your CLAUDE.md or AGENTS.md files, your tools, MCP servers and credentials. Two things are blocked:

GuardHow
cannot push, merge or open a pull requestgit push is rewritten to an address git cannot open; gh runs with no account; GitHub tokens are removed from its environment
cannot change ~/.partyline, where approvals and rulings liveClaude builders: permission deny rules and the Bash sandbox block reading and writing it. Codex builders: the workspace-write sandbox limits writes to the checkout and temp

Reviewers and the arbiter read a snapshot of the work read-only: Claude with only Read, Glob and Grep and no MCP servers, Codex in its read-only sandbox without your config or the repository's AGENTS.md.

The Loops board

ctrl-\ l opens the Loops popup; ptln loop tab shows the same board full-screen. The board has five columns, in the order work moves:

ColumnHolds
Needs youa brief waiting for approval, or a disputed finding waiting for a ruling. When loops decide, cards pass through here while the decision is made
Plannedbatch steps not started yet
In progressbuilding, or revising the brief
In reviewbaseline checks, a round's checks and reviews, a batch's review, or paused
Donefinished, failed or stopped; listed for seven days
KeyAction
← → · ↑ ↓ (or h l · j k)move between columns · cards
⏎open a card's details: who is working on it and their last action, its token use, its rounds and findings; on a building or reviewing card, select its contractor
aapprove a card that needs you
sstop the selected run, after confirmation
ddelete the card's loop, or its whole batch; press d again to confirm
rcycle the repository filter: all repositories, then each in turn
,loop settings
tabswitch between Board and Contractors
esc · qclose

Delete a loop

$ ptln loop delete <id>

Stops the loop if it is still running, stops its builder, reviewers and arbiter, and removes its records for good: it leaves the board and cannot be resumed. A batch step, or a batch id, deletes the whole batch. The command does not ask for confirmation; d on a card does.

Commands

CommandDoes what
ptln loop guidethe workflow for the calling session's engine
ptln loop start --brief <file> --checks "<cmd>"start a single run (run by the session)
ptln loop batch start --brief <file> --brief <file> ... --checks "<cmd>"start a batch, with one approval for every step (run by the session)
ptln loop ready <id> --report <file>the work is done; partyline checks and reviews it
ptln loop dispute <id> <finding> --reason "..."dispute a P1
ptln loop brief <id> --file <file>revise a single run's brief
ptln loop batch revise <id> --brief <file> ...revise a batch after its review or a rejection
ptln loop batch next <id> · batch status <id>start a batch's next step · summarise the batch
ptln loop listen <id> · inbox <id>wait for results (a Claude background task) · print the state and waiting messages
ptln loop status [<id>]every loop, or one
ptln loop resume <id>run a paused review again
ptln loop pr <id> <url-or-number>record the PR the session opened
ptln loop delete <id>stop and remove a loop or its batch
ptln loop tab [--contractor <id>]the Loops board full-screen
ptln loop review [--by claude,codex] [--base <ref>]a one-off review of the working tree against <ref>, with no loop

A card's details total the tokens each model used, by role (builder, reviewer, brief reviewer, arbiter, decider): fresh tokens (input, cache writes and output) and cost, with cache reads listed apart. Codex reports no cost, so its rows show tokens only. A building card shows the builder's last command instead of the note set when it started.

Loop records live under ~/.partyline/loops/, outside the repository, so the session being reviewed cannot edit them.