| Crates.io | ztus |
| lib.rs | ztus |
| version | 1.0.15 |
| created_at | 2026-01-21 01:37:23.693511+00 |
| updated_at | 2026-01-24 08:18:02.707489+00 |
| description | A blazingly fast Rust CLI tool for resumable uploads using the TUS protocol and chunked downloads |
| homepage | |
| repository | https://github.com/zachhandley/ztus |
| max_upload_size | |
| id | 2058025 |
| size | 378,595 |
ztus (like yeetus but with a z) - a blazingly fast Rust CLI tool for resumable uploads using the TUS protocol and chunked downloads.
A TUS (tus.io) client because existing ones were out of date or abandoned. Implements the TUS resumable upload protocol for reliable file uploads that can be interrupted and resumed, plus wget/curl-like chunked downloads.
Performance: ztus achieves 50-100+ MiB/s on gigabit networks with adaptive chunk sizing and HTTP/2 support - a 40-50x improvement over traditional TUS clients. Upload a 24 GB file in ~5-10 minutes instead of ~4 hours.
~/.ztus/ with enhanced crash recovery# Build and install locally from source
cargo install --path .
cargo build --release
The release binary is at target/release/ztus.
cargo test
# Basic upload (adaptive chunk sizing enabled by default)
ztus upload myfile.zip https://files.example.com/upload/
# Upload with verbose output (shows adaptive behavior)
ztus upload myfile.zip https://files.example.com/upload/ -v
# Disable adaptive sizing and use fixed chunk size
ztus upload myfile.zip https://files.example.com/upload/ --no-adaptive
# Use specific chunk size (disables adaptive sizing)
ztus upload myfile.zip https://files.example.com/upload/ -c 5242880
# Resume interrupted upload
ztus resume myfile.zip https://files.example.com/upload/
Adaptive Chunk Sizing is enabled by default and automatically optimizes performance:
To customize adaptive behavior, create ~/.ztus/config.toml:
[upload.adaptive]
enabled = true
initial_chunk_size = 10485760 # 10 MB
min_chunk_size = 5242880 # 5 MB
max_chunk_size = 104857600 # 100 MB
adaptation_interval = 5 # Re-evaluate every 5 chunks
stability_threshold = 0.1 # 10% variance threshold
# Basic download
ztus download https://files.example.com/myfile.zip -O myfile.zip
# Download with custom chunk size (default: 5MB)
ztus download https://files.example.com/myfile.zip -O myfile.zip -c 10485760
# Resume interrupted download (automatic)
ztus download https://files.example.com/myfile.zip -O myfile.zip
The download command supports:
~/.ztus/downloads/# List incomplete uploads
ztus list
# Clean up old incomplete uploads (older than 7 days)
ztus cleanup --days 7
# Show configuration
ztus info
ztus includes Python bindings with both synchronous and asynchronous APIs, built with PyO3.
# From PyPI (once published)
pip install ztus
# Or build locally from source
pip install maturin
cd /path/to/ztus
maturin develop --release --features python
The Python bindings require Python 3.11 or later (due to PyO3 compatibility).
import ztus
def progress_callback(bytes_transferred: int, total_bytes: int) -> None:
"""Progress callback function"""
if total_bytes > 0:
percent = (bytes_transferred / total_bytes) * 100
print(f"Progress: {bytes_transferred}/{total_bytes} bytes ({percent:.1f}%)")
# Create client
client = ztus.TusClient()
# Upload with progress callback
client.upload(
"/path/to/file.txt",
"https://tus.server.tld/files",
progress_callback=progress_callback
)
# Download file
client.download(
"https://files.example.com/myfile.zip",
"myfile.zip",
progress_callback=progress_callback
)
# List incomplete uploads
incomplete = client.list_incomplete()
# Clean up old uploads (older than 7 days)
count = client.cleanup(days=7)
import asyncio
import ztus
async def main():
def progress_callback(bytes_transferred: int, total_bytes: int) -> None:
if total_bytes > 0:
percent = (bytes_transferred / total_bytes) * 100
print(f"Progress: {bytes_transferred}/{total_bytes} bytes ({percent:.1f}%)")
client = ztus.TusClient()
# Upload asynchronously
await client.upload_async(
"/path/to/file.txt",
"https://tus.server.tld/files",
progress_callback=progress_callback
)
# Resume interrupted upload
await client.resume_async(
"/path/to/file.txt",
"https://tus.server.tld/files"
)
# Download asynchronously
await client.download_async(
"https://files.example.com/myfile.zip",
"myfile.zip",
progress_callback=progress_callback
)
asyncio.run(main())
| Method | Description | Sync | Async |
|---|---|---|---|
upload(file_path, url, progress_callback=None) |
Upload a file | ✅ | ✅ |
resume(file_path, url, progress_callback=None) |
Resume interrupted upload | ✅ | ✅ |
download(url, output_path, chunk_size=None, progress_callback=None) |
Download a file | ✅ | ✅ |
list_incomplete() |
List incomplete uploads | ✅ | ❌ |
cleanup(days) |
Clean up old state | ✅ | ❌ |
The progress callback receives two integers:
bytes_transferred: Total bytes transferred so fartotal_bytes: Total bytes to transfer (0 if unknown)def my_callback(bytes_transferred: int, total_bytes: int) -> None:
print(f"{bytes_transferred} / {total_bytes}")
See python/examples/ for complete examples:
sync_upload.py - Synchronous upload with progressasync_upload.py - Asynchronous upload with progressprogress_callback.py - Advanced progress tracking with ETASee PERFORMANCE.md for detailed performance analysis and benchmarks.
| Network Type | Throughput | 24 GB File Time | Improvement |
|---|---|---|---|
| Gigabit | 50-100+ MiB/s | ~5-10 min | 40-50x faster |
| 100 Mbps | 20-25 MiB/s | ~16 min | 14-17x faster |
| 25 Mbps | 4-5 MiB/s | ~1.3 hours | 3x faster |
ztus supports configuration via ~/.ztus/config.toml:
[upload]
chunk_size = 5242880 # Fixed chunk size (if adaptive disabled)
max_retries = 3 # Maximum retry attempts
timeout = 30 # Request timeout (seconds)
verify_checksum = true # Enable checksum verification
checksum_algorithm = "sha256" # Checksum algorithm
[upload.adaptive]
enabled = true # Enable adaptive chunk sizing
initial_chunk_size = 10485760 # 10 MB starting size
min_chunk_size = 5242880 # 5 MB minimum
max_chunk_size = 209715200 # 200 MB maximum
adaptation_interval = 5 # Evaluate every N chunks
stability_threshold = 0.1 # 10% variance threshold