A single-binary Rust media manager that searches many indexers at once and files downloads into Plex. https://alangaudet.dev/projects/magnetarr
Find a file
2026-09-24 11:11:19 -04:00
.github/workflows WIP: make the script the single source of truth 2026-07-31 02:12:13 -04:00
crates fix: import a TV pack whose extras repeat a file name (v0.6.8) 2026-09-23 18:37:04 -04:00
docs docs: the GUI runs 0.6.8 and the 0.6.7 AppImage is gone 2026-09-23 19:48:09 -04:00
feedback chore: track the feedback-loop tooling and drop release tags 2026-08-14 12:17:04 -04:00
resources chore: replace platform icons with the new neon bull artwork 2026-09-10 09:20:29 -04:00
scripts feat: About page and Indexers page (v0.6.6) 2026-09-17 17:55:06 -04:00
.gitignore feat: v0.3.2 edition-aware naming and full Plex library coverage 2026-08-08 23:42:20 -04:00
AGENTS.md fix: import a TV pack whose extras repeat a file name (v0.6.8) 2026-09-23 18:37:04 -04:00
Cargo.lock fix: import a TV pack whose extras repeat a file name (v0.6.8) 2026-09-23 18:37:04 -04:00
Cargo.toml fix: import a TV pack whose extras repeat a file name (v0.6.8) 2026-09-23 18:37:04 -04:00
CHANGELOG.md fix: import a TV pack whose extras repeat a file name (v0.6.8) 2026-09-23 18:37:04 -04:00
GEMINI.md Initial import: fork of avatarr legacy, renamed to Magnetarr 2026-07-24 15:52:31 -04:00
LICENSE Initial import: fork of avatarr legacy, renamed to Magnetarr 2026-07-24 15:52:31 -04:00
README.md docs: clone from git.alangaudet.dev; drop the dead avatarr link 2026-09-24 11:11:19 -04:00
roadmap.toml fix: stop the torrent before the move and plan only its own files (m28, v0.6.7) 2026-09-21 17:42:57 -04:00
THANKS.md Initial import: fork of avatarr legacy, renamed to Magnetarr 2026-07-24 15:52:31 -04:00

🎬 Magnetarr

A single-binary Rust media manager. Search torrents, download via qBittorrent, organize into a Plex-compatible library — GUI and CLI in one portable executable.

A leaner, unified alternative to the Sonarr + Radarr stack: TV, movies, and anime in one binary, one UI.

Forked from avatarr (my earlier media manager, now archived and not published) — its legacy branch (JSONL + TOML persistence) — in July 2026 and versioned fresh from v0.1.0. Avatarr was itself a Rust rewrite of the Python plex-pipeline. The complete pre-fork history is preserved in avatarr's archive/legacy-final tag.

Ready to install? Linux · Windows · macOS · TMDB setup

🧭 Status

