What it is
Air Kalon moves a file from one device to another through light. The sending device shows the file as a continuous stream of QR codes. The receiving device reads them with its camera and rebuilds the file.
Nothing else is involved. There is no Wi-Fi, no Bluetooth, no cellular link, no pairing, no account and no server. A transfer uses no network code at all; the Mac app's only connection is its update check. A transfer works in airplane mode and between two devices that have never met.
What you can send
- A file. Any type, up to 256 MiB. It arrives with its original name and media type.
- Several files or a folder. They travel as one zip archive named
bundle.zip, up to 256 MiB in total. - Text. Typed or pasted text travels as
snippet.txt. Rich text travels assnippet.rtfand keeps its styling. A snippet that is a single web link gets an Open button on the receiver. - A photo. On iPhone and iPad, straight from the photo library.
One stream also carries at most 56,403 source symbols, one per frame, so the frame size sets a practical ceiling below the 256 MiB cap: about 77 MiB at the default frame size and about 157 MiB at the largest. The user guide explains what happens when a file is larger.
What you need
| Requirement | |
|---|---|
| Mac | macOS 14 or later, Apple silicon |
| iPhone and iPad | iOS 17 or later |
| Sender | A screen that can show the code at full brightness |
| Receiver | A camera. The iPhone uses its back camera; the Mac uses its default camera, built in or Continuity Camera |
| Permission | Camera access on the receiving device. On the sender, only if you switch on auto-stop |
| Both devices | The current build of Air Kalon. Earlier builds used a different format and cannot exchange files with it |
Every app both sends and receives. Measured pairings include Mac to iPhone, iPhone to Mac, Mac to iPad and iPad to iPhone.
How a transfer behaves
- No handshake. Every frame describes itself, so the receiver can start reading halfway through a stream.
- Missed frames do not matter. Frames are RaptorQ coded. The receiver needs enough distinct frames, in any order, and the one it misses is replaced by the next one it catches.
- Verified before it is offered. Every transfer, of any size, carries a SHA-256 digest of the original bytes. The receiver checks it before it shows the Save button, and offers nothing if the check fails.
- One direction. Light only goes from the sender's screen to the receiver's camera. An optional acknowledgement lets the receiver's screen tell the sender to stop, if the sender has a camera pointed at it.
One wire format
Every frame is a mode 2 frame: a 24-byte header followed by one RaptorQ (RFC 6330) encoding symbol. The only other frame on the channel is the 19-byte acknowledgement. The file inside the stream is always a KCF1 container, Kalon's own file format. A receiver ignores any other QR code in view and refuses any payload that is not a verifiable KCF1 container.
Key figures
| Figure | Value |
|---|---|
| Frame overhead | 24-byte header per QR code |
| Default frame size | 1,465 bytes, a version 27 QR code at error correction level L |
| Largest frame | 2,953 bytes, a version 40 QR code at level L |
| Default rate | 24 frames per second |
| Frames needed, on real devices | Exactly the source symbol count in every recorded run |
| Best measured goodput | 44.4 KB/s at version 40; 30.5 KB/s at the default size |
| Largest file or bundle | 256 MiB |
| Largest stream | 56,403 source symbols: about 77 MiB at the default size, about 157 MiB at the largest |
The performance page gives the conditions behind every number.
How it is built
The work splits along one line: the core owns every byte, the platform owns every photon.
- Rust core (
core/airkalon-core, crate version 3.0.0). The RaptorQ coding layer, the frame and acknowledgement formats, the KCF1 container, QR module generation and a C interface of 42 functions under ABI version 2. - Swift package (
kit, named AirKalonKit). Rendering and frame pacing, camera capture, barcode decoding with Apple's Vision framework, the receiver's hardening policy and the shared Send and Receive screens. - Apps (
apps/macos,apps/ios). Thin shells that add file pickers, saving and sharing.
The mode 2 frame and the acknowledgement frame are fixed by golden test vectors committed when their specification was frozen, and every test run compares the implementation against them byte for byte. The KCF1 container is fixed by its specification and its own test suite.
Read next
- User guide for sending and receiving step by step.
- How it works for the coding and the camera pipeline.
- Wire format for every byte on the screen.
- Integration for the Rust, C and Swift interfaces and building from source.