Recovering a run
A run that does not reach a pull request stops in one of two ways. They are not equally common, and they are not recovered the same way, so it is worth knowing which one you have.
| Exit | Resumable? | How you continue | |
|---|---|---|---|
| Paused — stopped short, checkpoint intact | 75 |
Yes, always | styre run --resume <ident> |
| Abandoned — reserved terminal | 1 |
No | Not currently produced by any run |
Every pause is resumable. There is no split between a kind of stop that saves state and a kind that doesn’t — the checkpoint is written continuously while the run works, not only at the moment it stops, so it is always there to resume from.
Paused runs
Section titled “Paused runs”A run pauses whenever it stops without reaching a pull request. The reason tells you why:
| Reason | What it means | Consumes a retry? |
|---|---|---|
budget |
A session limit was hit, or your provider account ran out of credits. | No — pausing is an interruption, not a failure. |
needs_you |
The loop bounded its retries — a step, a check, or a review kept failing the same way — or it hit something structurally unresolvable on its own (a bad acceptance criterion, a plan defect, a broken environment). | Depends on the cause; read the message. |
interrupted |
Reserved for a crash, SIGINT, or a power loss. Not emitted by a graceful stop — if the process is still running long enough to print a reason, it is budget or needs_you. |
No. |
Whatever the reason, the outcome is the same: exit 75, and the run is resumable.
The reason and the resume command are printed on stderr:
Paused — out of budget: session limit reached (resets 2026-07-23T18:00:00Z).Resume with: styre run --resume ENG-482 --profile ~/.config/styre/acme-app/profile.jsonCheckpoint: ~/.local/state/styre/acme-app/ENG-482The checkpoint holds the run’s record and the in-progress step’s partial output. Your committed work is not in there — it is already safe in the branch, in git. This is not a park-time dump written once as the run exits; the run journals to this location continuously as it works, so it is the live state of the effort, not a snapshot taken on the way out.
Resuming
Section titled “Resuming”styre run --resume ENG-482 --profile ~/.config/styre/acme-app/profile.jsonOnly the interrupted step runs again. Everything already finished stays finished. There is no
separate flag for “resume after I fixed the cause” — a plain --resume always picks up wherever the
run left off and re-evaluates from there, so fixing the underlying problem before you resume is
enough.
When the branch has moved
Section titled “When the branch has moved”If the branch head changed while the run was paused — you pushed a commit, or amended one — resume refuses rather than building on a base it does not recognise:
resume refused: branch HEAD moved since the run paused.That is exit 65. Three ways forward, starting with the safe one:
styre run --resume ENG-482 --inspectShows what it would do and changes nothing.
styre run --resume ENG-482 --accept-headResumes against the new head, discarding the carried-over context from the interrupted step.
styre run ENG-482 --freshDiscards the existing checkpoint and starts over from scratch.
Exit 65 is also returned if a concurrent resume already holds the run’s lock — a second
styre run --resume on the same ticket while one is already in progress. In that case, wait for
the other resume to finish rather than racing it.
Starting fresh instead of resuming
Section titled “Starting fresh instead of resuming”A checkpoint for a ticket is only ever replaced on purpose. If you run styre run ENG-482 while a
checkpoint for ENG-482 already exists, it refuses rather than silently clobbering it:
a checkpoint already exists for ENG-482 at ~/.local/state/styre/acme-app/ENG-482Resume it with 'styre run --resume ENG-482', or discard it with 'styre run ENG-482 --fresh'.Use --resume to continue, or --fresh to discard the checkpoint and run the ticket from
scratch — useful once you have rewritten the acceptance criteria, or decided the existing attempt
is not worth continuing.
Every reason a run pauses for needs_you
Section titled “Every reason a run pauses for needs_you”Grouped by what you would do about it. All of these end the same way — a paused run at exit 75,
resumable once you’ve acted on the cause.
The loop ran out of attempts
Section titled “The loop ran out of attempts”| Message | What happened | What to do |
|---|---|---|
step '<name>' exhausted after 3 attempts |
One step failed three times. | Read that step’s error. Retrying unchanged will not help — fix the cause, then resume. |
no progress: '<name>' failed identically twice |
A check failed the same way twice running — the fix attempts are not changing anything. | Usually a real defect the agent cannot see. Look at the failure yourself, then resume. |
no progress: '<name>' under-delivered identically twice |
A work unit twice failed to touch the files its plan said it would. | Often a plan built on the wrong files. Re-scope the ticket, then resume. |
The acceptance checks could not be settled
Section titled “The acceptance checks could not be settled”| Message | What happened | What to do |
|---|---|---|
no progress: AC-check(s) N still flagged after 2 re-authors |
The test for one of your criteria was rewritten twice and still is not sound. | Almost always the criterion, not the code. Rewrite it — see Writing a ticket — then resume. |
no progress: repeated re-author of the same AC-check |
The same check kept being rewritten without improving. | As above. |
gate: still red after 3 arbitrated rounds |
The acceptance tests stayed red across three rounds of adjudication. | Check whether the criterion is achievable as written, then resume. |
gate: check(s) still red at HEAD … no further HEAD movement possible |
The code stopped changing but the tests are still red, so nothing further can move it. | The criterion and the implementation disagree. One of them has to give — fix it, then resume. |
Review would not sign it off
Section titled “Review would not sign it off”| Message | What happened | What to do |
|---|---|---|
no progress: identical review findings |
The reviewer raised the same blocking findings twice. | Read the findings — the fix attempts are not landing. Fix, then resume. |
no progress: identical plan-review findings |
The same, on the plan rather than the code. | The plan needs your input before continuing is worth it. |
blocking plan-defect found in code review; operator policy is escalate |
Review found a problem with the plan itself, not the code. | This is the default policy. Set onPlanDefect: "redesign" in config to loop back and re-plan instead of pausing. |
deferrable major finding requires a human deferral decision |
Review found something significant and will not decide on its own whether to defer it. | Yours to call: fix it, or accept it and resume. |
The environment, or an external service
Section titled “The environment, or an external service”| Message | What happened | What to do |
|---|---|---|
provision failed for ticket |
Installing dependencies failed. This pauses on the first failure, with no retries. | Fix the environment — lockfile, toolchain, network — then resume. |
step 'verify:checks-gate' failed: … |
The gate hit an infrastructure fault rather than a genuine red result. | Usually environmental. Read the error, fix it, then resume. |
| A projection failure | Styre could not write back to Linear, Jira, GitHub or Slack after several attempts. | The service is down, or your token is wrong. The run’s own work is unaffected — fix the credential or wait it out, then resume. |
None of these require a fresh run. Fix the cause and resume — the pending reason is consumed as part of resuming, so there is no separate “resume after fix” step.
Abandoned: exit 1
Section titled “Abandoned: exit 1”abandoned is a reserved terminal outcome — the run gave up for good, with nothing left to
continue from. It is not currently produced by any code path in styre: every stop today is a
paused run with a reason, and pausing is always resumable. If you see exit 1, treat it as
unexpected and worth reporting rather than as a routine outcome to work around.
Listing & cleaning up
Section titled “Listing & cleaning up”styre ls lists every paused, resumable effort across your projects, each with the exact
styre run --resume <ident> --slug <slug> command to pick it back up, plus a separate section for
finished (pr-ready/done) leftovers and one for runs currently in progress. It’s the quickest way
to find a paused effort again if you’ve lost track of its ident.
styre clean <ident> reaps that one effort’s disk artifacts — its worktree and its checkpoint. It
refuses (exit 75) if a run is currently live on that ident. styre clean --all reaps only
provably-finished (pr-ready/done) efforts for the current project, and skips anything paused or
running. Add --purge to a single-ident clean to also delete the local and remote branch (closing
the PR); it is opt-in and does nothing to the repo’s default branch beyond reaping disk state.
Cleaning is not abandoning the ticket. styre clean only reaps local disk state — the worktree
and the checkpoint. It never changes the ticket’s status with your tracker, and it does not touch a
run that is still in progress; it refuses instead. If you clean a paused effort, the checkpoint is
gone and a later styre run <ident> starts fresh (there is nothing left to --resume), but the
ticket itself is exactly as unresolved as before.
Refusals before a run starts
Section titled “Refusals before a run starts”These stop a run before any work happens, and none of them is a failure of the loop:
| Exit | What it means | Fix |
|---|---|---|
64 |
A checkpoint already exists and you ran without --resume or --fresh. |
--resume to continue, --fresh to discard and start over. |
65 |
Resume refused — the branch moved, or another resume of the same ticket is already running. | --inspect, then --accept-head or --fresh; if it’s a concurrent resume, wait for it to finish. |
69 |
A program your build or test commands need is missing. | Install it; the message names it. |
75 |
styre clean <ident> pointed at a run that is still live. |
Wait for the run to finish (or resume it), then clean. |
78 |
Bad config, or an unusable profile. | Fix the value, or re-run styre setup. |
See Exit codes for the full table.