<!-- description: AgentRQ v0.7.0 adds Machines — install agentrqd on a computer you own, enrol it once, and start a coding agent on it from the control panel, then watch its terminal and type into it from anywhere. -->
<!-- date: 2026-09-17 -->
<!-- author: AgentRQ Team -->
<!-- ogimage: https://agentrq.com/assets/blog/machines-og.png -->

# Machines: Run Agents on Hardware You Own, and Watch the Terminal From Anywhere

Until now, an AgentRQ agent ran wherever AgentRQ ran. Your own computers — the workstation with the toolchain, the build box under the desk, the spare laptop that does nothing at night — were not places you could put one.

AgentRQ v0.7.0 changes that. Install one binary on a computer, enrol it once, and it becomes a place agents can run. You start them from the control panel, and you watch their terminals from whatever you happen to be holding.

![The machine detail page: the launcher, three running sessions, and what the box has left](/assets/blog/machines-detail.png)

## The Shape of It

There are three nouns and they map onto three screens.

A **machine** is a computer running `agentrqd`. The machines page lists them with a status dot, the agent count, and enough of a reading to answer the only question that matters before you start another one — whether this box can take it.

![The machines list: one online host with its CPU and memory reading](/assets/blog/machines-list.png)

A **session** is one agent running on one machine, in one workspace's folder. You start it by choosing those two things and pressing a button.

A **terminal** is your view into a session, and it is a real one.

![Watching a claude-code session started on a remote machine](/assets/blog/machines-terminal.png)

## The Terminal Is Not a Log Viewer

This is the part worth being precise about, because "see the output" and "use the terminal" are very different products and only one of them is useful.

The browser runs `xterm.js`, and what it sends is exactly the bytes your keys produced. Esc is `0x1b`. Enter is `\r`. An arrow key is `ESC [ A`. There is no interpretation layer deciding which keys are worth forwarding — from `useTerminalSession.js`:

```
## Esc gets no special handling, and that is the point
```

Esc mattering is not incidental. An agent at a prompt that cannot be interrupted is an agent you can only watch, and interrupting a coding agent is most of what supervising one consists of. Resize works too: the pane measures itself, tells the far end its new `cols` and `rows`, and the program on the other side reflows because it genuinely received `SIGWINCH`.

Under it is a deliberately boring binary protocol, documented in `daemon/wire`:

```
[ type:1 ][ sessionID:8 big-endian ][ payload... ]
```

PTY traffic is arbitrary bytes at volume, so it travels as bytes. Control messages — start, kill, attach, heartbeat — are JSON, because they are low-rate and worth reading in a log. The package that defines the format imports nothing outside the standard library, on purpose: the daemon and the backend are built from different modules, and a daemon already installed on somebody's build server is not upgradable on demand. Old daemons talking to new backends is the normal case, not the exception.

## What This Unlocks

**Your development environment is the thing agents actually need.** A hosted sandbox starts from nothing: no toolchain, no local database, no credentials, no checked-out repository sitting on the branch you were in the middle of. Every one of those has to be reconstructed before the agent can do anything, and the reconstruction is usually harder than the task. A machine you already work on has all of it, already configured, because you configured it. Enrolling it is how an agent inherits a working environment instead of being handed an empty one.

**Capacity you already own becomes capacity agents can use.** The interesting number on the machines page is free memory, and it is there because it answers a scheduling question you now get to make: this box has room, that one does not, start it over there. A spare machine that was doing nothing is an agent host. The screenshots in this post come from a Raspberry Pi with 4 GB of RAM running three agents at once — not a recommendation, just a demonstration that the floor is low.

**Watching is the half of delegation that was missing.** A task board tells you what an agent decided, after it decided. A terminal tells you what it is doing, while it does it, and — because the keyboard works — lets you do something about it. The gap between noticing an agent has misunderstood and being able to stop it used to be the length of a task. Now it is one keystroke.

**The machine stays put and you do not.** This is the one that surprised us in practice. The daemon runs on a computer that never moves; the viewport is a browser, and browsers are on phones. Watching a build box from a phone in another room is the same code path as watching it from the desk two feet away — there is no separate mobile story, because the terminal was never tied to the machine it displays. The first draft of this post was reviewed by somebody reading the agent's terminal on a phone, from bed.

## Enrolling Is a Grant, and It Says So

![The add-machine panel: install steps, and the warning before them](/assets/blog/machines-enrol.png)

The panel puts the consequence above the commands, in the last moment where stopping is easy:

**Enrolling lets anyone who can authenticate as that AgentRQ account run commands on it as the user who started the daemon. Compromise of the account is compromise of every enrolled machine.**

That is the whole trust model, and the [Daemon Guide](/docs/daemon) leads with it rather than burying it in a caveats section. An agent started on your machine can read every file you can read and use every credential in your home directory, because as far as the operating system is concerned it **is** you.

