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.
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.
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.
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.
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.
| Check | Why it matters |
|---|---|
platforms | Prevents sending to Windows an executor written only for Linux, or the reverse. |
| server signature | The client runs only code that matches what the server signed. |
| capabilities | Policy and Vaglio stay server-side; the device does not widen permissions. |
| placement | States whether the job may stay on the server or requires a specific device. |
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.
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.
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.
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.
| System | Current containment | Note |
|---|---|---|
| Linux | Client-side bwrap when available | Strong filesystem and network isolation, consistent with the server model. |
| Windows | Job Object + process limits | Useful for timeout and process-tree kill; not yet full filesystem/network isolation. |
| macOS | Planned backend | Enabled 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.
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.