Remote ports
A dev server running on a runner can be opened in the browser on your own machine. Strado forwards the port through the same tunnel the runner already holds open.
How it reaches you
Your machine binds a listener on loopback and pipes it to the runner's port
through the relay. Nothing on either machine is exposed to the network: the
listener is 127.0.0.1 only, and the runner still opens no inbound port.
Heads up
The local port is not the remote port. The forwarder always takes an
arbitrary free port on your machine, so a dev server on the runner's 8080
might arrive at localhost:59022. Strado tells you which one — do not assume
the numbers match. This is deliberate: the remote port is never claimed
locally, so a runner's dev server can never collide with your own.
The forwarding runs in its own process rather than inside the server that enumerates your worktrees, so a heavy page load cannot slow the rest of the app down.
What the runner will let through
Not every port. A runner only forwards ports it can account for: the ports its
own worktrees are configured to use, its repos' default ports, and anything the
operator has opted into by hand in ~/.strado/runner.env.
That is defence in depth rather than a security boundary — anyone who can open a forward already has a shell on the box through the same tunnel — but it means a bug or a stolen ticket cannot turn into an enumeration of the runner's loopback, and a refusal in the log means something.
Latency, honestly
Note
Measured on one setup — a Mac and a runner on the same LAN, with the relay in Mumbai. Treat these as the shape of the problem, not a guarantee.
| Measure | Result |
|---|---|
| Median per request | ~170 ms |
| Bulk transfer | 5 MB in 1.67 s, about 3.1 MB/s |
| Terminal round trip | 64 ms median |
Bulk transfer is fine. Request count is what hurts. At ~170 ms each, a cold page making 200 requests costs roughly 34 seconds serialised, or about 6 across a browser's usual six connections. A page that is already loaded, doing hot module reloads of a few small messages, feels fine.
The reason is the route rather than the distance: every request goes from your machine to the relay and back down the runner's tunnel, even when the runner is five milliseconds away on your own LAN.
When the runner goes away
Connections reset immediately rather than hanging, and the mapping is kept and marked unreachable rather than deleted. When the runner comes back, the forward resumes on the same local port — measured at about five seconds — so a browser tab you left open keeps working instead of pointing at nothing.