rzsz

April 28, 2026 · View on GitHub

A modern Rust rewrite of the classic lrzsz file transfer tool. Transfer files over terminal connections using ZModem, XModem, and YModem protocols.

中文文档

Features

  • Single binary — One zz binary (449KB static), all commands via symlinks
  • Drop-in replacement — Works as rz, sz, rrz, rsz via argv[0] detection
  • Smart modezz file sends, zz receives, no separate commands needed
  • ZModem — CRC-16/32, adaptive block sizing, multi-file batch, crash recovery
  • XModem — 128B/1K blocks, CRC-16 and checksum modes
  • YModem — Batch transfer with file headers, size tracking
  • Secure — Restricted mode by default, path traversal protection, filename sanitization
  • Terminal compatible — Works with Xshell, SecureCRT, iTerm2, MobaXterm
  • Zero dependencies — Static musl build, runs on any Linux (x86_64, aarch64)

Quick Start

curl -fsSL "https://raw.githubusercontent.com/kookob/rzsz/main/install.sh?t=$(date +%s)" | sudo bash

Uninstall

curl -fsSL "https://raw.githubusercontent.com/kookob/rzsz/main/install.sh?t=$(date +%s)" | sudo bash -s -- --uninstall

Other install methods

# From cargo
cargo install rzsz

# From binary release
curl -LO https://github.com/kookob/rzsz/releases/latest/download/zz-linux-x86_64-musl.tar.gz
sudo tar xzf zz-linux-x86_64-musl.tar.gz -C /usr/local/bin/

# Replace system rz/sz (optional)
sudo ln -sf /usr/local/bin/zz /usr/bin/rz
sudo ln -sf /usr/local/bin/zz /usr/bin/sz

Usage

# Unified command (auto-detect mode)
zz file1 file2        # Send files
zz                    # Receive files

# Traditional commands (symlinks to zz)
sz file1 file2        # Send files
rz                    # Receive files

# Common options
zz -r file            # Resume interrupted transfer
zz -p                 # Receive: protect existing files (don't overwrite)
zz -E                 # Receive: rename if file exists (.1, .2, ...)
zz -e file            # Escape all control characters
zz -T file            # Turbo mode (less escaping, faster)
zz -8 file            # Try 8K blocks
zz -q file            # Quiet mode
zz -v file            # Verbose mode
zz --help             # Show all options

File Overwrite Policy

OptionBehavior
Default (no flags)Overwrite existing files
-p / --protectSkip existing files with message
-E / --renameAuto-rename (file.1, file.2, ...)

How It Works

zz is a single binary that determines its behavior from how it is invoked:

Invoked asModeProtocol
zz fileSendZModem (auto)
zzReceiveZModem (auto)
sz / rsz / lszSend (forced)ZModem
rz / rrz / lrzReceive (forced)ZModem
sb / rsbSendYModem
rb / rrbReceiveYModem
sx / rsxSendXModem
rx / rrxReceiveXModem

X/YModem limitations

X/YModem are provided for compatibility. Only ZModem mode honors the full option set. On X/YModem paths:

  • XModem send: -k / -8 selects 1024-byte blocks; other send options are ignored.
  • XModem receive: the first non-flag argument is the destination filename (XModem has no filename in the protocol). Output is padded to the block boundary.
  • YModem receive: -q suppresses the received: line; -p / -y / -E / -r / -R / -U have no effect (files are always overwritten into the current directory with the filename from block 0).

For full option support, use ZModem (the default).

Comparison with lrzsz

rzszlrzsz
LanguageRustC
Binary size (static)449 KB~200 KB
Binary count1 (zz)2 (lsz + lrz)
Unified commandzz (auto-detect)No
Memory safetyCompile-time guaranteedManual
Terminal restoreRAII (guaranteed on all exit paths)Signal handler (fragile)
Timeout mechanismpoll()alarm()/SIGALRM
State managementStruct fields50+ global variables
Protocol state machineExplicit enum + matchImplicit goto chains
Path traversal protectionDefault onOpt-in

Performance (10MB pipe transfer)

SenderReceiverThroughput
C lszC lrz116 MB/s
Rust szC lrz49 MB/s
C lszRust rz45 MB/s
Rust szRust rz29 MB/s

The Rust version is 2-3x slower in pipe benchmarks due to per-byte escape encoding (vs C's batch zsendline_s). In real-world SSH/serial transfers, network latency dominates and the difference is imperceptible.

Terminal Compatibility

TerminalZModem SupportStatus
XshellBuilt-inTested
SecureCRTBuilt-inCompatible
iTerm2Configurable triggerCompatible
MobaXtermBuilt-inCompatible
TabbyPluginCompatible
Windows TerminalNoneUse scp instead
PuTTYNoneUse scp instead

Building from Source

git clone https://github.com/kookob/rzsz.git
cd rzsz

# Development build
cargo build

# Release build
cargo build --release

# Static musl build (no runtime dependencies)
rustup target add x86_64-unknown-linux-musl
cargo build --release --target x86_64-unknown-linux-musl

# Run tests
cargo test
bash tests/interop.sh

Architecture

src/
├── bin/zz.rs           # Unified binary: auto-detect send/receive from argv[0]
├── sender.rs           # ZModem send: handshake, file data, adaptive blocks
├── receiver.rs         # ZModem receive: ZRINIT negotiation, file write, resume
├── xmodem.rs           # XModem: 128B/1K blocks, CRC-16/checksum
├── ymodem.rs           # YModem: batch transfer, file headers
├── zmodem/
│   ├── frame.rs        # Frame encoding/decoding (hex/bin16/bin32)
│   ├── session.rs      # Protocol state machine, header parsing
│   ├── crc.rs          # CRC-16 and CRC-32 lookup tables
│   └── escape.rs       # ZDLE escape table
└── serial/
    ├── mod.rs           # ProtocolWriter/StatusWriter (type-safe I/O separation)
    ├── reader.rs        # Buffered modem reader with poll() timeout
    └── terminal.rs      # TerminalGuard (RAII terminal mode restore)

Publishing

See PUBLISHING.md for crates.io and GitHub Release instructions.

License

Apache-2.0

Credits

  • Original rzsz by Chuck Forsberg (Omen Technology)
  • lrzsz maintained by Uwe Ohse
  • ZModem protocol specification (1988)