Today (v0.6.8):

  • Working torrent search across twelve indexers — six native ports (TPB, Nyaa, YTS, EZTV, Knaben, SubsPlease) and six vendored Cardigann definitions that ship enabled (LimeTorrents, Torrent Downloads, Shana Project, Tokyo Toshokan, 1337x, Uindex) — with score-based ranking, plus any of the 589 catalogue entries offered (the 542 vendored Cardigann definitions plus 52 native ports of the trackers Prowlarr implements in C# with no YAML definition, less the five definitions of sites the six native ports above already carry) added through [indexers] or browsed and added from the Indexers page (Ctrl+8)
  • qBittorrent monitor that auto-organizes completed downloads into Plex folder structures
  • A completed torrent is stopped before any of its files move, and an import plans only the files that torrent declares to qBittorrent. Two torrents can legally share one staging folder; the second one's files stay where they are, and its folder is kept. A source file that qBittorrent reports as unfinished or deselected stops the import at Verify, before anything is written
  • Verified handoff to qBittorrent: indexers that publish only a .torrent link (1337x, among others) have their file downloaded and uploaded directly, so an add that did not happen is reported as a failure instead of a success
  • One release, one row: results are collapsed by release name as well as by transfer identity, so a torrent carried by several indexers stops appearing two and three times over (321 raw rows to 199 on a live twelve-indexer search)
  • Configurable libraries: customize Movies, UHD Movies, TV Shows, and Anime, or add first-class libraries such as Star Wars and Disney with their own paths, qBittorrent categories, and optional tags
  • Confirm-mapping gate for absolute-numbered anime: when an episode number overflows its season (TMDB season lengths), the GUI holds before renaming and raises a File · Absolute · Maps-to dialog — confirm, correct per-file, or cancel and resume later from the Attention card
  • Movies + TV + Anime (seasons, episodes, ranges, complete-series packs)
  • Explicit Movie/TV/Anime mode selector on the Search screen — no more guessing what the parser will infer
  • Search box that grows with the titles pasted into it, to a six-line cap and scrolling past that, so a long queue can be read back and corrected before it runs
  • TV and Anime Season Picker dialog when a bare series title is searched — TMDB resolves the canonical title, the picker offers S01–S10 or a Complete Pack shortcut
  • magnetarr-cli search --type {movie,tv,anime} is strict; --complete, --season N, and --episode N provide direct-dispatch shortcuts for TV-style series
  • Smart per-episode quality upgrades (size + resolution comparison)
  • IMDB/TMDB metadata resolution with year-aware caching, and season-shape disambiguation when a release name carries no year: a multi-season pack whose title collides with a remake (ReBoot 1994 against Reboot 2022) is settled by comparing the staged season structure against each candidate's, instead of falling through to the provider's popularity ranking
  • Ctrl K command palette: fuzzy-matched navigation to all nine screens and seven commands, with a chrome-bar Search everything · Ctrl K pill that summons the same overlay
  • About page (Ctrl+9) with the version, the licence, the project links and the Bitcoin and Dogecoin donation addresses with QR codes; indexer management on its own Indexers page (Ctrl+8)
  • Inspector rails on Search and Monitor: the selected release or transfer is described in full beside the table, with its whole name word-wrapped, its routing, its paths, and a one-click copy of the magnet or .torrent link
  • Needs attention is a button that opens a dialog with a selectable, copyable report of every retained failure, so filing a bug costs one paste
  • System tray icon with Hide, Show and Quit, and a close policy of Ask, Close to tray or Quit that the app asks about once and remembers
  • Change the library a transfer sorts to from the Monitor rail; the pick is written to qBittorrent as the torrent's category, so it shows up there and survives a restart
  • Verify, Rename and Move in a Monitor row are buttons that do the thing: plan the transfer without touching a file, list the planned names, or process it now
  • Slint desktop GUI + clap-based CLI
  • Cross-platform: Linux (AppImage), Windows (.exe), macOS (.app+DMG)
  • Workspace regression suite: cargo test --workspace --no-fail-fast; strict lint gate: cargo clippy --workspace --all-targets -- -D warnings
  • Auto-migration from ~/.config/plex-pipeline/ → ~/.config/magnetarr/ on first launch (idempotent, EXDEV-safe)

Next: m21, the read-only library doctor in the roadmap. v0.6.8 imports a pack whose extras repeat a file name across folders, and keeps an episode whose title holds an extras keyword. v0.6.7 stops a torrent before its files move and scopes an import to the torrent's own file list. v0.6.6 adds the About page and moves indexer management to its own Indexers page. The v0.6.5 pack-parsing fix reads long-form episode names, year ranges and absolute episode numbers, and routes a pack's sibling movie, special and extras folders. The v0.6.4 TV year-routing fix keeps same-title shows with different years separate. Phase B is complete — the native ports and the Cardigann runtime cover the full indexer list, and the legacy aggregate bridge that predated them is retired (see the retirement note below). Phase C is complete with v0.5.0: the Library browse shelf (grid and list, read-only, Ctrl+4) and now the Ctrl K command palette with its chrome-bar pill — see docs/ROADMAP.md. Phase A of the Tidemark v1.1 shell completed with v0.3.0 (adopted design: docs/design/SPEC.md).

✨ Features (today)

  • 🧩 Cardigann definition runtime: the pinned Cardigann v11 catalogue — all 542 upstream torrent definitions — is embedded, validated and executed directly (magnetarr-cli indexer sync / list / test / report). A definition the supported subset cannot run is rejected at load with every reason listed, never silently returning nothing, and the Preferences card renders it blocked with that reason rather than hiding it. report measures the engine against the same 542: 296 fully supported, and every remaining gap named with its reason.
  • 🔍 Multi-source torrent search: twelve indexers are built in and searched concurrently — six native ports (TPB, Nyaa RSS, YTS, EZTV, Knaben, SubsPlease) and six Cardigann definitions vendored with the binary and enabled out of the box (LimeTorrents, Torrent Downloads, Shana Project, Tokyo Toshokan, 1337x, Uindex). Every HTML-scraping site is read by the definition runtime; there is no second implementation of any of them. The two Cloudflare-fronted ones (1337x, Uindex) need a FlareSolverr URL in [sources.flaresolverr] and skip quietly without one.
  • 🌟 Quality preference: Select "Any" to prefer 1080p while accepting all qualities, or choose a specific quality (720p, 1080p, 2160p) to only show results matching that quality
  • 📊 Smart scoring: Ranks results by title match, year, quality, seeders, file size
  • 📺 TV support: Season packs, explicit episode search, anime absolute-number fallback, auto-discovery (S01+), season ranges (S01-S05), complete series packs
  • 🏯 Dedicated Anime lane: Anime searches keep TV-style season/episode handling but download under qBittorrent category anime and import into a separately configurable Anime library path. The category is created automatically on first use.
  • 0️⃣ Anime specials organization: Special, Specials, OVA, and ONA release folders map to Plex Season 00; regular seasons use zero-padded Season 01-style folders, and duplicate destinations abort before any files move.
  • 🔎 Search diagnostics: GUI and CLI logs show every source query/category, raw count, and final viable count when a search comes up short
  • 📽️ UHD routing: 2160p/4K movies automatically routed to UHD Movies library
  • 🏷️ Configurable libraries: Movies, UHD Movies, TV Shows, and Anime use the same editable library model as new Star Wars or Disney libraries. Every library owns its path, qBittorrent category, organizer type, and optional tags; Monitor routes by category.
  • :clapperboard: Edition-aware naming: A library can declare the fan edits it recognizes (editions = [{ match = "4k77", name = "4K77" }]); a matching release keeps its Plex {edition-4K77} tag on both folder and file, so alternate cuts of one film stay distinct library items instead of stacking. A library that declares editions refuses an import whose edition it cannot identify, rather than silently writing a plain name.
  • ⬆️ Smart quality upgrade: Incoming files compared by resolution and size — upgrades lower quality, fills missing episodes, replaces zero-byte files
  • 👀 Torrent monitor: Polls qBittorrent, auto-organizes completed downloads into Plex folder structure
  • 🏷️ IMDB/TMDB metadata: Resolves missing years and canonical titles via API lookup (year-aware caching, acronym-aware matching)
  • ❓ Bare title resolution: Movie searches without a year are enriched through IMDb/TMDB before source lookup; untyped list entries and bare TV titles retain their existing metadata-assisted routing
  • 💾 Persistent move logs: JSONL history at ~/.config/magnetarr/move_log.jsonl — survives restarts, easy to grep
  • 🎁 Extras collection: Extras/bonus folders in TV packs automatically moved to Show/Featurettes/
  • 🎥 Movie extraction: Movie files found in TV packs processed as regular movies
  • 🌐 Cross-platform: Linux (AppImage), Windows (.exe), macOS standalone binaries
  • 🖥️ GUI + CLI: Slint desktop GUI and full-featured command-line interface
  • 🚀 First-run setup: Auto-generates config template on first launch
  • 📄 Batch mode: Process list files with movies, TV seasons, season ranges, and discover mode

🎨 GUI

  • Search workspace: Multi-line paste queue, Movie/TV/Anime-aware library selector, grouped results on the Tidemark grid (score/seeds/size/quality, two-line release cells, selected-only routing), a routing-preview rail showing rename + destination + pattern before download, and a collapsible activity drawer
  • Monitor workspace: Page-header stat cluster (down/up/active/failed), a verify → rename → move stepper per row fed by live organizer stage surfacing, exact-percent progress, an all-failures rail of kind-titled cards with Retry and Set location…, and a three-line Recent activity well
  • Attention page: Every retained failure as a full card — kind, torrent title, complete error text, destination, Retry and Set location… — with a live sidebar badge counting failures
  • Library shelf: What is already on disk, read off the configured library paths and parsed by the same parser the search grid uses — a grouped card grid (Movies · TV · Anime, with season spans, episode counts and absolute ranges) and a seven-column sortable list, with a kind filter, find-in-library, five sort fields and a N paths · <root> context line. Read-only by contract: no rename, no move, no delete, no row action — the scan never touches a file, and it runs on a worker thread so a NAS-sized library never blocks the window. A quality or source token the path does not carry renders —; nothing is inferred
  • Rules screen: Per-type naming cards backed by the live [rules] engine — editable filename patterns with a keystroke-live sample, rendered destination templates, token chips, and an anime absolute-numbering pill
  • Tidemark shell: Compact dark chrome, custom keyboard-friendly controls, responsive layouts, and bundled Inter and JetBrains Mono fonts
  • Command palette: Ctrl K from anywhere — or the chrome bar's Search everything · Ctrl K pill — raises an overlay over the dimmed app body with two groups: Navigate, every screen with its own Ctrl N chip, and Commands, the seven operations the app can actually run (Process now, start/stop the monitor, find in the indexer catalogue, the Preferences LIBRARIES card, the move log, the density switch, Quit). Typing fuzzy-matches and highlights the matched glyphs; ↑/↓ move the selection across the group boundary, Enter runs it and closes, Esc closes changing nothing. Commands and navigation only — it does not search indexers or the library; find-in-library stays on the Library toolbar
  • Sidebar shell: Frameless chrome bar (brand mark opens the About page; minimize/maximize/close controls; drag anywhere) over a 212 px sidebar — Search, Monitor, Attention, Library, Rules, Destinations, qBittorrent and the Indexers n/m row that opens the Indexers page, and pinned About and Preferences — with Ctrl+1…Ctrl+9 screen shortcuts (Ctrl+4 Library, Ctrl+5 Rules, Ctrl+6 Destinations, Ctrl+7 Preferences, Ctrl+8 Indexers, Ctrl+9 About) plus Ctrl K (command palette), Ctrl+, (Preferences) and Ctrl+Q
  • Move Log viewer: Browse full move history from move_log.jsonl, including date, status, torrent name, and destination path; Clear Log resets it
  • Preferences page: Edit existing libraries or add new ones, including their paths, qBittorrent categories, and optional tags; configure qBittorrent, TMDB and interface density on the same routed page; the INDEXERS card is a link to the Indexers page
  • Indexers page (Ctrl+8): The managed indexers, each with its enable switch, its settings and a Test button, and the vendored catalogue browser with kind and support facets; Ctrl+F focuses the catalogue filter
  • About page (Ctrl+9): The version and the licence, the source and support links, and the Bitcoin and Dogecoin donation addresses with a QR code and a copy button each
  • Clipboard support: Copy magnet links and wallet addresses to clipboard
Search and Download Torrent Monitor
Magnetarr Search and Download workspace Magnetarr Torrent Monitor workspace
Attention Library
Magnetarr Attention workspace Magnetarr Library shelf
Rules Confirm mapping
Magnetarr Rules workspace Magnetarr confirm-mapping dialog
Command palette Command palette, filtered
Magnetarr command palette Magnetarr command palette filtered by a query
Preferences
Magnetarr Preferences page
list.txt ──> Search ──> Score & Rank ──> Download ──> Monitor ──> Organize ──> Plex
          (native indexers)               (auto-pick)  (qBittorrent)  (rename/move)

Install from source

There are no prebuilt downloads. Choose your platform below and paste the commands into a terminal. They install both magnetarr and magnetarr-cli on your PATH. The first build can take several minutes.

Linux

First, paste the dependency command for your distribution:

# Debian/Ubuntu
sudo apt update && sudo apt install -y git curl build-essential pkg-config \
  libssl-dev libfontconfig1-dev \
  libx11-dev libxcb-shape0-dev libxcb-xfixes0-dev libxkbcommon-dev
# Fedora
sudo dnf install -y git curl gcc gcc-c++ make pkgconf-pkg-config openssl-devel \
  fontconfig-devel libX11-devel libxcb-devel libxkbcommon-devel
# Arch/CachyOS
sudo pacman -S --needed git curl base-devel pkgconf openssl fontconfig libx11 \
  libxcb libxkbcommon

Then paste this block to build and install Magnetarr:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
. "$HOME/.cargo/env"
git clone https://git.alangaudet.dev/alan/magnetarr.git
cd magnetarr
cargo install --locked --force -j 4 --path crates/gui
cargo install --locked --force -j 4 --path crates/cli
magnetarr-cli --version
magnetarr

Windows 10/11

Open PowerShell as Administrator, then paste this entire block. Windows may show installer or permission prompts while the build tools are installed.

winget install --exact --id Git.Git --source winget --accept-source-agreements --accept-package-agreements
winget install --exact --id Rustlang.Rustup --source winget --accept-source-agreements --accept-package-agreements
winget install --exact --id Microsoft.VisualStudio.2022.BuildTools --source winget --accept-source-agreements --accept-package-agreements --override "--wait --passive --norestart --add Microsoft.VisualStudio.Workload.VCTools --includeRecommended"
$env:Path = "$env:USERPROFILE\.cargo\bin;C:\Program Files\Git\cmd;$env:Path"
rustup default stable
git clone https://git.alangaudet.dev/alan/magnetarr.git
Set-Location magnetarr
cargo install --locked --force -j 4 --path crates/gui
cargo install --locked --force -j 4 --path crates/cli
magnetarr-cli --version
magnetarr

macOS

First, install Apple's command-line tools. Paste this command and finish the installer window before continuing:

xcode-select --install

Then paste this block to build and install Magnetarr:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
. "$HOME/.cargo/env"
git clone https://git.alangaudet.dev/alan/magnetarr.git
cd magnetarr
cargo install --locked --force -j 4 --path crates/gui
cargo install --locked --force -j 4 --path crates/cli
magnetarr-cli --version
magnetarr

First-run setup

Launch Magnetarr and press Ctrl+, to open Preferences. Enter your qBittorrent Web UI details and library paths, then add the optional TMDB key below.

Add a TMDB key

TMDB improves title, year, and anime season matching.

  1. Create or sign in to a TMDB account.
  2. Open Account Settings > API and request a Developer API key.
  3. Copy the API Key (v3 auth). Do not copy the longer API Read Access Token.
  4. In Magnetarr, open Preferences > Metadata, paste it into TMDB API key, and select Save Preferences.

TMDB's official getting-started guide explains the registration step.

Migrating from plex-pipeline-rs

If you previously ran the Python plex-pipeline, Magnetarr auto-migrates your ~/.config/plex-pipeline/ directory to ~/.config/magnetarr/ on first launch. No manual action required. The migration is idempotent (it only fires when the new directory does not yet exist) and falls back to a recursive copy on EXDEV if your config and home directories live on different filesystems. See CHANGELOG.md for details.

🕹️ Usage

GUI

magnetarr

🔍 Search screen:

  • Paste one title per line into the queue input (3 titles queued counts live); Movie/TV/Anime, library, and quality selectors sit beside it
  • Choose Auto to preserve normal Movies/UHD/TV/Anime selection, or explicitly choose any compatible configured library
  • Auto Mode or Auto-pick all to select the best result per entry
  • Score-based grouped ranking: collapsible group headers with result counts and composition notes, two-line release cells (name over type · indexer), selected-only routing crest
  • Routing preview rail: what the selected release renames to, where it moves, and the filename pattern — before anything downloads
  • Selected count + total size footer and a collapsible activity drawer (newest log line always visible in the strip)

📡 Monitor screen:

  • Live download and upload rates with active, queued, and failed counts
  • Dense torrent table with progress, speed, ETA, peers, and pipeline state
  • Selected routing details, recent move history, and retained failure cards
  • Process Now button for one-shot processing
  • Retry button for a failed item without racing the normal monitor loop
  • Dry Run toggle to preview moves without executing

⌨️ CLI

# Search
magnetarr-cli search --type movie "Big Adventure 1985"             # Single movie
magnetarr-cli search --type tv "Sunset Valley S01"                  # TV season
magnetarr-cli search --type anime --season 1 "Steins;Gate"         # Anime season
magnetarr-cli search --type tv "Echo Company S05E14"                # Inferred episode
magnetarr-cli search --type tv --season 1 --episode 5 "Steins;Gate" # Explicit episode
magnetarr-cli search --type tv --complete "Echo Company"            # Complete series
magnetarr-cli search --type movie "Night Runner"                     # Bare title
magnetarr-cli search --file list.txt --auto               # Batch from file
magnetarr-cli search --file list.txt --auto --dry-run     # Preview only
magnetarr-cli search --type movie --quality 1080p "Night Runner 2003" # Quality filter
magnetarr-cli search --type movie --library "Star Wars" --auto "A New Hope 1977" # Explicit library

# Monitor
magnetarr-cli monitor                 # Continuous (polls every 30s)
magnetarr-cli monitor --once          # Process completed and exit
magnetarr-cli monitor --dry-run       # Preview moves
magnetarr-cli monitor --test-resolve  # Test metadata resolver

# Rules
magnetarr-cli rules                   # Show effective naming rules with samples

# Indexer definitions (Cardigann)
magnetarr-cli indexer sync            # Install the pinned definition snapshot
magnetarr-cli indexer list            # Show each definition's load status
magnetarr-cli indexer test 1337x                          # Keywordless smoke test
magnetarr-cli indexer test limetorrents --query "Interstellar 2014" --category 2000
magnetarr-cli indexer test shanaproject --set sort=fsize  # Override a setting

# Debug
magnetarr-cli --test-parse            # Test torrent name parsers

🧩 Indexer definitions (Cardigann)

Magnetarr executes Cardigann v11 YAML definitions directly: a tracker is a definition file, not a Rust module.

  • indexer sync installs the pinned catalogue — 542 definitions plus their provenance manifest — into ~/.config/magnetarr/indexers/definitions/. There is no runtime fetch: the catalogue ships with the binary, so upstream churn cannot change what a running Magnetarr does. Each file is read back off disk byte for byte after it is written, and the command reports write failures separately from the definitions this engine cannot execute — the latter are a fact about the catalogue, not a broken install, so a clean sync exits zero with 542 definitions, 0 write failure(s), 236 not executable by this engine.
  • indexer list prints OK or UNSUPPORTED per definition with the complete list of reasons — every unknown key, unsupported feature, bad regex and uncompilable selector at once, not just the first. It defaults to the definitions this install actually uses (added plus shipped-enabled); --find <text> reaches any of the rest by id or display name, and --all lists the whole catalogue.
  • indexer test <id> runs a real search against the live site and prints the rows. It searches an explicit Newznab category, defaulting to the definition's first declared one and printing it above the results; a category the definition does not declare is rejected outright rather than guessed at. Omit --query and the definition's keywordless branch runs.
  • indexer report --dir <path> sweeps a whole directory of definitions and says how much of the v11 feature set the engine covers — three tier counts, a census of every gap code by definitions affected, and the unsupported tail per definition. --json, --markdown and --baseline write it out.

Anything the supported subset cannot execute fails at load, loudly, rather than degrading into an empty result. See docs/qa/m3-cardigann-exec.md for a live CLI run against all six.

How much of Cardigann v11 does it run? Measured, not asserted. A pinned snapshot of 542 upstream torrent definitions (resources/indexers/corpus/, Prowlarr/Indexers at 599bc7c2) is swept by the suite on every run: 540 parse, 305 load clean, 296 are fully supported, and every gap behind the rest is a named census key with a recorded reason — interactive captcha login (44), definitions with no Movies/TV category at all (102), .NET-only regular expressions (43), RSS/XML search mode (20). The corpus is report data — nothing embeds, syncs or enables it — but since v0.5.2 the executable pin is derived from it by scripts/dev/build-snapshot.sh: the same 542 files at the same commit, plus a closed patch list of exactly one entry. Vendored is not the same as enabled: the definitions that ship on are still the six in config::SEEDED_DEFINITIONS, and growing the catalogue turns nothing on. The full artifact is docs/qa/m10-cardigann-corpus-report.md.

Definitions join the search lanes through [indexers]. Add one from the Indexers page (Ctrl+8, or by hand), and every search asks it alongside the native ports:

[indexers]
# The default exclusion filter the retired bridge left behind.
# Emptying either list admits everything — there is no second gate.
exclude_languages = ["ru"]
exclude_names = ["rutracker"]

[indexers.definitions.limetorrents]
enabled = true
link = ""                       # empty → the definition's own links[0]

[indexers.definitions.limetorrents.settings]
# setting-name = "value"        # text / password / select / checkbox, by name

The six vendored definitions — 1337x, limetorrents, shanaproject, tokyotosho, torrentdownloads, uindex — are seeded enabled: they are the only implementation of those six sites, so an absent entry means enabled, exactly as an absent [sources.<site>] block meant enabled for the native ports they replaced. Turning one off is enabled = false; deleting its block re-seeds it on the next load. Anything else you add joins only because you added it.

A definition that cannot run — unknown id, corrupt file, unknown setting name, or one the exclusion filter blocks — is a Failed health row carrying its reason, visible on the card and counted in the sidebar's figure, never a silent drop. (The exclusion filter's defaults block none of the six.)

