reelsort
v0.3.1
Published
CLI to rename, organize, and manage your movie and TV library — Plex-compatible naming, hardlink support, and automated watch mode.
Downloads
2,174
Maintainers
Readme
ReelSort
A CLI to organize and manage your media library. Renames messy download filenames into clean, consistent formats, moves files into the right destination folders, tracks everything in a local SQLite database, and keeps your library inspectable with a single command.
Works on macOS, Windows, and Linux.
Installation
npm install -g reelsortPrerequisites
- Node.js >= 18
- ffmpeg — optional, required only for
reelsort probe
Quick Start
# Tell ReelSort where your downloads land and where your library lives
reelsort config add source ~/Downloads
reelsort config set dest movie /Volumes/Media/Movies
reelsort config set dest tv /Volumes/Media/TV
# Preview what would be imported without touching anything
reelsort --dry-run scan
# Import
reelsort scanGlobal Options
--dry-run (-n) and --verbose (-v) are top-level flags that work with any command:
reelsort --dry-run scan # preview an import without touching anything
reelsort --dry-run watch # run the watcher in observe-only mode
reelsort --dry-run undo # see what would be reversed
reelsort --verbose scan # show skipped items alongside imported onesBecause these are root-level flags, they go before the subcommand name.
Commands
reelsort config
Manage configuration stored at ~/.config/reelsort/config.json.
reelsort config add source <dir> # add a source directory
reelsort config remove source <dir> # remove a source directory
reelsort config set dest movie <dir> # set movie destination
reelsort config set dest tv <dir> # set TV destination
reelsort config set dest ps3 <dir> # set PS3 destination
reelsort config set language <code> # subtitle language (default: eng)
reelsort config set tmdb-key <key> # TMDb API key
reelsort config set format movie <fmt> # movie naming format
reelsort config set format episode <fmt> # episode naming format
reelsort config set format season <fmt> # season folder format
reelsort config show # print current configMultiple sources are supported — useful if your torrent client and browser downloads land in different folders:
reelsort config add source ~/Downloads
reelsort config add source /Volumes/External/uTorrent/Completedreelsort add <name>
Register a TV show for scanning. Searches TMDb by name, shows an interactive picker when multiple results are found (with a clickable link to each candidate's TMDb page), and creates the show folder in your TV destination.
reelsort add Severance
reelsort add "The Bear"TV episodes are only imported during reelsort scan if the show is registered. Use reelsort link to register shows that already exist on disk.
reelsort scan
Import media from all configured sources into their destinations. Parses raw download filenames, renames files, creates folder structure, and records every import in the database.
reelsort scan # move files to destinations
reelsort scan --hardlink # hardlink instead of moving (great for seeders)
reelsort scan --type movie # only process movies
reelsort scan --auto # auto-register unrecognised TV shows instead of skipping
reelsort scan --interactive # prompt when a duplicate is ambiguous
reelsort scan --force # replace all duplicates without prompting
reelsort --dry-run scan # preview without touching anything
reelsort --verbose scan # show skipped itemsTV episodes are skipped unless the show has been registered via reelsort add or reelsort link. --auto restores the old behaviour: unregistered shows are created on the fly without prompting.
Duplicate handling
When a file already exists at the destination, ReelSort compares quality automatically:
- Clear upgrade (higher resolution, or better codec at the same resolution, e.g. x265 replacing x264) — the existing file is trashed and the new one takes its place, no prompt.
- REPACK / PROPER tagged files — always auto-replace, same as a quality upgrade.
- Ambiguous (same quality, or quality can't be determined from the filename) — skipped silently by default. Pass
--interactiveto get a prompt:
Duplicate: The Dark Knight (2008)
A — keep existing [1080p x264]
B — keep incoming [1080p x264]
Skip--force skips the comparison entirely and replaces every duplicate unconditionally.
TV output creates the full folder structure:
TV/
Severance (2022)/
Season 2/
2x01.mkvSeason folders are matched by number if they already exist under any naming convention. New season folders are created using your configured format.
reelsort watch
Watch all configured sources continuously and auto-import new files as they arrive. Same logic as scan, triggered per item with a debounce to handle large downloads that arrive in chunks.
reelsort watch
reelsort watch --hardlink
reelsort watch --auto
reelsort --dry-run watch # observe what would be imported without moving anything
reelsort --verbose watch # show skipped items--dry-run is especially useful before you commit to automated importing — run it for a while to build confidence that ReelSort is routing everything correctly, then restart without the flag when you're ready.
Press Ctrl+C to stop.
reelsort clean
Remove source files that were already imported via hardlink or copy. Safe to run while seeding — if a file is locked by your torrent client, it is skipped and left for the next run.
reelsort clean # remove imported source files
reelsort clean --older-than 14d # only clean imports older than 14 days
reelsort --dry-run clean # preview what would be removed--older-than accepts d (days), h (hours), or m (minutes).
reelsort rename
Rename media files in-place inside a directory. Useful for cleaning up an existing library that wasn't imported through scan.
reelsort rename <dir>
reelsort rename <dir> --type movie
reelsort rename <dir> --type tv
reelsort rename <dir> --type ps3
reelsort --dry-run rename <dir>
reelsort --verbose rename <dir>Renames folders and their primary video file to match your configured movie format. Keeps one subtitle file (matching your configured language) and removes everything else.
reelsort reset
Rename episode files inside a season folder to match your configured episode format. Useful for seasons that were copied in without going through scan.
reelsort reset <dir> # e.g. "TV/Severance/Season 2"
reelsort reset <dir> --double # episodes are double-length (1x01-1x02)
reelsort --dry-run reset <dir> # preview renames without applying themThe season number is detected automatically from the folder name. The show title is read from the parent folder.
reelsort split
Split a flat directory of absolutely-ordered episodes into season folders, renaming files to your configured episode format along the way. Useful for anime and other shows that distribute episodes with a single running number rather than per-season numbering.
Provide the directory followed by the number of episodes in each season, in order:
reelsort split ./yuyuhakusho 12 10 12 20 24
# Season 1: 12 episodes, Season 2: 10, Season 3: 12, Season 4: 20, Season 5: 24ReelSort validates that the total of all counts matches the number of video files in the directory before touching anything. If the numbers don't add up, it exits with an error and nothing is moved.
reelsort --dry-run split ./yuyuhakusho 12 10 12 20 24 # preview first
reelsort split ./yuyuhakusho 12 10 12 20 24 # then applyFiles are sorted alphabetically before splitting, so the sort order must match episode order. Season folders are created using your configured season format. No TMDb key required.
reelsort probe
Index your library using ffprobe to get accurate codec and resolution for every video file. Results are stored in SQLite and used by reelsort list. Run this once to populate your existing library, then re-run whenever you add files outside of scan.
reelsort probe # index all destinations
reelsort probe --type movie # index only movies
reelsort probe --force # re-probe files already indexed
reelsort --verbose probe # show each file as it is probedRequires ffmpeg to be installed. If ffprobe is not found, the command tells you rather than silently doing nothing.
reelsort list
Display your library in a table, sorted by year. Codec and resolution come from the probe index (populated by reelsort probe) if available, otherwise fall back to parsing the original download filename from import history.
reelsort list # list all configured destinations
reelsort list --type movie # list only movies
reelsort list --missing-subs # only show items without subtitles
reelsort list --codec x265 # filter by codec
reelsort list --resolution 1080p # filter by resolution
reelsort list --sort title # sort alphabetically (default: year)Example output:
MOVIE /Volumes/Media/Movies
──────────────────────────────────────────────────────────────────────
Title Year Res Codec Size Sub
──────────────────────────────────────────────────────────────────────
Dune Part Two 2024 2160p x265 58.2 GB ✓
Oppenheimer 2023 1080p x264 22.1 GB ✗
The Dark Knight 2008 — — 14.8 GB ✓
──────────────────────────────────────────────────────────────────────
3 of 3 itemsreelsort link
Register TV shows that already exist on disk — useful when migrating an existing library or after manually organising files. Walks your TV destination, looks up each unregistered folder in TMDb, and prompts when multiple matches are found (with a clickable link to each candidate's TMDb page).
reelsort link # register all unlinked shows
reelsort link --force # re-link shows that are already registeredShows with a single TMDb match are linked automatically. Shows not found in TMDb are skipped with a warning. Once registered, shows work with reelsort scan and reelsort missing.
reelsort ended
Mark a show as ended so it is excluded from reelsort missing. Run it again with --remove to restore a show to active.
reelsort ended # pick a show to mark as ended
reelsort ended --remove # pick an ended show to restoreAn interactive picker lists your tracked shows. Ended shows are skipped in reelsort missing and a count is shown at the bottom of that output.
reelsort shows
List all registered TV shows with their TMDb link, size on disk, and ended status.
reelsort showsExample output:
SHOWS /Volumes/Media/TV (3 registered)
────────────────────────────────────────────────────────
Title Size Linked Status
────────────────────────────────────────────────────────
Severance (2022) 28.4 GB ✓ tmdb active
The Bear (2022) 14.1 GB ✓ tmdb active
White Lotus (2021) 9.7 GB ✗ ended
────────────────────────────────────────────────────────
3 shows · 2 linked · 1 endedreelsort stats
Show library statistics — total counts and size per destination.
reelsort statsreelsort missing
Check your TV library against TMDb and report any episodes that have aired but aren't on disk. Requires a TMDb API key. Shows must be linked (via reelsort scan or reelsort link) to appear.
reelsort missing # check all shows
reelsort missing --show Severance # check a specific showExample output:
Severance (2022)
S01E04 — The You You Are
S01E07 — Defiant Jazz
2 missing episodes total
2 ended shows skippedOnly episodes with a past air date are reported — future episodes are ignored. Ended shows are excluded entirely.
reelsort history
Show rename or import history grouped by session.
reelsort history # rename history
reelsort history --imports # import history (what scan/watch moved)
reelsort history --limit 5 # show last 5 sessions (default: 10)
reelsort history --imports --limit 3reelsort undo
Reverse the last reelsort rename session, or undo the last batch of imports from reelsort scan or reelsort watch.
reelsort undo
reelsort --dry-run undo # see what would be reversed without doing itReelSort picks whichever session is more recent — rename or import — and undoes it:
- Rename sessions — every file and folder rename is reversed in place.
- Import sessions (movies, PS3, books) — the destination folder is moved back to its original source path.
- Import sessions (TV) — the episode file (and any companion subtitle) is sent to the Trash. The original download folder is not restored since it was deleted during import.
Hardlink and copy imports are not reversed (the source file was never touched).
reelsort diff
Compare two directories and show what's in one but not the other.
reelsort diff <dir1> <dir2>
reelsort diff <dir1> <dir2> --only mkv
reelsort diff <dir1> <dir2> --ignore nfo jpgConfiguration Reference
Naming Formats
All formats use token substitution. Unrecognized tokens are left as literals.
Movie format
| Token | Description |
|---|---|
| {title} | Movie title (required) |
| {year} | Release year |
| {edition} | Plex edition tag, e.g. {edition-Director's Cut} |
reelsort config set format movie "{title} ({year})" # default
reelsort config set format movie "{title} ({year}){edition}" # Plex editionsDetected editions: Director's Cut, Final Cut, Extended, Theatrical, Unrated, Anniversary Edition, Collector's Edition, Special Edition.
Episode format
| Token | Description |
|---|---|
| {s} | Season number, no padding |
| {ss} | Season number, 2-digit padded |
| {sss} | Season number, 3-digit padded |
| {e} {ee} {eee} | Episode number, same padding options |
| {title} | Show title |
| {name} | Episode title (from TMDb, requires API key) |
reelsort config set format episode "{s}x{ee}" # 1x01 (default)
reelsort config set format episode "S{ss}E{ee}" # S01E01
reelsort config set format episode "S{ss}E{ee} - {title}" # S01E01 - SeveranceSeason folder format
Uses the same {s} / {ss} / {sss} tokens.
reelsort config set format season "Season {s}" # Season 1 (default)
reelsort config set format season "Season {ss}" # Season 01
reelsort config set format season "S{ss}" # S01Subtitle Language
Set the preferred subtitle language code. When multiple subtitle files are present, the one matching this language is kept. Falls back to the first subtitle found.
reelsort config set language eng # default
reelsort config set language fre
reelsort config set language spaTMDb Integration
When a TMDb API key is configured, reelsort scan looks up each title before naming it. This corrects capitalization, fills in missing years, and resolves ambiguous names — the canonical TMDb title and year are used instead of whatever was in the download filename.
reelsort config set tmdb-key <your-key>Movie lookup — automatically uses the top result.
TV show lookup — if only one show matches, it is used automatically. If multiple shows share the same name, an interactive picker is shown so you can choose the right one:
◆ Multiple shows found for "Severance":
> 1. Severance (2022) — In a corporation, a group of employees have... <
2. Severance (2006) — Six office workers on a corporate retreat...
0. SkipArrow keys or number keys to select, Enter to confirm. Choosing 0 or Skip falls back to the parsed filename as-is. If TMDb is unreachable or returns no results, ReelSort falls back silently and continues.
Episode names — TMDb also supplies the episode title for each file. Use the {name} token in your episode format to include it:
reelsort config set format episode "S{ss}E{ee} - {name}"
# produces: S01E01 - Good News About Hell.mkvThe TMDb ID is stored alongside every import in the database, which powers the reelsort missing command.
Getting a free API key:
- Create a free account at themoviedb.org
- Go to Settings → API
- Request a developer key — no credit card or approval needed, it's instant
Keys are stored locally in ~/.config/reelsort/config.json and never leave your machine.
Workflows
Hardlink mode (recommended for seeders)
Hardlinks let your torrent client keep seeding the original file while your library gets the clean, organized copy — no extra disk space used. Only works within the same filesystem.
reelsort scan --hardlink # or reelsort watch --hardlink
# ... seed until done ...
reelsort clean # remove source files once seeding is finishedIf source and destination are on different filesystems, --hardlink automatically falls back to copy with a warning. Copied files are also tracked and cleaned up by reelsort clean.
One-time library cleanup
If you already have a library that was organized manually:
# Preview first, then apply
reelsort --dry-run rename /Volumes/Media/Movies
reelsort rename /Volumes/Media/Movies
# Index metadata
reelsort probe
# Inspect
reelsort listFully automated
reelsort config add source ~/Downloads
reelsort config set dest movie /Volumes/Media/Movies
reelsort config set dest tv /Volumes/Media/TV
reelsort watch --hardlinkDatabase
ReelSort stores its database at ~/.config/reelsort/reelsort.db. It tracks:
- renameHistory — every rename performed by
reelsort rename, used byreelsort undo - imports — every file imported by
reelsort scanorreelsort watch, used byreelsort undoandreelsort clean - shows — one row per TV show folder, storing the TMDb series ID and ended flag. Populated by
reelsort scanandreelsort link, used byreelsort missingandreelsort ended - mediaInfo — codec, resolution, and duration indexed by
reelsort probe, used byreelsort list
Platform Support
| Platform | Supported | |---|---| | macOS | ✓ | | Windows | ✓ | | Linux | ✓ |
File watching on macOS uses FSEvents, Windows uses ReadDirectoryChangesW, and Linux uses inotify — all via chokidar.
