
Using AxiOwl to Manage a Remote Server
Remote server work is usually split between two worlds: the local machine where the operator is thinking and the Linux host where the work needs to happen. AxiOwl's current remote-server path is built around making that boundary explicit. The local AxiOwl runtime keeps node records, verifies SSH reachability, and can delegate message delivery to a remote AxiOwl process through a small relay protocol.
That matters because a remote server is not just another chat window. It has its own filesystem, shell, identity, provider sessions, and failure modes. AxiOwl treats that difference as product state instead of hiding it behind a vague "remote" label.
The Remote Node Is A First-Class Record
In the current C++ implementation, remote servers are represented by NodeRecord entries. A node record stores a stable node_id, display name, aliases, host, SSH user, optional SSH key path, enabled state, last seen time, last verified time, and last error.
The CLI exposes that model directly:
axiowl node add --id <node-id> --host <host> --ssh-user <ssh-user> [--key <ssh-key-path>] [--name <display-name>] [--alias <alias>]
axiowl node list
axiowl node verify --id <node-id>
There is also a compatibility-style registry command for adding a node:
axiowl registry add-node --id <node-id> --host <host> --user <ssh-user> [--key <ssh-key-path>] [--name <display-name>]
The important detail is that AxiOwl does not treat a hostname as enough. The node has to be registered, and the remote delivery path later checks that the target agent's node_id matches a node in the local node registry. If the node is missing, if the host is empty, or if the SSH user is empty, the remote provider path fails with a clear error instead of guessing.
Verification Uses The Same Kind Of Identity Check Operators Use
axiowl node verify --id <node-id> builds an SSH command with batch mode and a connection timeout. When a key path is present, it passes that key with -i. The remote command it runs is intentionally simple:
hostname; whoami; pwd; hostname -I
That output is useful because it answers the basic operational questions before any higher-level relay is trusted: which host answered, which account ran the command, what working directory was used, and which IP addresses the host reports. On success, AxiOwl updates last_verified_at and clears last_error. On failure, it stores a specific SSH failure message against the node record.
This is a small feature, but it is exactly the kind of feature that keeps remote automation understandable. Before a local agent asks a remote server to do anything important, the operator can confirm that AxiOwl is pointed at the intended box.
Remote Delivery Is An SSH Relay, Not A Public Service
The current remote provider implementation delegates over SSH. On Windows, provider_remote.cpp prepares a temporary JSONL relay input file and runs:
ssh ... <user>@<host> "axiowl relay-session --stdio"
The remote side runs axiowl relay-session --stdio, which reads line-delimited frames from standard input and writes line-delimited results to standard output. The protocol includes a hello frame and a deliver frame. A deliver frame includes the request id, target, final visible body, strict flag, sender resolution fields, and optionally a direct local provider target for the remote machine.
This design keeps the remote manager surface narrow. AxiOwl does not require opening a custom public manager port on the remote server. The local process uses the operator's existing SSH route, the remote process receives one relay session on stdio, and the result comes back through the same SSH command.
What Happens When A Message Is Sent To A Remote Target
A remote target is still an AxiOwl agent registry row. The local row uses provider remote, a node_id for the destination server, and a provider_session_id that identifies the remote target. The delivery code validates those pieces before making the SSH call.
The remote relay has two useful delivery modes.
First, it can hand the message to the normal remote MessagePipeline by target name. In that case, the remote AxiOwl process resolves the target from its own local registry and dispatches through its own provider edges.
Second, if the local target row encodes a direct remote provider and provider session id, the relay can build a direct provider request on the remote host. The parser recognizes direct targets for providers such as codex, vscode_native, vscode_copilot_backed, and antigravity. That lets the local runtime preserve the distinction between "send to this named remote agent" and "send to this specific provider session on that node."
In both cases, the remote side returns a deliver_result frame containing whether the provider accepted the message, the message id, state, target, provider, error, and method detail. The local side records evidence such as the remote request id, remote message id, remote provider, and remote detail.
Replies Can Flow Back Upstream
Remote delivery is not only a one-way SSH command. The relay can emit upstream_message frames while it is processing a remote delivery. When the local provider receives one of those frames, it turns it into a local MessageRequest and runs it through the local MessagePipeline.
That is how AxiOwl preserves the same routing idea across machines: a remote provider can send a message back toward the original local sender without asking the remote agent to invent a shell command or manually know the local registry layout.
The MCP server reinforces the same rule. Its axiowl_send_message tool uses the host MCP session id as the stable sender identity key. The tool description explicitly says that a successful MCP call is an AxiOwl handoff receipt only; provider delivery and provider reply are not implied. That distinction is important for remote work because "SSH command completed" and "the remote provider actually handled the message" are different facts.
Installing The Remote Linux Side
The repository's apps/linux-remote directory is currently reserved for the Linux remote node package. The active remote Linux installer payload still lives under the Windows desktop installer tree because it is packaged by the Windows installer flow.
The remote installer script, install-axiowl-remote-linux.sh, expects a payload directory. It checks for required commands, installs the axiowl binary to /usr/local/bin/axiowl, verifies the binary reports axiowl 0.1.0, installs the Codex plugin payload under a user-local AxiOwl Codex directory, writes a .mcp.json that runs:
/usr/local/bin/axiowl mcp-server --host codex --provider codex
It then registers a local Codex plugin marketplace, installs axiowl-codex@axiowl through Codex, lists plugins to confirm it is installed, and probes the MCP server to verify that axiowl_send_message is exposed.
Those checks are practical. For a remote server to be manageable through AxiOwl, it is not enough for a binary to exist on disk. The remote side also needs the Codex-facing MCP entry to expose the tool that lets a remote Codex session send back through AxiOwl.
Current Guardrails And Limits
The current source is explicit about remote scope. The CLI usage includes node commands and relay-session --stdio, and the remote provider code is wired for Windows-to-remote relay. At the same time, axiowl discover remote currently returns an out-of-scope report in the local-provider remediation build, and discover all explicitly excludes remote discovery.
The Linux remote side also has intentional limits. Several non-Codex provider implementations return errors on Linux remote builds with evidence that the Linux remote AxiOwl app intentionally supports Codex CLI delivery only. That is not a failure to hide; it is an operator boundary. Remote server management should start from the provider path that is actually installed and verified on that server.
This is the right shape for a remote feature that touches real machines. Node registration, SSH verification, relay delivery, and MCP tool proof are concrete. Broad automatic remote discovery and unsupported provider chaining are held back unless the implementation can make them observable and reliable.
A Practical Remote Workflow
A practical operator flow looks like this:
- Install AxiOwl on the remote Linux server with the remote payload installer.
- Confirm
/usr/local/bin/axiowl --versionreports the expected version. - Confirm the Codex plugin is installed and that the remote MCP server exposes
axiowl_send_message. - On the local machine, add the remote node with
axiowl node add. - Run
axiowl node verify --id <node-id>and check the returned host identity. - Add or discover the relevant remote agent registry row using the provider and session facts that are actually valid for that remote node.
- Send through the normal AxiOwl message path and inspect the handoff receipt, provider result, and any upstream reply.
That workflow is intentionally boring. It gives each layer one job: SSH proves reachability, the node registry stores the destination, the relay carries one structured delivery request, the remote AxiOwl process dispatches to its local provider, and the receipt states what was actually accepted.
Why This Helps With Server Operations
Remote server management often fails when tools blur local and remote context. A command that works locally may not exist remotely. A provider session discovered on one machine may not be present on another. A friendly agent name may refer to a different session on a different node.
AxiOwl's current remote model makes those boundaries inspectable. The registry stores node_id. The node list stores host and SSH user. Verification records the last known SSH result. Remote delivery evidence records the remote request id and remote provider detail. The relay has a protocol version and clear error frames.
For developers and operators, that means remote work can be coordinated without pretending all agents live in one flat namespace. AxiOwl can manage a remote server because it treats the server as a real node with its own identity, its own AxiOwl process, and its own provider sessions.
The result is a remote management path that is grounded in normal operational primitives: SSH, local binaries, MCP tools, registry records, and explicit receipts. That is the useful part. AxiOwl does not need a remote server to become a black box; it needs the remote server to become a named, verified participant in the same message system.