The Indexers page (Ctrl+8; the Preferences INDEXERS card until v0.6.6) is the one management surface for every indexer. It lists the six native ports first — each with its own enable switch, and Nyaa with its Base URL and Category — then the definitions, which it can also add, configure (one Save per definition), and test against the live site, including the Cloudflare-fronted pair once [sources.flaresolverr].url is set. A native port has no Test button: testing builds a definition-only registry. See docs/qa/m4-indexers-gui.md and docs/qa/m9-indexer-consolidation.md for live runs.

The sidebar's SOURCES section is two rows: qBittorrent, and a single Indexers n/m row — healthy over enabled, with an indexer that has not answered yet counting as up — whose dot shows the worst state any of them is in. Activating that row opens the Indexers page, where the per-indexer detail lives. Search results name the concrete indexer they came from, by display name.

📄 Input file format

# Movies — title with year
Big Adventure (1985)
Night Runner 2003

# TV — show name with S## tag
Sunset Valley S01
Echo Company S01-S03
The Drift S01+

# TV — individual episode
Sunset Valley S05E14

# TV — complete series pack (no season specified)
The Drift

# Bare title — resolved via TMDB (movie or TV detected automatically)
Big Adventure

⚙️ Configuration

Preferences writes this file when changes are saved. Manual configuration is optional; the file is created on first launch at:

