Skip to content

Runners

draft

A runner is a machine that runs agents for Pitwall: a Linux server or a Mac. It opens every connection to the server itself; the server never reaches into it, so it needs no inbound port. Agents run on it as its user, in a checkout of the project’s repository, with its owner’s Claude account.

Need For
Claude Code CLI Running the agents
git, able to clone and push to the projects’ repositories Checkouts and the ticket’s branch: the runner pushes with your own git credentials
curl The install
gh, logged in (optional) Creating a new project’s repository on GitHub, with your own login
systemd on Linux, launchd on macOS The background service

Binaries exist for linux/amd64 and darwin/arm64.

  1. Open Runners and click Register runner. Give it a name, its labels, and whose work it accepts:

    Sharing Takes
    Owner only Your tickets only
    Owner projects Every project you belong to
  2. Run the command the wizard shows, on the machine. It downloads pitwall-runner into ~/.local/bin, registers it, starts it as a background service of your user, and ends by checking the machine:

    Terminal window
    curl -fsSL <core>/api/runner/install.sh | sh -s -- --core-url <core> --token <token> --name <name> --labels <labels>

    On a new machine the checks say what is left, which is normal:

    [PASS] Claude CLI 2.1.296 (Claude Code)
    [FAIL] Claude token no Claude token is stored
    [PASS] git git version 2.43.0
    ✗ Not ready: 1 check failed. The runner takes no jobs until every check passes.
  3. Give it a Claude token. Signed in to the account, run claude setup-token, then paste what it printed into:

    Terminal window
    pitwall-runner claude-token add --account <that account’s email>

    No restart: the runner notices within a minute. Repeat for each account the machine should use, up to four. The same account’s token may go on every runner.

  4. The wizard, left open, shows the runner connected within 15 seconds, and its checks turning ready on their own.

Every command is listed in pitwall-runner CLI.

A runner answers for its own state. It checks what its jobs need every minute, takes no job while a check fails, and says why on the Runners page.

Check Passes when Also fails after
Claude CLI The CLI answers
Claude token A token is stored, readable by the runner’s user only A job whose token was not accepted, until the token changes
git git answers
git access Shown only after a fault A clone, fetch or push refused, until the runner can reach that remote again
Self-update Shown only after a fault An update that failed

pitwall-runner doctor prints the same checks, with what to run for each that failed.

gh is not a check: a runner without it is still ready. doctor adds a line for it, [PASS] with the GitHub user it is logged in as, or [INFO] with how to log in. Only a runner with gh logged in can create a project’s repository; the New project form says which of yours can (Creating a project).

A ticket whose step no runner can take says no runner ready on its page, with each runner and what keeps it. Fix the runner and the step starts on its own: nothing is retried by hand, and no attempt is spent.

The runner says Do
not ready, Claude token claude setup-token, then pitwall-runner claude-token add --account <email>, on that machine
no account available until … Every account it holds is limited: it starts on its own then, or sooner when you free an account (Claude accounts and usage)
every account is off Turn one on in Your settings → Claude accounts
not ready, git access Give the machine’s git credentials write access to the repository named
outdated Nothing: it updates itself once it holds no job
offline Start the machine, or check pitwall-runner service status on it

A token no longer accepted, or git credentials that expired, are found by the first job. The job goes back to the queue without spending an attempt, and the runner turns not ready until fixed.

A runner is When
Online It sent a heartbeat in the last 45 seconds
Offline Otherwise, shown with when it was last seen
Lost Offline for 90 seconds more, or revoked. The jobs it held go back to the queue

A run is tied to no runner: its work is pushed after every commit, so the next step goes to any runner that can take it. The exception is a step that asked you a question, whose answer continues on the runner that asked.

A runner updates itself. A runner built from another commit than the server is outdated: it is given no work, and once it holds no job it downloads the server’s build, replaces its binary and restarts, in seconds. A runner in the middle of a step finishes the step first, and the run waits those seconds.

Update by hand in three cases:

Case How you know
It was installed before self-update existed It stays outdated, “cannot update itself”
It was registered with --no-self-update Its card says “self-update off”
An update failed and was rolled back Its card says “update failed · rolled back”

On that machine, with <os>/<arch> being linux/amd64 or darwin/arm64:

Terminal window
curl -fsSL -o ~/.local/bin/pitwall-runner.new <core>/api/runner/download/<os>/<arch>
chmod 755 ~/.local/bin/pitwall-runner.new
mv ~/.local/bin/pitwall-runner.new ~/.local/bin/pitwall-runner
pitwall-runner service install

service install restarts the service on the new binary and keeps the registration, the workspace and any paused job. Do not run the install command from Register runner again: it registers a second runner.

  1. pitwall-runner service uninstall stops the service and removes it.
  2. Revoke the runner on the Runners page, which ends its credential.
  3. Delete ~/.local/bin/pitwall-runner, ~/.config/pitwall-runner/ and ~/.local/share/pitwall-runner/ to leave nothing behind.