Why osewa exists, every benchmark against ssh and mosh, how it works, what it costs and where it's going. TLS 1.3, with Ed25519 keys on both ends.
Bandwidth is no longer the hard part. Soon almost anywhere will have at least Starlink, and even that carries tens of Mbit/s. What hurts now is latency, deep buffers, switching networks and blocked UDP. And on the other end there's often a coding agent, redrawing a full-screen TUI for hours while you check in from a laptop or a phone.
| ssh | mosh | osewa | |
|---|---|---|---|
| Session | Dies with the TCP connection | Survives roaming | Lives on the host: survives roaming, sleep and server restarts |
| Transport | TCP | UDP only | QUIC, falling back to TLS over TCP |
| Screen on the host | None, bytes are replayed | Its own emulator, no scrollback | libghostty-vt, Ghostty's terminal engine |
| Beyond the shell | Port forwards, exec | Terminal only | Port forwards and exec on the same connection |
| Kitty protocols | Passed through | No | Keyboard; graphics with animation, kept on the host and redrawn on reconnect; clipboard reads and paste events |
| Modern OSC | Passed through | Few | Yes: hyperlinks, cwd, prompt marks, agent status (OSC 7501) |
Client moved to a new IP after 5 s offline. Time from the network coming back to a working session.
QUIC's 1-RTT handshake and a pinned device key, against ssh's key exchange and auth round trips.
| osewa | mosh | ssh | |
|---|---|---|---|
| Transport | QUIC + TLS WebSocket, raced | UDP only (SSP) | TCP |
| Survives sleep / IP change | Yes, resumes in 0.4 s | Yes, 1.1 s | No |
| Echo p50 during a download, cellular (60 ms, deep buffer) | 138 ms | — | 1,714 ms |
| Echo p50 during a download, Wi-Fi (20 ms, 1% loss) | 44 ms | — | 374 ms |
| Echo during a download, 1 Mbit/s (100 ms, 1% loss) | 154 ms | — | none within 15 s |
| Connect + run a command, 120 ms RTT | 388 ms | — | 1,630 ms |
| Local echo prediction | Yes | Yes | No |
| Port forwarding, exec | Yes | No | Yes |
| Works with UDP blocked | Yes, falls back to TCP | No | Yes |
| Bulk throughput | Equal to ssh; ahead on lossy Wi-Fi (0.99 vs 0.92 MB/s) | — | — |
osewa over QUIC, its default, from the full run of 2026-10-31. Same container and ports for every side, netem-shaped links. Over TLS WebSocket, echo during a download was faster still on cellular (73 ms) and at 1 Mbit/s (125 ms). Reproduce: make bench-vs · make bench-mosh.
From a Mac in Thailand to a 1-vCPU Linode in Tokyo, about 100 ms away over the public internet. osewa connects four times faster than ssh and six times faster than mosh, downloads at three times ssh's speed, and during the download echoes keys in 102 ms, as fast as idle. ssh's take 145.
With a fast path, keeping keys ahead of bulk costs osewa nothing: it downloads at three times ssh's speed and still echoes keys as fast as idle.
ssh's download swings a lot run to run here, so read the ssh and mosh download numbers as rough. osewa QUIC's download while typing ranged 15.8–39.9 MB/s across the runs; the WebSocket's held at 27 in every one.
| Median of 5 runs | osewa QUIC | osewa WebSocket | ssh | mosh |
|---|---|---|---|---|
| Connect + run a command | 311 ms | 511 ms | 1,337 ms | 1,993 ms |
| Echo p50, idle | 99 ms | 101 ms | 110 ms | 114 ms |
| Echo p50 / p95 during a download | 102 / 105 ms | 104 / 143 ms | 145 / 150 ms | 113 / 119 ms |
| Download alone | 39.67 MB/s | 27.26 MB/s | 11.96 MB/s | n/a |
| Download while typing | 30.55 MB/s | 27.28 MB/s | 11.55 MB/s | 15.45 MB/s |
Echo is timed with prediction off, so it's the real round trip of a key. mosh carries only the terminal, so its download is a separate ssh connection beside the session, which is why it can beat ssh's own. Runs of 2026-10-31 with osewa-bench vs, server build 377ebff.
osewa keeps the real screen, so it parses everything the program writes, where ssh just forwards bytes. That's host CPU on heavy output, and it's why a flood can't slow your program down.
Same container and run as the lab benchmarks, osewa over TLS WebSocket. An idle session uses under 0.1% CPU on both ends for all three. In a flood the program wrote 173 MB/s under osewa, 22 MB/s under mosh and 1.2 MB/s under ssh.
osewa login uses ssh one time to install itself on the host and enroll your device with an Ed25519 key. From then on it runs on its own port, and even updates go over osewa. Linux and macOS hosts.
osewa login once over ssh, then attach, forward, exec and update over osewa.The same frames run on both. QUIC gets a 300 ms head start; if UDP is blocked, the WebSocket wins. Nothing to configure. Both are TLS 1.3 on port 7322 with the same pinned device keys, so the race picks a road, never a weaker lock.
Each terminal runs in its own process on the host and keeps the exact screen with libghostty-vt. Reconnecting sends one snapshot, not a replay. Pings spot a dead path in about a second, and unacked keys are resent.
Frames go out by priority: control, terminals, exec, then forwards. While you type, bulk is held to the path's bandwidth-delay product plus 40 ms of queue. Each forward gets its own QUIC stream, so a lost packet in a download never blocks a key.
A coding agent runs for hours in a full-screen TUI, and you check in from wherever you are. osewa keeps that screen on the host in libghostty-vt, so what the agent's terminal does reaches you whole on every reconnect. The host answers the agent's queries itself, so it never waits on a client that's asleep.
osewa keeps each session's status on the host. When you attach, a blocked or done agent shows a one-line notice. A new prompt (OSC 133) ends a working or blocked status.
--clipboard-read, and only the owner gets them.| Sequence | What it is | mosh 1.4 | osewa |
|---|---|---|---|
| OSC 7501 | Agent status: working, blocked, done, idle, with progress and a message | Dropped | Kept per session: osewa ls shows it, and attach shows a notice when the agent is blocked or done |
| OSC 133 | Prompt marks | Dropped | Passed to your terminal; a new prompt ends a working or blocked status |
| OSC 9, OSC 777 | Desktop notifications | Dropped | Sent to your terminal as one, live only, never replayed on reconnect |
| OSC 52 | Clipboard | Copies, selection c only; no reads | Copies reach your clipboard; reads only with --clipboard-read, owner only |
| OSC 8 | Hyperlinks | Dropped | Kept in the screen and passed through |
| OSC 7 | Current directory | Dropped | Passed through |
| OSC 0, 1, 2 | Window and tab titles | Passed through, cut to 256 characters | Passed through, control characters stripped |
| OSC 4, 10, 11, 12, 21 and resets 104, 110–112 | Palette, foreground, background and cursor colors | Queries go unanswered; colors the program sets are dropped | Your terminal's colors answer the agent's queries; colors it sets are drawn on your terminal and reset on detach |
| DSR 996, mode 2031 | Light or dark appearance | No answer | Answered from your terminal's, and reported when it changes |
| OSC 22 | Pointer shape | Dropped | Your terminal's pointer follows |
Kitty keyboard (CSI u) | Unambiguous keys and modifiers | Not supported | Supported |
Kitty graphics (APC G) | Images, including animation | Dropped | Drawn on terminals that draw them (kitty, Ghostty, WezTerm; --graphics to choose): kept on the host and redrawn on reconnect; images sent inline only |
| OSC 5522 | Kitty's clipboard protocol | Dropped | Reads wait for the owner like OSC 52's, text only, with --clipboard-read; pastes arrive as Kitty paste events when the program asks for them |
Everything else (other OSCs, DCS including tmux passthrough, APC, PM, SOS) is dropped before it reaches your terminal. The remote program doesn't get to command it. mosh column: mosh 1.4.0, its latest release, read from its source; its main branch has since added OSC 8 hyperlinks, not yet released.
The cryptography is: TLS 1.3 only, and both ends prove who they are with Ed25519 keys on every connection, no passwords. The server's key comes to you during enrollment over ssh, so there's no “trust this host?” prompt, and a revoked device is out on its next connect. Where ssh is ahead is age: OpenSSH has decades of audits and osewa has none yet, it adds a second open port, and its device key is a plain file (mode 0600), not one behind a passphrase or an agent.
For interactive work, yes. You need ssh once, to enroll; after that osewa runs on its own port (TCP and UDP 7322).
The client races QUIC against a TLS WebSocket and takes whichever connects first. With UDP blocked, that costs 300 ms per connect.
mosh keeps sessions alive and predicts echo too, but it is UDP-only and carries only the terminal. osewa adds TCP fallback, port forwarding and exec, and keeps keystrokes ahead of bulk data on the same connection.
Yes. QUIC starts with 1200-byte packets to fit a WireGuard MTU, and our Mac-to-Mac runs to Tokyo, in the README, were taken over Tailscale.
Only through what osewa lets past. The screen is parsed on the host, and only known sequences reach your terminal: other OSCs, DCS (including tmux passthrough), APC, PM and SOS are dropped, and titles lose their control characters. Clipboard reads go only to the session's owner, and only when they attached with --clipboard-read.