A keyboard-driven BitTorrent client for Windows that lives in your terminal.
castnet is a small TUI over librqbit. It does the daily
things: add a magnet, URL, or .torrent, watch progress and speeds, pause, choose which files
to download, remove a download, and pick up where you left off after a restart.
Built in Rust (2024 edition) with ratatui, Tokio, and librqbit. No daemon, no browser, no config file.
- One 5.2 MB Windows executable; no service or database.
- Rendering works from cheap session snapshots, never while holding the engine lock.
- Per-file selection, pause/resume, and session persistence are wired to the live torrent.
- Torrent metadata is treated as untrusted and sanitized before it reaches the terminal.
- 15 offline tests, including full TUI snapshots at 100 and 200 columns.
- Add a magnet link, an HTTP(S)
.torrentURL, or a local.torrentpath. - Live progress, download/upload speed, peer count, and ETA per torrent.
- Pause and resume, individually.
- Per-file selection; changes apply to the running torrent immediately.
- Remove a download from the list, keeping its files by default or deleting them from disk.
- Downloads persist across restarts through librqbit's session store and fastresume.
- Single binary, one screen, keyboard only.
Tested on Windows with Rust 1.89 or newer (edition 2024).
cargo build --release
.\target\release\castnet.exeTo install it on your PATH:
cargo install --path .To install directly from GitHub:
cargo install --git https://github.com/Raghav-Kochhar/castnetThere are no prebuilt binaries; Windows users build from source.
Release builds use fat LTO, one codegen unit, abort-on-panic, and size-first codegen;
the executable is about 5.2 MB. Swap opt-level = "z" for "s" or 3 if CPU throughput
matters more than size. A panic restores the terminal and exits.
castnet [--dir DIR] [TORRENT]...--dirsets the download folder. Defaults to your OS downloads folder.TORRENTarguments may be magnet links,.torrentURLs, or local paths. They are added as soon as the UI starts, socastnet "magnet:?xt=urn:btih:..."works as a one-shot launcher.
| Key | Action |
|---|---|
a |
Add a torrent |
↑ / k, ↓ / j |
Move the selection |
g, G |
Jump to the top / bottom |
space / p |
Pause or resume |
enter |
Open the file list |
esc |
Back |
d |
Remove from the list (asks first; keep or delete files) |
q |
Quit |
When removing a download, y removes it and keeps the files; x removes it and deletes
the files from disk.
In the file list, space toggles a file. At least one file must stay selected. The selection
is applied to the live torrent, so you can turn individual files off while it is running.
- Downloads:
--dir, or your Windows Downloads folder. - Session and resume data:
%LOCALAPPDATA%\castnet. - Log:
castnet.login the same folder. Only warnings are written by default; setRUST_LOG=info(ordebug) for more.
- The UI never talks to the engine while drawing. Every tick (and after every key) the app takes a cheap snapshot of the session and renders from that. File lists are only built for the torrent whose detail screen is open. The render layer is a pure function of app state, which is what makes the snapshot tests possible.
- One input thread, one async loop. Crossterm events are read on a blocking thread and
forwarded over a Tokio channel; the main loop
select!s between input and a 500 ms tick. - The terminal is restored on panic. A panic hook leaves the alternate screen before the panic message is printed, so a crash does not leave the terminal in raw mode.
- Torrent metadata is untrusted. Names and paths are stripped of control characters before
they reach the terminal, to avoid escape-sequence injection from a hostile
.torrent. - No custom database. Persistence, fastresume, and DHT state are librqbit's job.
- One process. Quitting stops the swarm; there is no background daemon or remote control.
- No search, indexers, RSS, rate limits, watch folders, notifications, or themes.
- Seeding is on by default (librqbit's default). Pause a torrent to stop uploads.
- Removing a download keeps its files unless you choose to delete them in the confirmation.
- This is a client, not a content index. Use it only for content you have the right to download.
- Windows only.
cargo test
cargo clippy --all-targets -- -D warnings
cargo fmt --all -- --checkUI changes may require regenerating the snapshot:
$env:INSTA_UPDATE = "always"
cargo testThe test suite covers key handling, formatting, and a full render of the download list through
ratatui's TestBackend. It stays offline and fast; swarm behavior is not covered.
There is one ignored test that exercises a real public .torrent (metadata only, no payload
download):
cargo test -- --ignoredMIT. See LICENSE.
