kew loop — Loop management subcommands¶
kew loop pause¶
Request a cooperative pause of a running first-class loop.
Usage¶
Usage: kew loop pause <loop_id>
Arguments:
loop_id ID of the loop to pause (use `kew status` to list)
Example:
What it does¶
kew loop pause sets a pause_requested flag on the loop record. The running
agent checks this flag at each safe point (between iterations) and stops
cleanly when it is set. It does not interrupt the agent mid-iteration.
Key properties:
- Cooperative — the loop finishes its current iteration before stopping. Your worktree, uncommitted work, and branch are all preserved exactly as the agent left them.
- Non-destructive — no force-kill, no worktree wipe. All in-progress work survives the pause.
- Resumable — once paused, resume the loop with:
Distinct from kew stop¶
| Command | Scope | Mechanism | Effect on worktree |
|---|---|---|---|
kew loop pause |
Single loop | Cooperative flag | Preserved (agent stops at next safe point) |
kew stop |
Entire fleet | Hard kill (SIGTERM→SIGKILL) + latch | Running agents terminated, runs marked killed; dispatch blocked |
Use kew loop pause when you want to inspect or redirect a single loop.
Use kew stop when you need to halt all dispatch immediately (e.g. an incident).
If a pause request and
kew stopland in the same moment, the loop may recordpaused(the underlying run is still markedkilled). Either way the worktree is preserved and the loop can be continued withkew loop resume.
Error conditions¶
- Loop not found or not in
pursuingstate — exits with a non-zero code and a message. A loop that is alreadyneeds_human,achieved,unmet, orpausedcannot be paused again.
kew loop resume¶
Resume a paused first-class loop with operator guidance.
Usage¶
Usage: kew loop resume <loop_id> [OPTIONS]
Arguments:
loop_id ID of the loop to resume (use `kew status` to list)
Options:
--guidance TEXT Human guidance injected into the continuation session (required)
--budget FLOAT New per-session budget cap in USD (overwrites the loop's cap)
--max-steps INT New per-session step cap (overwrites the loop's cap)
--timeout INT New per-session wall-clock cap in minutes (overwrites the loop's cap)
--runner TEXT Reassign to a different native runner (e.g. claude-code, opencode)
--model TEXT Override the model for the continuation (must be priced)
Examples:
# Resume a needs_human loop with guidance
kew loop resume abc123 --guidance "The failing test expects a UTC timestamp, not local time."
# Resume a budget_limited loop with a larger budget
kew loop resume abc123 --guidance "Keep going — expand the test coverage too." --budget 5.0
# Resume with new step and time caps
kew loop resume abc123 --guidance "Try a simpler approach." --max-steps 30 --timeout 20
# Reassign to opencode and override the model
kew loop resume abc123 --guidance "Try with opencode." --runner opencode --model claude-sonnet-4-6
Not to be confused with
kew resume.kew resumeclears the fleet-stop latch engaged bykew stopand re-enables dispatch for all issues. Seekew resume.
What it does¶
kew loop resume continues a paused loop on the same loop record — same
worktree, same branch, same loop_id. It:
- Validates the loop is in a resumable state (
needs_humanorbudget_limited). - Restores or reuses the loop's worktree (the prior agent's committed work is already there).
- Applies any cap bumps (
--budget,--max-steps,--timeout) to the loop record before launching. - Injects your
--guidanceinto a fresh continuation prompt alongside the original goal and the reason the loop stopped. - Launches a new agent session against the same worktree.
- Re-runs the verification gate when the session ends —
achievedstill requires a real gate pass. The resume does not bypass the gate.
The loop's step_count and spent_usd accumulate across resumes, so the
timeline in kew status and the TUI Flight Recorder reflects the loop's full
lifetime spend.
Resumable states¶
| Status | Resumable? | Typical cause |
|---|---|---|
needs_human |
Yes | Agent got stuck, gate failed (sabotage guard), or a run error (timeout, crash) |
budget_limited |
Yes | Session hit agent.max_budget_usd before the gate passed |
achieved |
No | Loop already succeeded — resume rejected |
unmet |
No | Loop was explicitly closed as unmet — resume rejected |
Budget semantics¶
Each continuation runs with a fresh per-session allowance for max_steps,
budget, and wall clock — the same model as a normal first-class loop run.
Budget accumulation across resumes
A budget_limited loop resumed without --budget continues under the
loop's existing cap as a new session allowance. Because each resume gets its
own fresh allowance, the loop's lifetime spend can exceed the original cap
by design — one cap-worth per resume. Use --budget to set a tighter or looser
cap for the next continuation. The spent_usd shown on the loop record
accumulates across all sessions.
Step cap¶
The step cap (max_steps) is a runaway guard — if the agent takes more steps
than the cap, the loop is classified needs_human before the verification gate
runs.
The default cap is scaled by issue complexity:
| Complexity | Default max_steps |
|---|---|
simple |
80 |
medium |
200 |
complex |
400 |
Override with --max-steps at dispatch time or on resume:
Runner and model reassignment¶
A loop records both halves of its route — the runner and the model it was
dispatched on, plus the complexity tier they were resolved at — so a resume
continues on the route the loop started on. A loop routed by complexity (a
simple-labelled issue landing on the simple tier) keeps that tier for every
later session instead of falling back to the [routing].default / [agent]
route. Loops created before this was recorded (schema v34 and earlier) have no
stored model and still resolve from config.
A flag-less kew loop resume picks its route in this order:
- A runtime route override — a
config_overridesrow foragent.modelorrouting.*, set in the web UI or by a second operator. That surface exists to steer the effective route without a commit, so it wins: the continuation re-resolves from the effective config at the loop's own recorded tier (never[routing].default). Without this, an in-flight loop would be unsteerable short of killing and re-dispatching it. - The loop's own recorded route. Absent such an override, the record decides
— so an edit to a committed
kew.tomldoes not re-route a live loop, and an earlier explicit--runner/--modelreassignment is not forgotten. - The config route at the loop's tier, for a pre-v35 record that has no route to continue.
An explicit --runner / --model on the resume itself outranks all three — it
is you naming the route for this loop.
Use --runner to continue the loop on a different native runner:
Native runners are claude-code, opencode, and pi. Passing any other value is rejected
with an error. The loop's existing worktree and branch carry over — the new runner inherits all committed
work from prior sessions.
--runner on its own swaps only the runner: the continuation keeps the model
already recorded on the loop, rather than reverting to [agent].model — but
only if the new runner can actually run that model. kew never invents the
missing half of a route in either direction, so if the pair would be
cross-provider (say --runner claude-code on a loop recorded against
openrouter/deepseek/deepseek-v4-flash) the resume is refused before anything
runs, naming both halves:
cannot resume abc123: runner 'claude-code' cannot run the recorded model
'openrouter/deepseek/deepseek-v4-flash'; pass an explicit --model to name the
route you want
Pair --runner with --model to change both halves — an explicit --model is
you naming the route, so it is never second-guessed (it still has to be priced).
The same refusal applies to the legacy path where a pre-v35 loop would otherwise
pair the new runner with [agent].model.
Compatibility is decided by the runner registry's model namespaces — the same prefixes routing already uses to infer a runner from a model:
| Runner | Models it can be handed implicitly |
|---|---|
claude-code |
claude-* |
opencode |
openrouter/*, ollama/*, gpt-*, gemini-*, o1-/o3-/o4-*, any provider/model |
pi, hermes |
openrouter/* |
lemonade |
lemonade/* |
Anything outside the table needs an explicit --model.
Whenever the runner a session runs under differs from the one on the record, a
loop_reassigned audit event is written before the continuation starts,
capturing the old and new runner names — including the legacy path where a
pre-v35 loop with no recorded model resolves from config. Both halves of the
route that actually ran are then written to the record, so the next resume
continues on it rather than reverting or inheriting a pair no session ran.
Use --model to override the model for the continuation session:
The model must be priced — either listed in MODEL_PRICING or added to
config.pricing.overrides. By default, only claude-* models are priced. If you want to run
OpenCode with a Gemini or GPT model, add it to config.pricing.overrides first (or use a free
ollama/* model — ollama/ models are zero-cost and bypass the priced check). Passing an
unpriced model is rejected before any mutation occurs.
Audit trail¶
A loop_resumed event is written to the audit trail before the session starts,
recording loop_id, guidance, and the budget_usd and max_steps cap values. This is followed by
the normal loop_started, iteration_recorded, verification_checked, and
loop_finished (or needs_human_raised) events from the continuation run.