Skip to content

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:

kew loop pause abc123

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:
    kew loop resume abc123 --guidance "..."
    

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 stop land in the same moment, the loop may record paused (the underlying run is still marked killed). Either way the worktree is preserved and the loop can be continued with kew loop resume.

Error conditions

  • Loop not found or not in pursuing state — exits with a non-zero code and a message. A loop that is already needs_human, achieved, unmet, or paused cannot 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 resume clears the fleet-stop latch engaged by kew stop and re-enables dispatch for all issues. See kew resume.

What it does

kew loop resume continues a paused loop on the same loop record — same worktree, same branch, same loop_id. It:

  1. Validates the loop is in a resumable state (needs_human or budget_limited).
  2. Restores or reuses the loop's worktree (the prior agent's committed work is already there).
  3. Applies any cap bumps (--budget, --max-steps, --timeout) to the loop record before launching.
  4. Injects your --guidance into a fresh continuation prompt alongside the original goal and the reason the loop stopped.
  5. Launches a new agent session against the same worktree.
  6. Re-runs the verification gate when the session ends — achieved still 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:

kew loop resume L1 --guidance "keep going" --max-steps 500

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:

  1. A runtime route override — a config_overrides row for agent.model or routing.*, 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.
  2. The loop's own recorded route. Absent such an override, the record decides — so an edit to a committed kew.toml does not re-route a live loop, and an earlier explicit --runner / --model reassignment is not forgotten.
  3. 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:

kew loop resume abc123 --guidance "Try opencode this time." --runner opencode

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].modelbut 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:

kew loop resume abc123 --guidance "go" --runner opencode --model claude-sonnet-4-6

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.