Text

Two Machines, One Thread

Written by Gustama Dimas

I have two machines that matter.

msi-server is the newer one — a small MSI Cubi 5 running Ubuntu Server, and the box my assistant gateway lives on. .185 is the older desktop, still doing useful work, still holding a few things I haven't got round to migrating.

For a long time the only channel between them was me. I'd notice something on one machine, walk over to the other, and retype it. That works fine right up until it doesn't.

So I built a relay. Not a clever one — two one-way pipes.

Pipe one: .185 → me

A small script on .185 posts a message to an HTTPS endpoint on the gateway. It's token-authenticated, restricted to a single agent, and delivered to my phone labelled 📡 .185 so I always know which machine is speaking.

The important part is what it doesn't do. Nothing on .185 listens for inbound connections for this. The machine only ever makes outbound requests. No new port, no new attack surface.

Pipe two: me → .185

This is the interesting half, because the obvious design is wrong.

The mirror-image approach would be an HTTP endpoint on .185 that I post to. I rejected it. That machine has a history: a gateway process that occasionally hangs, and an agent database that has grown large enough to overflow its context window under real work. Adding a new always-listening inbound surface to a box with those properties is how you end up with a service that dies at 3am and leaves no trace of why.

Instead I reused something already trusted and already tested: SSH.

The flow is one command:

  1. I decide to send something to .185
  2. A script on msi-server opens an SSH connection
  3. It runs the agent CLI there against a fixed session key
  4. The agent's reply comes back on stdout
  5. I relay that into the chat thread

One round trip. No new port open anywhere.

What it looks like when it works

Four tests, all end to end:

transport smoke     → PONG-185-FASE2
simple message      → FASE2-V2-OK
tool use on .185    → returned hostname, uptime, version
final               → FASE2-FINAL-OK

The third one is the one that mattered. It didn't just prove the pipe carried text — it proved that a request originating on one machine could reach the other, cause it to run a shell command there, and bring the real output back. That's the difference between a notification and a remote control.

The limitation, stated honestly

The relay is synchronous. A request waits for a reply, and the timeout is 300 seconds by default. For chat and short queries that's generous. For anything heavy — a ten-minute build, a long coding task — it will time out, and the work gets orphaned.

The fix is an async variant: fire the request, get an acknowledgement, deliver the result when it's ready. I haven't built it, because nothing yet needs it. Writing it now would be writing code for a problem I don't have.

What I'd take from this

The best interface between two machines is usually the one that's already there.

SSH was already trusted, already keyed, already understood. An HTTP endpoint would have been more modern and less reliable. The question isn't "what's the correct way to do this" — it's "what's the smallest new thing I can add to make this work."

Here the answer turned out to be: nothing, on the receiving end. Just a script and a key that already existed.