Platform Config file
Linux ~/.config/magnetarr/config.toml
Windows %APPDATA%\magnetarr\config.toml
macOS ~/Library/Application Support/magnetarr/config.toml
[qbittorrent]
url = "http://localhost:8080"
username = ""
password = ""

[paths]
staging_dir = "/downloads" # qBittorrent download root / Magnetarr cleanup boundary
movie_dir = "/media/Movies"
uhd_movie_dir = "/media/UHD Movies"
tv_dir = "/media/TV Shows"
anime_dir = "/media/Anime"

[[libraries]] # optional custom library; absent section seeds the original four lanes
name = "Star Wars"
role = "custom"
media_type = "movie" # movie, tv, or anime
destination = "/media/Collections/Star Wars"
category = "star-wars"
tags = ["star-wars", "franchise"] # optional

[[libraries]]
name = "Disney"
role = "custom"
media_type = "movie"
destination = "/media/Collections/Disney"
category = "disney"
tags = ["disney"]

[sources.tpb]
enabled = true
api_base = "https://apibay.org"
request_delay_ms = 2000
min_seeders = 1

[sources.yts]
enabled = true

[sources.eztv]
enabled = true

[sources.nyaa]
enabled = true
base_url = "https://nyaa.si"
category = "1_2" # English-translated anime

