DOCS · INTEGRATIONS

Self-hosted runners

Pair a machine to run spec, onboard and build jobs with its own Claude Code and its own git credentials.

On this page

A runner is a machine of yours that claims jobs and executes them locally. It exists so the model credential and the git credential can both be yours, on hardware you control, while specd still orchestrates the pipeline.

Pair a machine

  1. Generate a pairing code

    From the project's Settings page (owner or maintainer). It is shown once — copy it now.

  2. Run the pair command on the machine

    specd runner pair 5VXCK-7UYZC. The code is single-use and expires after 30 minutes if never redeemed, the same way an unused device-login code does.

  3. Read all three lines it prints

    It reports the project it paired with, that the token was stored, and that outbound connectivity to the API works — so a firewall rule is caught right there rather than discovered later on a job that silently never starts.

Run the daemon

terminal
SPECD_RUNNER_TOKEN=$(specd runner token) SPECD_API=http://localhost:4000/api \
  pnpm --filter @specd/runner start

It polls for claimable work on an interval (SPECD_RUNNER_POLL_MS, default 5s). When a spec or onboard job is queued for its project, it drives the machine's own local claude CLI and reports the parsed result back.

It never touches the database or the knowledge index — the server does all of that on either side of the daemon's one job: drive the model, hand back a parsed reply. build jobs are the exception that also needs git on PATH.

Builds use the runner's own git

Leases and reclaim

A claimed job is held under a lease. If the runner stops heartbeating, the job becomes claimable again — after 180s for most jobs, 900s for builds, because a build legitimately takes longer to look alive.

After three reclaims the job is failed as repeatedly abandoned rather than bouncing between runners forever. A job that cannot be executed anywhere is a job someone needs to look at, and a queue that hides that is a queue that quietly stalls.

Managing runners

Project Settings lists every runner — paired or awaiting its first pairing, and how long since it was last heard from. Removing one revokes it immediately: its stored token stops authenticating on the very next request, with no grace period.

When a runner is used

Automatically, whenever a project's AI mode is subscription_runner and a runner is paired to it. If no runner is available, nothing is dispatched — the synchronous path (specd's own process shelling out to a local claude) runs exactly as before.

The complete reference — every environment variable, the job lifecycle, the build sandbox — is in docs/runners.md in the repository.