How to Add a Remote Node to AxiOwl

A remote node in AxiOwl is a Linux machine that the Windows AxiOwl coordinator can reach over SSH and use as a remote Codex delivery endpoint. The important part is not just that the host exists. AxiOwl needs a registered node row, a verified SSH path, a Linux-side axiowl installation, and at least one registered remote target that maps an AxiOwl agent name to something sendable on that node.

The current C++ implementation makes this split explicit. The Windows build is the local coordinator and registry owner. The Linux remote build is intentionally narrower: it acts as a remote Codex endpoint and relay-session receiver. It does not provide VS Code, Antigravity, desktop IPC, tray behavior, GUI behavior, or remote relay chaining on the Linux side.

That narrow contract is useful. A remote node is not a magic mirrored desktop. It is a known SSH destination that can run axiowl relay-session --stdio and delegate delivery to the remote machine's local Codex-capable AxiOwl setup.

What AxiOwl Stores for a Remote Node

AxiOwl keeps remote node records in its node registry. In the current code, the node table is a TSV file named nodes.tsv under the AxiOwl state directory:

%LOCALAPPDATA%\AxiOwl\registry\nodes.tsv

On Linux, the state root is $XDG_STATE_HOME/axiowl when XDG_STATE_HOME is set, otherwise ~/.axiowl.

Each node row has the fields AxiOwl needs for routing and verification:

node_id
display_name
aliases
host
ssh_user
ssh_key_path
enabled
last_seen_at
last_verified_at
last_error

The practical minimum is a stable node ID, host, SSH user, and optionally a key path. The key path may be omitted when the normal SSH environment can already authenticate non-interactively.

Prerequisites

Before adding the node, make sure the Windows coordinator can reach the Linux host with OpenSSH. AxiOwl's verification and remote relay paths use ssh with BatchMode=yes, so password prompts are not part of the intended flow.

From the Windows machine, a healthy SSH check looks like this:

ssh -i C:\path\to\key.pem user@example-host "hostname; whoami; pwd; hostname -I"

The command should return the remote hostname, user, working directory, and IP addresses without prompting for a password. That is the same identity probe shape AxiOwl uses during node verify.

The remote Linux host also needs the remote AxiOwl package installed. The current remote installer expects a payload containing:

bin/axiowl
plugins/axiowl-codex/.codex-plugin/plugin.json
plugins/axiowl-codex/.mcp.json
installer/install-axiowl-remote-linux.sh

On the Linux node, the installer places the axiowl binary at:

/usr/local/bin/axiowl

It verifies the installed binary reports:

axiowl 0.1.0

It also installs the bundled Codex plugin payload under the user's local AxiOwl Codex area, writes a Codex plugin marketplace entry, runs codex plugin marketplace add, runs codex plugin add axiowl-codex@axiowl, and checks that the AxiOwl MCP server exposes axiowl_send_message.

Add the Node

Use axiowl node add from the Windows coordinator:

axiowl node add --id "front" --host "example-host-or-ip" --ssh-user "ubuntu" --key "C:\path\to\key.pem" --name "Frontend Linux"

The --key option is optional when your SSH configuration already works without an explicit key path. You can also add an alias:

axiowl node add --id "front" --host "example-host-or-ip" --ssh-user "ubuntu" --key "C:\path\to\key.pem" --name "Frontend Linux" --alias "frontend"

There is also a lower-level registry form:

axiowl registry add-node --id "front" --host "example-host-or-ip" --user "ubuntu" --key "C:\path\to\key.pem" --name "Frontend Linux"

For ordinary operator use, node add is clearer because it matches the node-specific command group and accepts --ssh-user.

Verify the Node

After adding the node, verify it:

axiowl node verify --id "front"

The current implementation loads the row from nodes.tsv, builds an SSH command with BatchMode=yes and ConnectTimeout=10, adds -i <key> when a key path is configured, and runs this command on the remote host:

hostname; whoami; pwd; hostname -I

If the SSH command succeeds, AxiOwl records last_verified_at and clears last_error. If it fails, AxiOwl records a last error like an SSH verification failure with the exit code and prints the captured SSH output.

You can inspect registered nodes with:

