Local-first routing
The dashboard probes 127.0.0.1:33120 first on every API call. If reachable, the request goes loopback (~0.3ms round-trip). If not, it falls back to the Firebase-gated tunnel at <machine>.tunnel.ujex.dev.
Why it matters for terminals
A PTY pushes a byte for every keystroke. Round-trip latency is the difference between "it feels native" (1ms) and "it feels laggy" (50ms+).
The numbers
| Path | Median | P95 |
|---|---|---|
| Loopback (LAN-direct) | 0.34ms | 0.81ms |
| Same-LAN remote daemon | 1.8ms | 4.2ms |
| Tunnel via mail.ujex.dev | 148ms | 270ms |
How the probe works
Every API call has a 150ms timeout to localhost. If it answers, we're on LAN. If it doesn't, we fall back. The dashboard caches the choice for 30 seconds to skip the probe on subsequent calls.
The tunnel
An embedded bore client in the daemon. nginx terminates Let's Encrypt TLS. Per-machine subdomains namespaced as <uid6>-<machine-slug>.tunnel.ujex.dev. CAA-pinned to LE + 4 named CAs. Admission token rotated via Firestore.
Detailed: LAN-direct routing post and Tailscale vs Cloudflare Tunnel vs bore.
FAQ
Does the phone app use LAN-direct?
No — phones can't reach your laptop's loopback. Phone always uses the tunnel.
Does it work offline?
Pairing requires internet. After pairing, LAN-only operation is fine — you just lose tunnel fallback.