Skip to content

ticket-runner ​

Humans plan, the pipeline executes.

ticket-runner runs the unattended half of the mattpocock-skills chain. Planning a feature takes judgement, so it stays with humans, in their own sessions: /grilling, /to-spec and /to-tickets (or /triage) turn it into GitHub issues, each with checkbox Acceptance Criteria, its blockers linked and the ready-for-agent label. Carrying an issue from there to a merge is repetitive, so the pipeline does it unattended, driving /implement where a human would have typed it. For each Ticket it has a headless Claude Code session implement the work, runs the repository's own tests, has a second session try to prove the criteria are not met, opens a pull request, waits for CI and squash-merges. Whatever it cannot finish goes back to a human with a draft pull request and a comment.

Why it exists ​

After Planning, every Ticket still needs an attended session: open it, paste the Ticket, wait, review, commit, merge, close, then go and find the next unblocked Ticket. Ten Tickets are ten sessions. The Frontier, the Tickets nothing blocks any more, never moves by itself, because nothing closes Tickets. The pipeline ends your part when Planning ends: one command drains the Frontier and leaves merged code behind.

When it fits, and when it does not ​

It fits when:

  • Planning has produced agent-sized Tickets, with checkbox criteria and native blockers.
  • The repository has CI, and a test or typecheck command the pipeline can run itself.
  • You want the work merged while you are away: overnight, or started from the Claude app.

It does not fit when:

  • The work needs a human's judgement midway. A Run asks nobody anything; a Ticket it cannot finish reaches a human only as a Hand-off.
  • No checkbox can grade the criteria. The verify Stage grades only - [ ] lines, and a Verdict of nothing but unverifiable fails: it is no evidence to merge on.
  • Nothing may merge without a person's review. A pull request is squash-merged as soon as its CI passes; nobody approves it first.
  • The repository has no CI or tests. A Run refuses to start without a Check and hands off a pull request with no CI checks, unless gates is switched off, and then it merges unchecked code.

Quick Start ​

You need Node 22 or newer, git, an authenticated gh, and claude with the mattpocock-skills plugin, version 1.2.3 or later. Installation has the full list.

bash
npm install -g ticket-runner

cd ~/code/acme        # the repository you want it to work in
ticket-runner init    # set it up, and report what only you can fix
ticket-runner run     # take every ready Ticket to a merge

To try it before installing anything, type npx ticket-runner wherever these pages say ticket-runner: see Try it without installing.

init exits 1 while anything it reports is still yours to fix, so ticket-runner init && ticket-runner run stops before a Run that could not work. A Run takes only issues that Planning made usable: labelled ready-for-agent, with - [ ] criteria, and blocked only through GitHub's own blocked by links.

The whole flow ​

Any Stage can be rate-limited, not only implement; every one of them ends in a Release. From Ticket to merge walks the Execution half one step at a time.

The guide ​

PageRead it for
Install and removeRequirements, the npm install, init, what a Run requires of a Target, remove, uninstalling
Planning the workWhat makes an issue a Ticket: Specs, Acceptance Criteria, native blockers, labels, the Guards
Runningrun, --lanes, a narrowed Run, stop, -v, the summary and exit codes, logs, running from the Claude app
ConfigurationEvery field of ticket-runner.json
From Ticket to mergeThe Stages, the Fix budget, Lanes and the Landing, rebase conflicts, what the board is told, Notes
Stopping and resumingHand-off, Release, Stop against kill, Stranded Tickets, handing a Ticket back, the Run lock and the State branch
InternalsPorts and adapters, a map of the modules, Versions, the ADRs, working on the pipeline itself

The words the pipeline uses (Ticket, Run, Stage, Lane and the rest) are defined once, in the glossary.