Remote Executors

A remote executor is a Metnos executor that is not launched on the server, but on a registered device in the same household: a Windows PC, a Linux laptop, and later other systems. The server remains the decision point: it checks whether the action is allowed, signs the payload, receives the result and writes the audit trail.

Public status: W3.3 validated on a real Windows PC on 2026-07-03, client 0.2.7, with UI join, Job Object, timeout with process-tree kill, single-instance lock and revocation through 403. The extended design detail remains in the internal document internal/design/remote-executors.html.
On this page
  1. Core idea
  2. Device identity and pairing
  3. Placement: when an executor may leave the server
  4. Installation from the UI
  5. Per-OS sandboxing
  6. Failures, duplicates and revocation
  7. Declared limits

1. Core Idea

Metnos is designed as a household system: many data live on the server, but not all of them. A document may sit on a laptop, a work folder on a Windows PC, a screen or an application may exist only there. Remote executors bring a controlled part of the catalog to the place where the data actually live, without turning each machine into a second Metnos.

The asymmetry is deliberate: the device executes, but it does not decide. The server keeps policy, Vaglio, executor selection, signing, the device registry and audit. The remote client, metnos-client, polls the server, verifies the signature of the received job, runs it inside the containment available for its OS and returns a signed result.

2. Device Identity and Pairing

Each device has its own Ed25519 identity. Admission happens through a single-use code generated by the server: the client consumes it, registers the device public key and receives the server public key for pinning. From that point on the device is not "an open browser": it is a known, revocable and recognisable machine.

The detailed flow lives in pairing, ch. 13. The essential parts are: short token, one-time consume, unique device fingerprint, periodic heartbeat and explicit revocation from the admin panel.

3. Placement: When an Executor May Leave the Server

An executor does not become remote by accident. The loader reads its manifest: allowed platforms, capabilities, signature and optional placement section. Only when the contract is compatible may the runtime assign the job to a device. Otherwise the executor stays local or is refused with an honest error.

CheckWhy it matters
platformsPrevents sending to Windows an executor written only for Linux, or the reverse.
server signatureThe client runs only code that matches what the server signed.
capabilitiesPolicy and Vaglio stay server-side; the device does not widen permissions.
placementStates whether the job may stay on the server or requires a specific device.

3.1 Chat-driven placement: the server or one of your PCs

The table above tells you whether an executor may leave the server. The practical question remains: on which machine does a command you type in chat actually run? Metnos answers with no panels and no manual toggles — it works it out from the sentence itself. We call destination the machine where the next command will run: either the server (the .33 machine where Metnos lives) or one of the PCs you have paired, that is, registered once through the pairing flow. Each paired PC has a name you chose (for example OFFICE-LAPTOP) and belongs to a user: the server knows which devices are yours.

The conversation below shows a single chat whose destination changes turn after turn. On the right: the three steps by which Metnos decides where to run, the two guarantees, and a diagram of the server / PC fork.

Metnos · Roberto's chat
How many lines of code are in the project?
🖥 server (.33)
The project has 48,213 lines across 612 files.
first turn, no PC named → initial destination = server
List the Documents folder on my office-laptop
🔀 device OFFICE-LAPTOP recognised → routing there, and from now on it is the destination
💻 OFFICE-LAPTOP
On OFFICE-LAPTOP, in Documents:
invoices/ (folder) contracts/ (folder) notes.txt 4 KB budget.xlsx 88 KB
📍 destination now: OFFICE-LAPTOP
Zip it up
↳ no PC named → the last destination stays: OFFICE-LAPTOP
💻 OFFICE-LAPTOP
Done on the laptop: created Documents.zip (1.2 MB) next to the folder.
How much free space is there on home-desktop?
💻 HOME-DESKTOP · not connected
HOME-DESKTOP is not connected (no heartbeat for over a minute). I will not silently run elsewhere: switch it on and try again, or tell me “on the server” or “on office-laptop”.
connectivity check before every dispatch → honest error, never a silent fallback
How many processes are running, here on the server?
🔀 destination reset to server (.33)
🖥 server (.33)
The server is running 147 processes.
📍 destination now: server (.33)
A note on honest limits. The target PC is identified by its name, not by where the connection comes from. Identifying it from the network origin (the IP address) would be unreliable: through the public tunnel the server always sees 127.0.0.1, and from Telegram there is no PC behind the message at all. That is why the anchor is the device name — matched against the real names of your paired PCs — and not the network fingerprint. A name dropped mid-sentence, without a locative preposition to anchor it, does not move the destination.

4. Installation from the UI

The natural operational point is /admin/devices: the server shows registered devices and can issue a join link. If the user opens the UI directly on the server, there is nothing to install: local executors are already available. If the UI is instead running on a PC different from the server, the page can offer the installer for the current platform and show registration progress.

The click does not give special privileges to the browser: on Windows it downloads MetnosClientSetup.cmd, which installs and starts metnos-client as a persistent operating-system process. The UI observes the join: token issued, client registered, heartbeat alive, client version, last error.

5. Per-OS Sandboxing

On the Linux server the canonical sandbox is bwrap. On a remote device containment is chosen by the client according to the operating system, but the interface is single: run this payload with these limits and return stdout, stderr, exit code, timeout and containment metadata.

SystemCurrent containmentNote
LinuxClient-side bwrap when availableStrong filesystem and network isolation, consistent with the server model.
WindowsJob Object + process limitsUseful for timeout and process-tree kill; not yet full filesystem/network isolation.
macOSPlanned backendEnabled only once containment has been verified.

See sandbox, ch. 10 for the per-OS detail and for why Windows AppContainer remains the next hardening step.

6. Failures, Duplicates and Revocation

The channel is built for an imperfect home network. The client polls, so it does not require open ports on the PC. Each invocation has idempotency and a deadline: if the network drops, the server can distinguish between a job not yet picked up, a job in progress and a result already delivered. If a client is stuck, the local lock prevents a second concurrent instance; if a job exceeds its timeout, the client kills the process tree. Since client 0.2.7, heartbeat runs in a separate task, so the device remains observable even while it is preparing its own execution environment.

Revocation is server-side: the revoked device gets an error on polling or heartbeat and stops receiving work. The server does not need to trust that the old client will behave well: it simply stops assigning payloads to it.

7. Declared Limits

Remote executors do not mean "run arbitrary code on the PC". They mean: run only signed executors, compatible with the platform, admitted by policy and sufficiently contained by the client. Mutating or unaudited executors stay out of the remote path until their containment is explicit.