Ovvi
Agent control

Remote machines

How an agent on a remote machine reaches the Ovvi on a Mac, how the command gets there, how long a call takes, and what differs

An agent on a remote machine runs the same ovvi command, with the same answers, as an agent on This Mac (Agent control). Everything the agent touches is on its own machine: the script, the mailbox and herdr. Ovvi already holds the link to that machine: one SSH session through the relay, which carries the event stream and every run (The SSH connection).

The flow

remote machine (devbox)                                   the Mac
──────────────────────────────────────────────            ─────────────────────────────
agent in pane w1:p2
  │ 1. ~/.cache/ovvi/bin/ovvi open git /srv/app uncommitted
  │ 2. writes ~/.cache/ovvi/rpc/<id>.req
  │ 3. herdr pane report-metadata w1:p2 ovvi-req=<id>
  ▼
herdr server ── pane.updated (tokens) ── events stream ── ssh forward ──► Ovvi (HostStore of devbox/default)
                                                                     │ 4. run: mv <id>.req <id>.run; base64
~/.cache/ovvi/rpc/<id>.run   ◄──────────────────────────── relay ────┘
                                                                     │ 5. herdr calls (layout.apply, tab.move…)
herdr server  ◄──────────────────── API socket ── ssh forward ───────┤    the card shows in the window
                                                                     │ 6. run: write <id>.out, <id>.exit
~/.cache/ovvi/rpc/<id>.exit  ◄──────────────────────────── relay ────┘
  │ 7. the script prints <id>.out, exits with the code
  ▼
agent reads the answer

On This Mac the same steps run with a Process for each run in place of the relay.

How the command gets there

When a store opens a session on a machine, one run (over the relay on a remote machine) makes the folders, removes mailbox files older than 60 minutes and reads the script's version:

d=$HOME/.cache/ovvi; mkdir -p "$d/bin" "$d/rpc" && chmod 700 "$d/rpc" &&
find "$d/rpc" -type f -mmin +60 -exec rm -f {} + ; sed -n 2p "$d/bin/ovvi" 2>/dev/null
  • If that line is missing, or its # ovvi-cli ‹protocol›.‹revision› is lower than Ovvi's own script's, a second run writes the script: base64 on standard input, to a temporary name, mode 0755, then mv. Ovvi never writes over a script of the same or a higher version (Versions).
  • Nothing else is installed. The script needs sh and POSIX tools. The relay needs Perl, the script does not.
  • $HOME is the machine's home: the login user's, the same user herdr runs as.

Timing

ovvi info, typed in a pane, to its exit:

WhereBestMedianWorst
This Mac (10 calls, a busy Mac at load average 130 to 200)0.34 s0.47 s0.69 s
CI's virtual Mac0.23 s0.5 s1.55 s
A remote machine over SSH on localhost (CI's sshd)0.18 s0.36 s0.48 s
  • A remote machine is faster than This Mac, because the relay is one long-lived process, while This Mac starts a Process for the take and another for the answer. Over a real network, each of the take and the answer adds one round trip, and the event adds half of one.
  • The script's own processes (the ring, and date and sleep in each 50 ms look) cost the rest.
  • ovvi status takes about 0.18 s: two herdr calls on the machine.
  • With no Ovvi, the command exits 3 after 2.4 to 3.0 s.

The take wait is 3 s and the answer wait 10 s, enough for a slow link. A caller that wants a fast "no" reads ovvi status first, which never leaves the machine.

What differs on a remote machine

  • Paths are the machine's. ovvi open ./notes.md opens the remote file, through the card's Exec, as every plugin card on that machine does.
  • localhost in a browser card is the machine's, through the SOCKS proxy (Remote localhost). A path for the browser, or a file:// URL for any kind, opens only on This Mac: from a remote pane it is bad_argument.
  • Plugins live on the Mac. ovvi plugins lists them, without log. plugins new, reload and install are other_machine.
  • remote in ovvi status is true, so the agent knows its own pbcopy does not reach the Mac. ovvi copy does.
  • The link drops (sleep, a network change): the event stream ends, and Ovvi opens it again as it does for every session. The snapshot read then takes a ring whose token still lives (3 s). A request after that is not replayed: the command exited 3.
  • Another session on the machine (ovvi float pi-herd/w1:p1) works while herdr runs it there. Ovvi opens the other session for the float, on a float-only page, as ovvi://float does with &machine=.
  • Two Macs on one machine: each has its own SSH link and stream. Both hear the ring, and the mv on the machine picks one (Two Ovvis).
  • A machine no Ovvi connects to keeps the script it has, or none.

Why not a forwarded socket

A socket of Ovvi's own on the Mac, reached from the machine by ssh -R /path/ovvi.sock:…, would give a plain request and reply. Ovvi does not use one:

  • Ovvi's SSH link runs with ClearAllForwardings=yes and no agent forwarding, so that a machine cannot reach the Mac through the app's long-lived link. A reverse forward opens exactly that door, to every process of the user on the machine.
  • Two Macs on one machine need two socket paths, and the command must pick one. herdr's tokens reach every Ovvi that follows the session, and the mv picks one.
  • The relay and the event stream already carry everything the bus needs.

On this page