I published Unmoor, an experimental encrypted, authenticated UDP terminal and file transport for Linux and macOS.
The basic idea is not new. Mosh solved the roaming terminal first. Unmoor explores a different set of trade-offs around the same general problem.
The session is identified by a cryptographic identity rather than an address tuple, so an address or NAT change doesn't end it; the session can resume once a usable UDP path exists again.
The main trade-off
Mosh and Unmoor differ in what they treat as the terminal.
Mosh synchronizes screen state. It can skip older output when newer state supersedes it, and its speculative local echo makes typing feel responsive before the server confirms each keystroke.
Unmoor sends the stream.
Once a terminal byte has been admitted by Unmoor, it is delivered or kept for repair. The client reports SYNC, OUT-OF-SYNC or STALLED, so a gap isn't silently treated as delivered.
That has a couple of useful consequences: normal terminal scrollback, search and copy work because the bytes really arrive, and someone who disrupts the path can stop output reaching you but cannot leave the client claiming that it received the complete stream.
There is a real price for that choice. When retained history fills, the sender applies backpressure, which can block the command producing output until the receiver catches up. Mosh can instead skip ahead.
If responsiveness on a bad link matters more than receiving the full terminal stream, use Mosh.
Some other differences
SSH authenticates Unmoor's initial exchange, but it carries public records rather than an Unmoor traffic key. Each endpoint derives fresh session keys locally using hybrid X25519 + ML-KEM-1024 key agreement.
Post-quantum key agreement is required by default. --pq=prefer and --pq=off are explicit downgrades, and rekeys use the same hybrid exchange.
After bootstrap, terminal and file traffic runs over encrypted, authenticated UDP.
A few other properties:
- a listener adopts a new return address only after a fresh authenticated packet advances the replay window, so a replayed packet can't redirect the session
- multiple authenticated UDP legs can belong to one session
- single-file push and pull verify the whole file before installing it atomically; a partial destination is never reported as success
- on Linux, the client confines itself by default using
no_new_privs, Landlock and seccomp - no root, capabilities or kernel module are required
"Multiple legs" does not necessarily mean multiple physical network paths. Different UDP source ports can exercise different RSS/ECMP choices, but that alone does not prove path diversity.
Unmoor is not a VPN, relay or NAT hole-puncher. The client still needs to be able to reach the listener's UDP port.
Where this came from
I actually wrote the lossy version first.
URTB drops output under pressure because a LoRa link gives you very little bandwidth and sometimes there is no better choice. That trade-off makes sense there.
A normal network path doesn't have the same constraint, so with Unmoor I wanted to see what happens if admitted terminal output is never silently discarded.
This is version 0.2.0 / protocol v2. It is experimental and has not had an external security audit.
It is not intended to be exposed as a public service endpoint, and protocol v2 may change without a compatibility promise.
The project was developed end-to-end with AI assistance across implementation, specification, tests, reviews and documentation. The material design decisions and responsibility for what was accepted remain mine. That provenance should be part of how the code is evaluated.
Try it
git clone https://github.com/nmicic/unmoor
cd unmoor
make -j2
make check
make smoke
make smoke performs a real post-quantum bootstrap over loopback UDP with a live PTY.
The repository contains the usage instructions, protocol and design notes, security model, limitations and tests:
Top comments (0)