kolu
Docs

tutorial

Across the hosts.

So far fleet-top has watched your machine. Now we reach one running on another box, over ssh, and show its top in your browser — using the exact same surface. The trick is a mirror: the remote box serves the surface, a local parent folds its frames into a local copy of the same surface and re-serves that, and the browser only ever talks to the local copy. Swap the box behind it and the browser never notices.

The agent — what runs on the far box

The remote side is tiny: it serves the same top surface over stdin/stdout. This is what the parent runs on each target — ssh <host> fleet-top-agent --stdio for a remote box, the realised binary directly for localhost. It is ephemeral — a fresh one per link — which is the right shape for a re-run-fresh reader like top.

/**
 * fleet-top-agent — serve the `top` surface over stdin/stdout.
 *
 * This is what `ssh <host> fleet-top-agent --stdio` runs on the far box. The
 * agent is ephemeral (a fresh one per link — `serveOverStdio` makes THIS
 * process be the server, so it's gone when the link drops); the parent's
 * `makeSession` re-spawns it on reconnect. That's the right shape for a
 * re-run-fresh reader like `top`.
 *
 * **Stdout is the protocol channel** — every diagnostic goes to fd 2. A stray
 * write to fd 1 corrupts the next frame.
 */

import { serveOverStdio } from "@kolu/surface/peer-server";
import { createTop } from "./top";

function log(line: string): void {
  process.stderr.write(`fleet-top-agent: ${line}\n`);
}

async function main(): Promise<void> {
  if (!process.argv.slice(2).includes("--stdio")) {
    process.stderr.write("usage: fleet-top-agent --stdio\n");
    process.exit(1);
  }
  const top = createTop();
  top.start();
  log(`serving top over stdio (pid ${process.pid})`);
  const end = await serveOverStdio({
    router: top.router,
    onFirstRequest: () => log("first RPC received — link is live"),
  });
  top.dispose();
  log(`stdin closed (${end.reason}) — agent exiting`);
}

main().catch((err) => {
  log(`fatal: ${(err as Error).message}`);
  process.exit(1);
});

The three-hop mirror

On the parent, each host is one binding. First, dial it — makeSession({ connectOnce: sshConnector(...) }) provisions the agent closure onto the box and runs it (over ssh for a remote host, directly for localhost), reconnecting on drop.

const session: Session<
  AgentClient<typeof surface.contract>,
  SshProv
> = makeSession({
  initialConnection: "probing",
  connectOnce: sshConnector<typeof surface.contract>({
    host,
    binary: "fleet-top-agent",
    // Constant resolver — this demo takes the agent .drv from the environment.
    // A consumer that picks the .drv per host's nix-system passes an async
    // `resolveSystem(host)` probe here instead.
    resolveDrvPath: () => Promise.resolve(agentDrv),
  }),
  label: `host:${host}`,
});

Then pump the agent’s frames inward, folding each into a local implementSurface of the same surface. The local copy is what browser subscribers read; makeSink writes the incoming frames through its ctx.

let firstLoad = true;
void pumpRemoteSurface({
  source: surface,
  session,
  makeSink: () => {
    firstLoad = true;
    return {
      cells: {
        load: (v) => {
          if (firstLoad) {
            firstLoad = false;
            session.markConnected();
          }
          fragment.ctx.cells.load.set(v);
        },
        memory: (v) => fragment.ctx.cells.memory.set(v),
      },
      collections: {
        processes: {
          upsert: (k, v) => fragment.ctx.collections.processes.upsert(k, v),
          remove: (k) => fragment.ctx.collections.processes.remove(k),
        },
      },
    };
  },
});

Finally re-serve: a directLink over the local fragment’s flattened router is the link the browser reaches. Three hops — dial, pump, re-serve — and the surface that started on another machine now serves from this process.

Watch it arrive

  1. Point the parent at one host and start it. HOST is the target (localhost here — no ssh needed); FLEET_TOP_AGENT_DRV is the agent’s flake output, resolved in place.

    # resolve the agent .drv (works from anywhere in the repo):
    export FLEET_TOP_AGENT_DRV="$(nix eval --raw "$(git rev-parse --show-toplevel)#fleet-top-agent.drvPath")"
    
    HOST=localhost pnpm run dev
    fleet-top part 3 serving 1 host(s) on http://localhost:7740
  2. Open http://localhost:5176. The header chip shows the host warming while the agent closure is realised, then flips to connected — and the same live top you built in part 1 fills in, this time streaming from the agent the parent stood up (on localhost, directly; on a remote box, over ssh).

You changed nothing about the surface or the browser code. The box could be a laptop across the room; the mirror makes it read like local state.

Next

One box is a mirror. Many boxes is a map. In A fleet of surfaces you gather N hosts into one keyed surface, render them as chips, and watch a single box’s trouble stay confined to its own chip — the moment fleet-top becomes a mini-drishti.