UnixDM splits validated HTTP downloads across as many as 32 transfer handles, writes each range to its final offset, and presents the transfer as a responsive terminal workspace. When byte ranges or a stable representation validator are unavailable, it safely falls back to a single stream. Interactive and line-oriented modes use the same verified engine.
brew install wthrajat/unixdm/unixdm
unixdm https://example.com/archive.tar.zst| Capability | Behavior |
|---|---|
| Parallel ranges | 1–32 libcurl easy handles when the server provides exact HTTP 206 ranges and a stable validator. |
| Safe fallback | A real one-byte probe detects servers that ignore Range before the destination is opened. |
| Resume | Versioned, checksummed, atomically published checkpoints bound to URL, file identity, size, and HTTP validators. |
| Recovery | Transient network and selected HTTP failures retry from the verified remaining offset with bounded backoff. |
| Direct writes | Best-effort preallocation, exact sizing, and EINTR-safe pwrite() at each segment's final byte offset. |
| Tail balancing | When a connection finishes, its slot can split the largest remaining range without a polling thread. |
| Queue | A text file supplies a sequential batch with per-item state and aggregate failure exit status. |
| Terminal UX | Wide, stacked, and minimum-size layouts; semantic theme; NO_COLOR; contextual help; safe cancellation. |
| Automation | --no-ui and redirected output use stable, line-oriented status instead of the alternate screen. |
The project deliberately does not claim benchmark superiority yet. Throughput claims will only be added alongside a reproducible benchmark that reports correctness, CPU, memory, syscall, storage, and network conditions.
Install UnixDM from the official tap on macOS or Linux:
brew install wthrajat/unixdm/unixdm
# (equivalent shortcut if you already tapped:)
# brew tap wthrajat/unixdm && brew install unixdmTo upgrade later:
brew upgrade wthrajat/unixdm/unixdmFor source builds, local setup, tests, and contributor workflows, see development.md.
The examples below assume unixdm is installed and on PATH. From a source build, use ./build/unixdm instead.
Download one file:
unixdm https://example.com/archive.tar.zstChoose the connection count and destination:
unixdm --segments 16 --dir "$HOME/Downloads" https://example.com/archive.tar.zstRun a batch at the next local occurrence of 02:00:
unixdm --input-file urls.txt --schedule 02:00 --dir "$HOME/Downloads"Use stable output in scripts or logs:
unixdm --no-ui --output artifact.bin https://example.com/artifact.binUnixDM refuses to replace an unrelated existing file by default. Use --force for an intentional replacement or
--no-resume to discard an old checkpoint and restart from byte zero.
Automatic checkpoints and resume are available only when the server exposes a known size, exact byte ranges, and a
strong ETag or Last-Modified validator. --resume makes an existing compatible checkpoint mandatory; it never bypasses
representation validators.
-n, --segments <1-32>: number of parallel ranges (default: 8)--speed-limit <KB/s>: aggregate receive limit (0disables)--retries <0-20>: retry cap (default: 3)-A, --user-agent <text>: custom user-agent string-H, --header <header>: additional header; repeatable
-o, --output <file>: output file path-d, --dir <directory>: output directory (default: current)-r, --resume: require a compatible checkpoint--no-resume: discard old resume state and start fresh-f, --force: replace an existing output without resume state-O, --open: open verified output after completion
-i, --input-file <file>: read one URL per line-s, --schedule <HH:MM>: start at next local wall-clock time--no-ui: use stable line-oriented output-v, --verbose: show transfer details-V, --version: show version-h, --help: show help
| Key | Action |
|---|---|
Tab / Shift-Tab |
Move between queue and range panes |
↑ / ↓ or j / k |
Move through the focused list |
Space |
Toggle pause and resume |
P / R |
Pause / resume aliases |
1 / 2 |
Focus queue / range pane |
? |
Open or close contextual help |
Escape |
Close contextual help |
Q / Ctrl-C |
Cancel and quit; checkpoint when resumable |
Enter |
Leave the final summary |
flowchart TD
R["Running: download in progress"]
P["Paused: transfers suspended"]
H["Help: contextual overlay shown"]
Q["Quit: exit requested"]
R -->|Space, P or R| P
P -->|Space, P or R| R
R -->|?| H
H -->|?| R
H -->|Escape| R
R -->|Q or Ctrl-C| Q
P -->|Q or Ctrl-C| Q
flowchart TD
A["Start download"] --> B["HEAD + Range 0-0 probe"]
B --> C{"Valid range support and stable validator?"}
C -->|Yes| D["Build verifier-aware range plan"]
C -->|No| E["Use single-stream fallback"]
D --> F["Multi-segment workers download each range"]
F --> G["Writes via offset-safe pwrite"]
G --> H["fsync + checkpoint snapshot"]
E --> H
H --> I{"All ranges/single stream verified?"}
I -->|Retry on transient failures| J["Resume from remaining offsets"]
I -->|Yes| K["Mark complete"]
J --> H
Progress numbers are for UX only; completion is decided only when every verified range (or single-stream) segment has completed.
UnixDM 0.2.0 is the upcoming correctness and professionalization release.
Contributions should preserve the core invariants: no unvalidated range writes, no progress-only completion decisions, no non-atomic checkpoint publication, and no worker-owned mutable objects in the renderer.
UnixDM is available under the Mozilla Public License 2.0. Dependency notices are collected in THIRD_PARTY_NOTICES.
