Run on your own machine
Pair a Mac, Linux box, or Windows machine and send phases to it — no ports to open, no tunnel.
The Peractor runner covers most work, but some phases need a real machine: building and screenshotting a native app, driving the iOS or Android simulator, a GPU, a toolchain only your box has.
Pairing puts your own machine behind a workflow phase. The agent runs there directly, with everything the machine can see and do.
How the connection works
The machine runs a small agent that dials out to Peractor over one WebSocket and keeps it alive with heartbeats. Everything — assignments, the live transcript, questions, git actions, screenshots — rides that one outbound connection. Nothing ever connects to your machine, so:
- No public IP address needed. Home NAT, office network, and hotel Wi-Fi all work.
- No port forwarding, no tunnel service, nothing to install beyond the agent.
- If the connection drops — sleep, a network change — the agent reconnects by itself.
What the machine needs installed
Phases run directly on your machine, not in a container. That is the point of pairing one, and it means the machine brings its own tools. Peractor installs nothing on it, and the Peractor runner having a program is no help here.
- macOS, Linux, or Windows.
- git — every phase clones the repository and pushes its branch.
- The agent CLI your workflows use —
claudeand/orcodex, plus a way for it to sign in. A machine that only runs command steps needs neither. - Node.js 24 or newer — the runner is a single file that runs on it. No checkout, no build.
- Whatever your own steps call — Xcode, a JDK, a package manager.
The runner checks all of this when it starts and prints one line per program, so read its first few lines before sending work:
Peractor runner: git — ok (/usr/bin/git)
Peractor runner: claude — ok (/Users/you/.local/bin/claude)
Peractor runner: codex — not installed (only needed for prompt steps whose agent is Codex)
"…isn't installed on this runner machine"
A phase that fails with this ran on your machine and could not find the program it needed. Two causes, likeliest first:
- It is not on the PATH the runner sees. The message ends with the exact PATH the run used — compare it with your terminal's. A background service does not get your shell's PATH by default, which is why the installer copies the PATH of the terminal you ran it in. So if you installed the tool (or a version manager like nvm, fnm, or mise) after pairing, re-run the install command from a terminal where the tool works.
- It genuinely is not installed there. Install it, then re-run the install command — the startup check will say ok.
Installing it on the Peractor server changes nothing for a paired machine, and installing it on the machine changes nothing for phases on the Peractor runner. Each place runs its own phases with its own tools.
Pair it
In Settings → Runners, use Pair a machine: give it
a name and at least one label, say macos. Pairing shows a
one-time token inside the exact command to run — copy it then, it is
never shown again. Only admins can pair or remove machines.
Run that command in a terminal on the machine:
curl -fsSL https://peractor.com/runner.sh | sh -s -- <your pairing token>
It takes a few seconds and does three things, all inside your home directory and none of them as root: downloads the runner, saves the token readable only by you, and installs it as a background service — a user LaunchAgent on macOS, a systemd user unit on Linux — so it survives logout and reboot. The Runners screen shows the machine online within a few seconds, and its log sits beside the runner.
The runner comes from the Peractor you paired with, so it always matches that control plane, including a self-hosted one. Running the same command again upgrades it in place.
Two options if you would rather not have a service:
--no-serviceruns it in that terminal, for the length of that terminal.--uninstallstops it, removes the service, and deletes its directory. Remove the pairing in Settings too — that is what revokes the token.
Windows (experimental)
A Windows machine pairs the same way with the PowerShell installer, which the pairing screen also prints. It installs under your user profile and keeps the runner alive with a scheduled task at logon.
Three honest differences, all by design:
- Command and check steps run under cmd.exe, not a POSIX
shell. A workflow whose steps say
ls && makeis written for the other machines. Give Windows machines their own label and write those steps for cmd. - Agent CLIs must be native builds. Windows cannot launch an npm shim from a service. The runner's startup check tells you when it found only a shim.
- SSH keys with a passphrase are not supported there yet — use a key without one, or an https token.
Experimental means exactly that: the paths above are tested in code, not yet on a fleet of real Windows machines.
How the agent signs in
Each machine signs in to the coding agent on its own. Your organization's key from Model providers backs the Peractor runner and is never sent to a paired machine. Two ways, either works:
- Save a credential for the machine — in Settings → Runners, the machine sign-in form stores a key or subscription token per machine. Admins only, write-only, shown as "set" but never readable back. Nothing on the machine needs configuring.
- Sign the machine itself in — run
claudeonce and log in, or set the credential in the environment that starts the runner. Save nothing in Settings and the machine's own sign-in carries its runs.
With neither, a run on that machine fails with the agent's own "not logged in" message. Nothing degrades silently.
When the plan runs out
The subscription a run spends is the machine's, so a machine can tell Peractor how that plan is doing. It is off by default — a machine's remaining plan is its owner's information — and an admin turns it on per machine.
With it on, the machine's row says when a coding-agent plan is used up and when the provider says it comes back, runs wait for the reset instead of failing on a machine that would only refuse them, and a run that does hit the limit says so in plain words instead of showing a bare error.
How it reaches your code
By default a run on your machine clones and pushes with your organization's credential from Git access. In Settings → Runners, Git access can set a machine's own instead:
- This machine's own git — Peractor sends the machine nothing. The clone and the push are signed by whatever the machine is already set up with: its SSH agent, a key, a credential helper. Nobody has to give Peractor a credential that can read your code, and the code only ever exists on hardware you own.
- A token or SSH key for this machine — stored for that machine alone and used by its runs, in place of the organization's.
Pull requests are still opened by Peractor, not by the machine, so a workflow with a git step that opens or merges one needs the GitHub app or an organization token for that part.
Send work to it
phases:
- id: build
title: Build and verify the app
runner: { labels: [macos] }
gate: true
steps:
- { type: command, name: build, run: "xcodebuild -scheme App build" }
- type: prompt
prompt: |
Launch the app in the iOS simulator, exercise the new screen, and
take screenshots of each state. Register the screenshots as
artifacts so the reviewer sees them.
You can set this from the workflow editor on any surface — each phase has a Runs on field offering your machines' labels, and it says plainly when a label matches nothing right now.
Phases without runner labels keep using the Peractor runner. Pairing never redirects work that did not ask for it. If the machine is offline when a labelled phase starts, the phase parks at its gate with the reason; start the agent and approve to retry.
Screenshots and other files the agent registers as artifacts come back inline in the run, so the reviewer sees the actual screens without touching the machine.
GUI work on macOS
Simulators, screenshots, and anything that touches the window server only work when the agent runs inside your logged-in desktop session. The installer puts it there, so this needs nothing extra as long as you run the install command on the Mac itself. Over SSH it refuses rather than installing something that would run blind.
- Grant Screen Recording in System Settings, under Privacy & Security. macOS prompts on the first capture, and the app it names is whatever started the runner.
- iOS work needs Xcode and its simulators; Android work needs an emulator image.
- Keep the machine awake for the hours you expect runs.
Trust, in both directions
The run arrives with exactly what it needs: a short-lived repository credential, the secrets the workflow declares, and this machine's own model credential if one is saved — never the organization-wide one.
In the other direction there is no container on your machine. The agent executes with your user's own access. Treat pairing like handing the organization a terminal on that box: pair machines you own, for organizations you trust, and remove the pairing the moment a machine should not receive work. Removal revokes the token and closes a live connection immediately.
Previews from your machine
Preview steps work here too. The served result stays bound to the machine's own localhost, and its traffic rides the same outbound connection back to Peractor — so reviewers open the usual per-run link with no port opened on the machine and nothing exposed to its network.
One limitation today
The warm workspace cache does not apply on a paired machine: each phase starts from a fresh clone.