Skip to content

Register a node

Agents run on nodes — remote Linux machines running the Halyard daemon. You can bring your own hardware: a laptop, a server, or a VM.

The daemon opens a single persistent outbound WebSocket to the Halyard control plane and keeps it open. There is no inbound network surface on the node — nothing listens for connections, and there is no broker in between. Over that one connection the node:

  • registers itself and advertises its capacity;
  • heartbeats so the control plane knows it is healthy;
  • receives dispatches and streams live output back.

If a node goes offline, its sessions stay queued; the control plane dispatches them the moment the node reconnects and reports capacity — durable-queue behavior without a queue to operate. A node that stops heartbeating past the timeout is marked offline and its in-flight sessions are unstuck.

Once the binary is on the machine, a single command sets everything up:

Terminal window
sudo halyard-node install \
--control-url <url> --bootstrap-token <token>

That copies the binary to /usr/local/bin/halyard-node, creates /opt/halyard, registers a systemd service (launches the daemon on boot, restarts it if it exits), enrolls the node, and starts it — so it reports online within seconds. After a reboot or a transient failure it recovers on its own, no manual restart. Manage it like any service: systemctl start|stop|status halyard-node, and read its logs with journalctl -u halyard-node.

The daemon is semantically versioned. To upgrade, download the latest binary and re-run install — it detects the version already installed, replaces it in place, and restarts the service:

Terminal window
curl -fsSL <binary-url> -o halyard-node && chmod +x halyard-node
sudo ./halyard-node install

It prints what it’s doing — for example upgrading halyard-node 0.1.0 → 0.2.0 — and keeps the node’s existing identity, so no re-enrollment is needed. Re-running the same version is a harmless no-op. Check the running version any time with halyard-node version (or systemctl status halyard-node).

Prefer two steps? Run sudo halyard-node install on its own to set up the service without enrolling — it then waits, harmlessly retrying, until you run halyard-node enroll --control-url <url> --bootstrap-token <token> separately. No sudo on that second command: install already handed /opt/halyard to your account.

Re-installing or re-enrolling? If this machine was enrolled before — you deleted the node in the app and want to register it again, say — its old identity is still on disk. Re-run install with a new bootstrap token and it notices the existing enrollment and asks before overwriting it:

Terminal window
sudo halyard-node install \
--control-url <url> --bootstrap-token <new-token>
# This node is already enrolled (node_id=…). Overwrite it and re-enroll
# with the new token? … [y/N]

Answer y to discard the old identity and enroll fresh; anything else keeps the existing one untouched. For an unattended overwrite (scripts, config management — where there’s no terminal to answer the prompt), pass --force to skip the confirmation:

Terminal window
sudo halyard-node install \
--control-url <url> --bootstrap-token <new-token> --force

Without a new token, a plain re-run always keeps the existing identity, so upgrading the daemon never disturbs a live enrollment.

Agent CLIs such as claude often live in your ~/.local/bin. The installed service puts that directory on its PATH so the daemon can find them; if you install the CLI somewhere unusual, adjust the unit’s Environment=PATH= line.

A node belongs to an enclave. Sessions are only ever scheduled onto nodes within the project’s enclave, so an agent working a public repo can never land on a machine that holds corporate credentials.

Each session chooses how its workspace is set up on the node:

  • Host directory — the agent works directly in an existing directory on the machine, reusing already-configured toolchains and build state.
  • Containerized — the node provisions an ephemeral environment from a Dockerfile or Docker Compose, mounts the cloned repository, and tears it down when the session ends.

Bring nodes online and offline and watch their health and capacity under Nodes in the app. Once a node is online in your project’s enclave, you can dispatch an agent onto it.