# The two native API ports. Each takes the same three keys and each defaults
# to enabled, so the block is only needed to change a base URL, slow a tracker
# down, or turn one off. The six HTML ports that used to sit here are vendored
# Cardigann definitions now — see [indexers.definitions] above and the
# retirement note below.
[sources.knaben]
enabled = true
base_url = "https://api.knaben.org"
request_delay_ms = 2000

[sources.subsplease]
enabled = true
base_url = "https://subsplease.org"
request_delay_ms = 2000

# cardigann:1337x and cardigann:uindex are Cloudflare-fronted and answer 403
# to a plain request.
# An empty url disables solving, and those two then skip quietly — they return
# nothing and stay healthy, rather than failing. FlareSolverr's container
# publishes no host port by default, so this is usually a container IP.
[sources.flaresolverr]
url = "" # e.g. "http://192.168.64.3:8191/v1"
max_timeout_ms = 55000

[rules] # optional — omit for the built-in Plex-style naming
[rules.movie]
filename = "{title} ({year}) {edition}"
dest = "{title} ({year}) {edition}" # relative to [paths] movie_dir / uhd_movie_dir
[rules.tv]
filename = "{title} ({year}) - S{ss}E{ee}"
dest = "{title} ({year})/Season {ss}"
[rules.anime]
filename = "{title} ({year}) - S{ss}E{ee}"
dest = "{title} ({year})/Season {ss}"

