QR Send CLI

This page documents the standalone terminal sender (qrsend native binary and the portable qrsend.wasm module, plus the thin qrsend-wasm.sh Wasmer launcher), including system config and auditing.

1. CLI quick usage

# Native binary
./qrsend [options] <file|->

# Wasmer
wasmer qrsend.wasm -- [options] --label file - < file

Considerations

The terminal sender is quite low-bandwidth compared to the browser-based sender. On a 80x24 terminal, you can expect around 3-4 kB/s at the default 15 fps. Resizing the window and adjusting the font size can help (160x50 can get up to 15 kB/s).

Compress your data before sending to maximize throughput, for example using zstd -19. Transparent compression in the qrsend protocol would be nice, but is not yet designed.

Because the transfers can take a long time at these kinds of bitrates, prop the receiving device in a stable position and consider using a stand or holder to keep the camera steady and the QR codes in view. It's one thing to go for a cup of coffee while waiting for a transfer to finish, and quite another to handhold a camera for five minutes.

Options

OptionDescription
--fps <hz>Frame rate for terminal updates (default 15).
--qrs-per-frame <n>Force number of QR codes rendered per terminal frame.
--packets-per-qr <n>Target logical packet count per QR.
--cols <n> --rows <n>Override terminal dimensions.
--label <name>Transmitted filename/label.
--ecc low|medium|quartile|highQR error correction level.
--stream-id <id>Set transfer id (15-bit effective).
--interactiveShow pre-send manifest and require confirmation.
--manifest-onlyPrint manifest and exit without streaming.
--log-audit <path>Append JSON audit events to a file.
--verboseEmit JSON audit events to stderr.
--invert, --fg, --bgQR foreground/background color controls.

2. System config files

Default config path (Unix): /etc/qrsend/send.cfg. Override at compile-time with QRSEND_CONFIG=/path/to/send.cfg.

2.1 send.cfg format

Format is key=value. Empty lines and # comments are ignored.

interactive=true
verbose=false
audit_log=/var/log/qrsend-audit.jsonl
audit_syslog=true
audit_journald=false
fg=#111111
bg=white
whitelist_path=/srv/approved
blacklist_path=/srv/approved/secrets

Supported keys include:

interactive
verbose
audit_log
audit_syslog
audit_journald
invert
fg
bg
whitelist_path / allow_path
blacklist_path / deny_path
whitelist_paths / allow_paths   # comma-separated
blacklist_paths / deny_paths    # comma-separated

2.2 Policy dirs: whitelist.d and blacklist.d

qrsend also loads line-based policy files from:

/etc/qrsend/whitelist.d/
/etc/qrsend/blacklist.d/

Each non-empty, non-comment line is one absolute path prefix.

3. Auditing and logging

Audit events are JSON records (TRANSFER_REQUESTED / TRANSFER_COMMENCED / TRANSFER_COMPLETED / TRANSFER_INTERRUPTED).

3.1 Stderr auditing

3.2 File auditing

Use --log-audit /path/file.jsonl or audit_log=... in config.

3.3 Syslog auditing

Enable with audit_syslog=true. qrsend writes local syslog events directly via the OS syslog API.

3.4 Journald auditing (Linux only)

Enable with audit_journald=true. qrsend writes to /run/systemd/journal/socket.

4. Notes