Architecture
Remora is a Rust workspace with three crates.
crates/
proto/ wire protocol: framing, rendezvous + session messages,
SPAKE2 handshake and the encrypted channel
server/ remora-server: ID registry, NAT traversal, relay
app/ remora: egui desktop app, host and viewer in one
The app
| Module | Responsibility |
|---|---|
host.rs | Registers with the server, listens for direct connections, authenticates viewers, runs capture and input threads |
viewer.rs | Connects, decodes frames on a background thread, tracks stats |
net.rs | Route selection (LAN direct → peer-to-peer → relay) and the port-443 fallback |
p2p.rs | UDP hole punching and the QUIC transport |
codec.rs | The tile codec |
capture.rs / input.rs | Screen capture (xcap) and input injection (enigo) |
channel.rs | Prioritized outgoing queue |
common.rs | Chat, file transfer, clipboard sync |
logo.rs | The logo, rasterized for the window icon, the sidebar and the .exe icon |
ui/ | egui interface: theme, vector icons, components, pages and the session view |
Screen codec
The screen is cut into 64 × 64 tiles. Each frame, only tiles that changed since the previous frame are sent, each encoded as one of:
- Solid colour, for flat areas (3 bytes),
- JPEG, in the speed and balanced modes,
- LZ4-compressed RGB, in lossless mode.
Tiles are encoded and decoded in parallel with rayon. A static desktop costs almost nothing; a full-screen video is where a hardware video codec would do better (see the roadmap).
Flow control: the viewer acknowledges each frame after decoding it, and the host never has more than two frames in flight. The frame rate therefore adapts to the slower of the network and the viewer's CPU, instead of queueing up latency.
Message priority
Each session has three outgoing queues, drained in strict order:
- Control: input, chat, acknowledgements, clipboard;
- Video: at most two frames;
- Bulk: file chunks of 64 KB.
So a large file transfer never delays a mouse click.
Wire protocol
Everything is length-prefixed postcard messages. The rendezvous protocol between apps and the server is plaintext and small: register, heartbeat, connect, join relay, plus the UDP hello used for hole punching. Session messages travel only inside the encrypted channel. The protocol carries a version number, and peers with different versions refuse to connect.
The docs site
This site lives in docs/: Next.js with MDX pages, shadcn/ui components, exported as static files for GitHub Pages.