[monitor]
poll_interval_secs = 30
confirm_absolute_mapping = true

[tmdb]
api_key = ""

[ui]
density = "compact" # or "balanced"

Configurable libraries

Open Preferences > Libraries to edit or remove Movies, UHD Movies, TV Shows, or Anime. Add Library expands the editor for a new entry such as Star Wars or Disney. Every library owns:

  • a display name and Movie, TV, or Anime organizer behavior;
  • its final library path;
  • a qBittorrent category;
  • optional comma-separated qBittorrent tags.

A library may also declare the fan edits it recognizes. That list is config-file-only in v0.3.2. [[libraries.editions]] entries are preserved across Preferences edits but there is no form for them yet.

Three limits worth knowing. A library that declares any editions requires one for every import into it (a Movies library with a single Extended entry would refuse ordinary films), so declare editions only on libraries whose whole contents are alternate cuts. A movie extracted from a TV season pack is renamed without an edition tag and without a refusal, because the edition gate guards the movie route only. And the Search rail resolves the tag from the indexer's result name while the organizer resolves it from qBittorrent's torrent name; Magnetarr does not force the two to agree, so an indexer that re-titles a release can preview a tag the import then refuses.

Existing configs remain valid. If [[libraries]] is absent, Magnetarr seeds the four established lanes from [paths] with categories movies, uhd, tv, and anime. Once a library list has been written, it is authoritative: removed established libraries stay removed, and even an empty list is valid. If Auto no longer has its established lane, Search asks for an explicit Library selection rather than silently choosing another destination.

