Always-on runners
Run the runner on a VPS so automated runs never wait, and what happens to dispatched runs, automations, and chat turns while a device is offline.
The runner connects to your backend from wherever it runs - pairing works from any machine that can reach your app's URL. A laptop that sleeps means queued work waits; an always-on machine means automations run the moment they are due.
What happens while a device is offline
| Work | Behaviour on an offline device |
|---|---|
| A run your product dispatches | Queues for 24 hours and starts as soon as the device reconnects. |
| An automation | Never queues. Presence is checked before anything is enqueued: with a usable fallback the fire runs there, otherwise it is recorded as a failed run naming the reason. A fallback is usable when it is a cloud model or a second paired device that is online. |
| An interactive chat turn | Refused outright (409) rather than queued, so the user can reconnect or pick a cloud model instead of waiting. |
| A run never collected in the window | Surfaces as expired in the app - the chat view and the automation status both say so. |
- A run leaves the queue when the device collects it. A device that drops before collection leaves the run waiting; a device that dies mid-run never resumes it, so the run expires 24 hours after collection - the hard ceiling on any run's life.
- An automation never overlaps itself. While one of its runs is still going, every fire is refused and recorded as an error; fires resume once that run ends or hits the 24-hour ceiling. The daemon gives up sooner on a run that goes 15 minutes with no output at all.
- An automation that comes due while its previous run is still queued replaces it, so only the latest run executes on reconnect, never a backlog.
- The automation card shows its pinned device and warns whenever that device cannot run it - offline, or online with the automation's CLI disconnected or signed out; you can move the automation in one click to any other paired device that has the same CLI connected and not signed out.
Run it on an always-on machine
Install on the server
Run the same install one-liner from the app's Runners page on the VPS (Linux and macOS are supported; a small always-free instance is plenty - the runner is idle until work arrives).
Pair it from the server
Pair exactly as on a desktop: run the pair command from the Runners page and approve it in your browser. Pairing binds the DEVICE, so the server shows up as its own runner alongside any others.
Let the service keep it alive
The one-liner's setup registers the always-on OS service, so the daemon starts on boot and survives reboots. It holds one connection to your backend and costs nothing while idle.
Tuning
- Concurrent runs. The cap is machine-global - one budget across every surface the daemon serves (all paired backends plus the user's own local work), not per backend. It defaults to 2; raise it on a beefy server with
limits set --max-concurrent-runs 4, effective on the next run with no restart. Interactive local work keeps priority, so under a low cap sustained local chat can delay backend runs. - Transport. The daemon holds one connection and receives work over it, so dispatch is immediate and an idle device sends no requests. Nothing to configure - see how work reaches a device.
- One daemon, every account. Each pairing keeps its own bearer, connected CLIs, and work folder, so two accounts on one computer never share state - but they draw on the same machine-global cap above.
Terminal Sessions
Any user can open their own coding CLI already wired to your product - your capabilities on its MCP surface, your prompt in its context - from their own terminal.
Your Agent on a Runner
A runner is a third model source alongside built-in AI and user keys - what it can run, the one call it cannot, and the single constraint your own agent tools must satisfy to reach a device.