Enrolment is local-only — someone has to be at the machine to type the code — which is what makes it safe to display the code in a browser. Installing the daemon is one command:

```sh
curl -fsSL https://agentrq.com/install-agentrqd.sh | sh
```

We argued about that pipe, because it asks you to run unseen code on the machine you are about to grant command access to. It won on the strength of what it replaced: the manual route — download an archive, unpack it, copy a binary — verified nothing at all, and an install nobody finishes protects nobody. The script checks the download against the SHA-256 checksums published with the release before anything is unpacked, and that check is fail-closed with no flag to skip it. If it ever stops being fail-closed, the pipe should go.

Reading it first is still the better habit, and it is the same install:

```sh
curl -fsSL https://agentrq.com/install-agentrqd.sh -o install-agentrqd.sh
less install-agentrqd.sh
sh install-agentrqd.sh
```

It installs and nothing else — no enrolment, no service, nothing started, and never as root. Windows has no `sh`, so it keeps the manual steps.

## The Limits That Are Real, and the One That Is Not

Three constraints are enforced rather than advised.

**The daemon runs exactly two programs.** `claude-code` and `acp-gateway`, and nothing else. The control panel asks for a **kind** — one of those two names — and the daemon decides from its own configuration what that means. There is no protocol message that says "run this command", so a backend that has been taken over cannot ask a machine for `/bin/sh`. What it can do, once one of those two is running, is send it keystrokes; that is the feature, and an agent at a terminal can do whatever you could do at that terminal.

**It refuses to run as root.** Not a warning — a refusal. An agent inherits the daemon's powers, so the daemon declines to have more than yours.

**The kill switch does not need the server.** `agentrqd disable --profile <id>` deletes the token from disk and takes effect immediately, whatever the backend thinks is true. Removing the machine in the panel revokes it server-side and closes its connection. The two are independent on purpose: either alone is enough, and the local one works when you cannot reach the panel.

And one thing that looks like a boundary and is not. A machine can be enrolled with several accounts, each a separate **profile** with its own token and identity, shown separately in the panel. They are **not isolated from each other** — same OS user, same home directory, same files. The desktop app's profiles do isolate, which makes the assumption a reasonable one to make and a costly one to be wrong about. Two accounts needing real isolation means two machines, or two operating-system users.

## What Is Recorded, and What Is Deliberately Not

| Recorded on the server | Not recorded anywhere |
|---|---|
| An agent being started, and by whom | Keystrokes |
| An agent being killed | Terminal output |
| A browser attaching to a terminal, and detaching | |
| An update being approved, and to which version | |

Keystrokes are absent by choice, not oversight. What somebody types into a terminal is passwords, tokens, and the contents of files — recording it would build the most sensitive log in the system to answer a question nobody asked. That an attach happened, and when, is the fact worth keeping. Terminal output is relayed to whoever is watching and then forgotten.

The same question is answerable from the machine itself. `agentrqd status` reports what is running right now, which folder each agent is in, which profile asked for it, and whether anybody is attached to its terminal at this moment — without asking the account that might be doing the watching. A machine whose owner cannot find out what is driving it is not a machine anyone should enrol.

When two browsers watch one terminal, both are told: the header reads **Shared with** and names the other viewer. Two people on one terminal is allowed — it is how you show a colleague what is happening — but never implicit.

## Updates Stop Everything, and Say So First

The daemon checks for new releases and tells the panel. It never updates on its own initiative, because approving an update means: stop every agent on this machine, replace the daemon, start them again.

Those agents come back as **new terminals** — same agent, same folder, same settings, and no scrollback, no in-flight work, nothing half-typed. The panel marks them as restored so an empty terminal is explained rather than alarming. Restoring the sessions means restoring the intent, not the state, and there is no version of this that could mean otherwise. The button says so before you press it, and the confirmation says it again.

Before replacing anything the daemon checks the release manifest's signature against a key built into it, checks the download against the manifest's checksum, runs the new binary to confirm it works on this machine, and writes down what was running — and only then stops it. A build with no release key refuses to update itself and says so. `agentrqd rollback` puts the previous binary back, which is why the old one is kept.

## Getting Started

`agentrqd` is one static binary for Linux, macOS and Windows, on the [releases page](https://github.com/agentrq/agentrq/releases/latest). **Machines → Add machine** gives you a code and the platform-specific steps.

```sh
agentrqd enroll --server https://your-agentrq-server --code ABCD-EFGH
agentrqd serve
```

The release archive carries a systemd user unit and a macOS LaunchAgent for keeping it running after you log out. Both are user-level, not system services, for the same reason the daemon refuses root.

Read the [Daemon Guide](/docs/daemon) before you enrol anything. It is short, it is blunt about what enrolling costs you, and being clear-eyed about that is the difference between a useful feature and a regrettable one.
