Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

5 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

rstdl

An IDM-style download manager for the terminal, written in Rust.

  • ⚑ Multi-connection HTTP downloads β€” a file is split into N segments downloaded in parallel over Range requests, like IDM.
  • πŸ’Ύ Resume everywhere β€” every segment persists to its own .part file, so a paused, crashed, or restarted download resumes exactly where it left off. Incomplete downloads are picked up automatically on the next launch.
  • 🧲 Torrents & magnet links β€” powered by librqbit (pure-Rust: DHT, uTP, PEX, fastresume). Torrents survive restarts and resume on their own.
  • πŸ–₯️ Interactive TUI β€” a full-screen dashboard with live progress bars, speeds, ETAs, peer counts, pause/resume/delete, and an input bar for pasting URLs or magnets.
  • 🌐 Browser trigger β€” while rstdl is running it exposes a small local HTTP API; a bundled Chrome extension (Manifest V3) intercepts downloads and hands them to rstdl.

Install

Prebuilt binaries are attached to every GitHub release β€” no Rust toolchain needed. Linux (x86_64 static musl + arm64), macOS (universal binary for Intel & Apple Silicon) and Windows (x86_64).

Linux & macOS (one line):

curl -fsSL https://raw.githubusercontent.com/snap-star/rstdl/master/scripts/install.sh | sh

Windows (PowerShell, one line):

irm https://raw.githubusercontent.com/snap-star/rstdl/master/scripts/install.ps1 | iex

The installers detect your OS/arch, verify the sha256 checksum, drop the binary in ~/.local/bin (or %LOCALAPPDATA%\rstdl\bin on Windows) and copy the Chrome extension next to it. Set RSTDL_REPO=you/rstdl to point at a fork. Downloads go to ~/Downloads by default (see Configuration).

From source (needs Rust):

cargo install rstdl --locked          # or: cargo binstall rstdl

Linux builds are fully static (musl), so a single binary runs on any distro. The release workflow builds them with a bundled OpenSSL (--features vendored-openssl).

Quick start

rstdl                          # start the TUI dashboard (default)

Press a, paste a URL or magnet link, press Enter. That's it.

Headless mode (e.g. on a server, or when you only want the browser trigger):

rstdl serve

CLI

rstdl                       interactive TUI dashboard (default)
rstdl serve [-p PORT] [-o DIR]     headless daemon with the browser-trigger API
rstdl add <url> [-p PORT]          add a URL/magnet/.torrent to a running rstdl
rstdl list [-p PORT]               list items from a running rstdl
rstdl config                       print config & state paths

TUI keybindings

Key Action
a add a URL / magnet / .torrent (paste into the input bar)
p / Enter pause / resume the selected item
d delete the selected item (and its files)
u toggle size/speed units (KiB/s ⇄ KB/s) β€” saved to the config
t cycle theme preset (dark β†’ solarized β†’ light) β€” saved to the config
r reload the theme + units from config.toml (no restart)
↑/↓ or j/k move the selection
g / G jump to top / bottom
q / Esc quit (downloads stay resumable)

Browser integration

rstdl listens on http://127.0.0.1:4578 (configurable) while running β€” in both the TUI and serve modes. The bundled Chrome extension talks to it.

  1. Build & start rstdl (rstdl or rstdl serve).
  2. Open chrome://extensions, enable Developer mode, click Load unpacked, and select the extension/ directory.
  3. Click the rstdl toolbar icon to check the connection and tweak what gets intercepted.

The extension:

  • Intercepts downloads via chrome.downloads: if the URL matches the file-type list (or when set to β€œeverything”), it cancels the browser download and POSTs it to rstdl. If rstdl isn't running, the browser download simply proceeds as normal.
  • Magnet links and .torrent URLs are always routed to the torrent engine.
  • Adds a right-click menu: β€œDownload with rstdl” on links/selection/page.
  • Shows browser notifications when downloads complete, fail, or turn out corrupt β€” the popup has a toggle for it.

You can also trigger downloads without the extension:

curl -X POST http://127.0.0.1:4578/download \
  -H 'Content-Type: application/json' \
  -d '{"url": "https://example.com/file.zip", "referer": "https://example.com/"}'

curl -X POST http://127.0.0.1:4578/torrent \
  -H 'Content-Type: application/json' \
  -d '{"url": "magnet:?xt=urn:btih:..."}'

API endpoints: POST /download, POST /torrent (JSON {url} or raw .torrent bytes), GET /status, GET /items, GET /events?since=N (notification history).


Configuration

First run writes ~/.config/rstdl/config.toml:

download_dir       = "~/Downloads"   # default output folder
connections        = 4               # parallel connections per HTTP download
max_concurrent_http = 3              # simultaneous HTTP downloads
browser_port       = 4578            # browser-trigger API port
min_segment_size   = 1048576         # files below this use a single connection
retries            = 5               # per-segment retries on transient errors
units              = "binary"        # "binary" = KiB/s/MiB, "decimal" = KB/s/MB

Units. Sizes and speeds are shown in 1024-based units (KiB, MiB, GiB) by default. Set units = "decimal" for 1000-based units (KB, MB, GB), or press u in the TUI to toggle live β€” the choice is saved to the config.

Notifications

rstdl can notify you when downloads complete, fail, or turn out corrupt (e.g. a size mismatch detected at merge). Three channels, all toggleable under [notifications]:

[notifications]
enabled      = true       # master switch
tui_banner   = true       # toast strip at the top of the TUI
desktop      = true       # real desktop notification (D-Bus / Notification Center)
bell         = false      # ring the terminal bell on a new TUI toast
command   = ""         # optional shell hook, e.g. "notify-send 'rstdl' '%t: %b'"
completed = true       # notify on success
failed    = true       # notify on failure
corrupt   = true       # notify when a download is detected as corrupt

For the command hook, %k is replaced with the kind (Completed / Failed / Corrupt), %t with the title and %b with the body β€” values are shell-escaped for you. If your desktop lacks a notification daemon, desktop notifications are skipped quietly; the TUI banner and event log still work. bell = true rings the terminal bell each time a banner toast appears (it only applies while a toast is visible, so it does nothing when tui_banner = false).

Every notification is also recorded in a sequence-numbered history served at GET /events?since=N (returns { seq, events: [{ seq, kind, title, body }] }) β€” the Chrome extension polls it and raises a browser notification for each new event (toggleable in the extension popup, browserNotify).

Logs: ~/.local/state/rstdl/rstdl.log. Torrent state: ~/.local/state/rstdl/torrents/.

Theming the TUI

All TUI colors come from the [theme] table in config.toml. Values are named colors (red, dark_gray, light_blue, ...) or hex RGB (#5fd7ff). Only include the keys you want to change β€” everything else uses its default:

[theme]
preset        = "dark"        # base palette: dark | solarized | light
                              # (extra per-key colors override the preset)
events        = "red"         # event-log lines (the "events" panel)
title         = "light_green" # header title
border        = "blue"        # panel borders
dim           = "dark_gray"   # sizes, ETA, counts
server        = "green"       # browser-trigger URL
speed         = "cyan"        # download/upload speeds
kind_http     = "cyan"        # ↓ icon
kind_torrent  = "magenta"     # β—Ž icon
name          = "white"       # item names
progress      = "yellow"      # progress bar while downloading
progress_done = "green"       # progress bar at 100%
percent       = "light_blue"  # percentages
status_done   = "green"       # Completed / Seeding
status_paused = "yellow"      # Paused
status_error  = "red"         # Failed / Error
status_active = "light_blue"  # Downloading / Merging
status_idle   = "dark_gray"   # other statuses
error         = "red"         # inline ⚠ errors
footer_fg     = "black"       # footer bar text
footer_bg     = "dark_gray"   # footer bar background
input_fg      = "black"       # URL input text
input_bg      = "yellow"      # URL input background

Presets & live reload

Pick a base palette with preset = "dark" | "solarized" | "light". Any color keys you set are layered on top of the preset, so you can tweak just the events color without losing the palette.

  • t β€” cycle the preset (dark β†’ solarized β†’ light). The choice is written back into config.toml, so it sticks after a restart.
  • u β€” toggle units (KiB/s ⇄ KB/s), also persisted to config.toml.
  • r β€” re-read config.toml and apply changes live. Edit the file with your editor, save, press r: no restart needed. Only the changed line is touched when toggling, so comments and manual edits survive.

rstdl config prints the current paths, the active preset, the unit system, the resolved theme colors, and the preset list.

How resume works

Each download lives in a staging folder next to the final file: <download_dir>/.rstdl/<name>-<hash>/ containing meta.json (URL, headers, size) and one part.N file per connection. A part file's on-disk size is its resume point, so:

  • pause/resume β€” the next run simply issues Range: bytes=<partsize>-... per part;
  • crash/restart β€” rstdl scans the staging folder on startup, rebuilds the items, and resumes them automatically;
  • completion β€” parts are concatenated into the final file and staging is removed.

Servers without Range support (or files smaller than min_segment_size) fall back to a single resumable stream.

Architecture

src/main.rs     CLI (clap), logging, runtime wiring
src/manager.rs  shared engine state, unified item model, event log
src/httpdl.rs   segmented HTTP engine (probe β†’ Range segments β†’ merge), resume, retry
src/torrents.rs librqbit session wrapper (magnet/.torrent, pause/resume/remove, stats)
src/server.rs   localhost HTTP API for the browser trigger (axum, CORS)
src/tui.rs      ratatui dashboard
src/config.rs   XDG config & state paths, theme-preset persistence
src/theme.rs    theme model: presets (dark/solarized/light) + color parsing
src/util.rs     formatting helpers
extension/      Chrome MV3 extension (intercepts downloads β†’ local API)
scripts/smoke.sh      end-to-end test (multi-conn, crash + resume, integrity)
scripts/install.sh    one-line installer for Linux & macOS (curl | sh)
scripts/install.ps1   one-line installer for Windows (irm | iex)
.github/workflows/    release.yml β€” builds + packages binaries for all platforms

Testing

bash scripts/smoke.sh   # throttled local server β†’ segmented download β†’ kill β†’ resume β†’ sha256 check

Roadmap ideas

  • Watch folder for .torrent files / URL files (.url, .rdm)
  • Speed limits per download / global
  • Queue priorities and schedules
  • Firefox port of the extension
  • Media/video stream interception (XDM-style content script)
  • Notifications on completion

About

An IDM-style download manager for the terminal, written in Rust.

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages