Introduction
Porter moves a file between two machines with no network between them. The sending machine renders the file as a slideshow of QR codes in a terminal; a phone camera scans them and reassembles the original bytes.
That's the entire transport. No pairing, no accounts, no server, no cloud.
Principles
The air gap is the feature
Porter is not a faster way to send a file — it is a way to send one when no other path exists. A machine with no network interface, an isolated lab network, a device you will not plug a USB stick into.
No back-channel, so no retries
The receiver cannot ask for a frame again. Fountain coding removes the need: every frame is an XOR of a random subset of the file's blocks, so any sufficient pile of frames reconstructs it and no individual frame matters.
One binary on the sending side
The sending machine is often not the one you keep a runtime on. The sender is a single static Rust binary — no Node.js, no Python, nothing to install first.
Two implementations, one wire format
A Rust sender and a Dart receiver must derive fountain symbols identically from the frame's sequence number. The format is specified normatively and checked against shared fixtures, not by trusting the two to stay in step.
Nothing written unless asked
No telemetry, no analytics, no history file by default. --resume opts into
persisting slideshow position; without it, the sender leaves no disk trace.
When to use something else
Porter is honest about being slow. QR codes are a low-bandwidth, line-of-sight, lossy link, and a 109 MB file is around 26,000 chunks — a real transfer that has been run, and also a long time holding a phone at a screen.
If the two machines can see each other over a network, use a network.
porter-sender serve is in the box for exactly that case: an HTTP receiver that
accepts uploads and QR-scan JSON alike, so you can start with the camera and
finish over a wire when one turns out to be available.
The pieces
| Component | Role |
|---|---|
rust-sender/ | The QR slideshow sender, plus serve and join. Single static binary. |
flutter/ | The receiver app for Android and macOS. Scans, decodes, verifies, saves. |