Saving a library ensures its category and tags exist in qBittorrent. A missing category is created using staging_dir as its initial save path; an existing category and its save path are never edited. Search offers Auto plus every type-compatible library. Monitor resolves the final path and naming rule from the torrent's category, while tags remain optional qBittorrent metadata. Unknown categories fail during Verify before any filesystem move.

staging_dir is not a library. qBittorrent still controls download placement; Magnetarr uses this root as a safety boundary when removing leftover source data after a successful cross-filesystem organization.

Confirm-mapping gate

With confirm_absolute_mapping = true (the default), the GUI monitor holds an absolute-numbered anime batch before renaming whenever an episode's absolute number overflows the season it was headed for — e.g. episode 29 of a 28-episode Season 1 — as judged by TMDB's per-season episode counts. The confirm dialog shows each file's proposed SxxEyy; Confirm & Rename applies it (editable per file), Cancel keeps the torrent untouched and retains an Attention card whose Retry re-raises the dialog. The gate is config-file only and takes effect at the next monitor start or Process Now. It fails open: false, dry runs, an empty TMDB key, or any TMDB error organize exactly as before — and per-season numbering that fits its season never prompts. The CLI never holds.

Naming rules

Filename patterns and destination templates accept these tokens; unknown tokens render literally, and tokens with no value clean up (empty brackets and doubled separators collapse — a yearless show renders Show - S02E01 from the same pattern that yields Show (2022) - S02E01).

Token Value Notes
{title} Movie/show title From the parser, or TMDB when resolved
{year} Release year Optional for shows — cleans up when unknown
{ss} Season, 2-digit Resolved season (an explicit S00 special stays 00)
{ee} Episode portion of the tag Includes multi-episode tails: S01E01E02 renders ss=01, ee=01E02
{abs} Absolute episode number, 3-digit Only when the release arrived absolute-numbered (anime)
{quality} 2160p/1080p/720p/480p Scraped from the release name
{codec} x265, x264, HEVC, AV1, … Scraped from the release name
{source} BluRay, WEB-DL, WEBRip, … Scraped from the release name
{group} Release group Trailing -GROUP or leading [Group] (anime)
{edition} {edition-4K77} The complete Plex edition tag, from the owning library's editions list; renders as nothing when the library declares none

The file extension is appended automatically and is not a pattern token. Date-coded episodes (Show - 2025-03-25.mkv) and files with no episode tag keep their built-in naming. TV/Anime filename patterns must keep S{ss}E{ee} — upgrade detection finds existing episodes by tag (the GUI enforces this on save). A custom dest template disables the automatic year-refinement folder rename, so existing libraries are never mass-renamed by a template edit.

Retired: the Prowlarr bridge