axiowl node list

That command prints each node ID with its host, SSH user, enabled state, last verification timestamp when present, and last error when present.

Register a Remote Agent Target

Adding a node tells AxiOwl how to reach a machine. It does not by itself create a sendable agent target. A target is still an agent registry row.

The current documented remote setup uses a remote provider row whose node points at the node ID:

axiowl registry add-agent --name "Remote Test" --provider remote --node "front" --session "Remote Agent Name"

Then send through the normal AxiOwl send command:

axiowl send --to "Remote Test" --body "hello"

For a remote provider row, the --session value is the remote target name stored as the provider session ID. The Windows remote provider looks up the node from nodes.tsv, opens an SSH command to that node, and runs:

axiowl relay-session --stdio

It sends JSONL relay frames over standard input. The remote relay process responds with JSONL frames, including a deliver_result frame that reports whether the remote side accepted the message, what provider handled it, and any error detail.

What Happens During Remote Delivery

Remote delivery is deliberately plain. The Windows coordinator writes a temporary JSONL input file containing a hello frame and a deliver frame. The deliver frame carries the target, final visible body, strict flag, and sender identity fields when AxiOwl has resolved them.

The Windows side then runs SSH to the target node:

ssh ... user@host "axiowl relay-session --stdio"

On the Linux side, relay-session --stdio reads each JSON line. If the frame is a delivery request with a direct provider and provider session ID, it calls the local delivery worker path. Otherwise it routes the request through the local message pipeline and registry on that Linux node. The remote process emits a structured deliver_result line back to the Windows coordinator.

This design keeps the remote boundary inspectable. SSH is the transport, standard input and output are the relay channel, and the local node registry remains the routing source of truth.

Installer-Assisted Remote Enrollment

The Windows MSI line also contains remote-node automation. The installer helper can collect remote node candidates from packaged remote-node configuration, local configuration, and existing node registry rows. It verifies candidates over SSH, enrolls them with axiowl node add, verifies them again with axiowl node verify, archives the remote payload, copies it to the Linux host with scp, extracts it under /tmp, runs install-axiowl-remote-linux.sh, and cleans up the temporary remote staging directory.

The packaged remote-nodes.json in the source tree currently contains an empty array, so an operator should not assume the default package already knows their infrastructure. The durable behavior to rely on is the explicit node registry: add the node, verify it, deploy the Linux remote payload when needed, and register the remote agent target.

Current Boundaries to Remember

The current remote Linux app is Codex-oriented. The Linux remote installer requires codex, installs the AxiOwl Codex plugin, and verifies the MCP tool list. Source comments and provider implementations are explicit that Linux remote AxiOwl intentionally supports Codex CLI delivery only.

That means a remote node is the right tool when you want the Windows coordinator to route work to a known Linux Codex endpoint over SSH. It is not the right abstraction for turning a Linux host into a remote VS Code desktop, Antigravity endpoint, GUI tray app, or another relay hub.

A Practical Checklist

Use this sequence when bringing up a new remote node:

  1. Confirm Windows can SSH to the Linux host without a password prompt.
  2. Install or deploy the Linux remote AxiOwl payload so /usr/local/bin/axiowl exists.
  3. Confirm the remote binary reports axiowl 0.1.0.
  4. Confirm the remote Codex plugin installation exposes axiowl_send_message.
  5. Add the node with axiowl node add.
  6. Run axiowl node verify --id <node-id>.
  7. Register at least one remote agent row with axiowl registry add-agent --provider remote --node <node-id>.
  8. Send a small test message with axiowl send.

If a send fails, check the node verification output first. Most remote-node failures are easier to reason about when separated into three layers: SSH reachability, Linux-side AxiOwl/Codex installation, and the agent registry row that maps a friendly AxiOwl name to the remote target.

Closing

AxiOwl remote nodes are intentionally boring infrastructure. A node row names the machine. SSH proves reachability. The Linux remote package provides a Codex-capable AxiOwl endpoint. The agent registry decides which named targets are sendable. That combination gives AxiOwl a concrete way to route from a local Windows coordinator to a remote Linux Codex environment without pretending the remote host is the same thing as the local desktop.