Magnetarr used to reach extra indexers through a Prowlarr server. It no longer does: the native ports and the Cardigann definition runtime cover that list, so the bridge, its container, and [sources.prowlarr] were removed in v0.4.0.

Nothing needs doing to an existing install. Like the retired [sources.rutracker] section before it, a [sources.prowlarr] block left in an older config file is ignored on load and dropped the next time the GUI saves the configuration — searches run on the native engine either way. If you ran a Prowlarr container only for Magnetarr, it can be stopped.

Retired: the six hand-written HTML ports

LimeTorrents, Torrent Downloads, Shana Project, Tokyo Toshokan, 1337x and Uindex each had a hand-written scraper and a vendored Cardigann definition carrying the same id. Every fix had to land twice. The scrapers are gone; the definitions are the only implementation, seeded enabled so the six sites are searched exactly as before.

Nothing needs doing to an existing install — the mapping happens on the next load:

  • a [sources.<site>] block keeps its enabled state: enabled = false stays off, and a block that was on stays on;
  • a customised base_url becomes the definition's link, so a mirror keeps working. A base_url left at the shipped default is not carried over, since pinning the definition to one mirror is not what it meant;
  • request_delay_ms loses its override. The definition carries the site's own requestDelay — 3 s for 1337x, 2 s for the rest, which is exactly what the ports used — so the politeness is unchanged, but a hand-tuned number is not preserved;
  • the stale [sources.<site>] tables are dropped the next time the configuration is saved, the same way [sources.prowlarr] was.

The migrated entries are written as [indexers.definitions.<id>] — including [indexers.definitions.1337x], unquoted. Deleting one of those blocks re-seeds it on the next load, exactly as deleting [sources.<id>] re-enabled the port before; enabled = false is how you turn one off. Search results still name the site itself ("LimeTorrents"); it is the search diagnostics and health rows that read cardigann:<id> where they used to read the bare id.

🏷️ Metadata resolution

When a torrent name lacks the year (common for TV shows), the monitor resolves the canonical title and year automatically. This ensures Plex-standard folder naming:

Movie Name (Year)/Movie Name (Year).ext
Show Name (Year)/Season N/Show Name (Year) - S01E01.ext

Resolution chain (first match wins):

  1. 🎞️ IMDB Suggestion API — free, no key needed
  2. 🎥 TMDB Search API — year-aware filtering (primary_release_year for movies, first_air_date_year for TV); follow the TMDB setup
  3. 📝 Torrent name — if the year is already present
  4. 📁 Existing library folder — parsed name matched against disk, with automatic folder rename when the resolver provides a corrected canonical title

Cache keys include title, media type, and year — same-title entries from different years are resolved independently.

🔧 Troubleshooting

Issue Solution
qBittorrent connection failed Check URL in Preferences (default: http://localhost:8080), ensure Web UI is enabled
The sidebar's Indexers n/m row shows a red dot Activate the row (it opens the Indexers page) and read the failing indexer's status line; a definition also has a Test button that reports the reason. cardigann:1337x and cardigann:uindex need [sources.flaresolverr].url set and report a config-level skip without it
No results for specific quality Switch to "Any" — specific quality does hard filtering
Config not found Run the app once to auto-generate it, then see the platform path table
Permission denied moving files Check that configured paths exist and are writable
First launch left both ~/.config/plex-pipeline/ and ~/.config/magnetarr/ Should never happen — the migration is idempotent and uses fs::rename. If it does, the new dir wins; you can manually rm -rf ~/.config/plex-pipeline once you've confirmed the new dir is intact

🏗️ Architecture

Cargo workspace with three crates:

Crate Purpose
magnetarr-core Library: parsers, search engine, scoring, monitor, metadata, config, move log
magnetarr-cli CLI binary (clap)
magnetarr GUI binary (Slint)

Tech stack today: Rust 2021, Tokio async runtime, reqwest for HTTP, regex for parsers, Slint for GUI, clap for CLI, JSONL for the move log, TOML for config.

🤝 Heritage and attribution

If code is ported from Sonarr or Radarr (both GPL-3.0), it is legally clean because Magnetarr is GPL-3.0-or-later. Each ported file gets a header comment crediting the source commit, and THANKS.md is the canonical attribution list (currently a placeholder).

This project is also a Rust rewrite of the original Python plex-pipeline (archived, private). The Rust port is ~484× faster startup, ~30× faster parsing, ~5.6× less memory, and ~7.7× smaller binary than the PyQt6 original.

📜 Changelog

See CHANGELOG.md for the release history. The current release is v0.6.6.

The changelog — not git tags — is the canonical release record. Tagging lapsed once: v0.3.1 through v0.3.5 shipped untagged by choice and no backfill is planned. Every release from v0.3.6 onward carries an annotated tag, through v0.6.6.

⚖️ License

GPL-3.0-or-later — see LICENSE. This keeps any future port of GPL-3.0 Sonarr/Radarr code legally clean; the license is locked and will not change.