Renamr

A fast, cross-platform media renamer — a ground-up rewrite of FileBot (via its FB-Mod fork), built from scratch as its own project: new stack, new architecture, new branding.

Status: early scaffold, but the core loop works end to end. The naming-expression engine is ported and tested, the faithfully-recreated two-pane UI is wired to real native file/folder loading and drag-and-drop, local filename-based season/episode detection ("Match") is working, real online metadata lookups against TMDB ("Fetch Data") are working, and the actual on-disk rename operation is wired up (same-directory rename, skip-on-conflict, with a confirmation step showing the full old-name/new-name plan before anything touches disk — there is no undo yet). Full media-metadata bindings and the fuzzy similarity/matching engine are not yet ported. See "Porting roadmap" below.

Why a rewrite, and why this stack

The original is a ~20k+ line Java/Swing app built with Ant. The goals were: faster startup and UI, faster matching/renaming, a codebase that's actually pleasant to work in, and a genuine rebrand — not a coat of paint.

Renamr is Tauri: a Rust core (crates/renamr-core, src-tauri) plus a TypeScript/React frontend (src), compiled to a small native binary per platform (Windows/macOS/Linux) with a system webview instead of shipping a bundled browser engine. That's the concrete "faster" win over both the original JVM/Swing app and an Electron-style rewrite: quick cold start, small binary, real OS-native windowing.

An earlier attempt used Kotlin + Compose Multiplatform to stay on the JVM and reuse FileBot's Java logic directly. That was abandoned (nothing was salvaged into this repo) after discovering the sandbox this was originally built in blocks Maven Central and the Gradle Plugin Portal, making it impossible to compile or test. Tauri was chosen as the replacement because both halves — Cargo via crates.io, npm via the public npm registry — are reachable, so every piece described as "done" below is actually compiled/tested, not just written and hoped for.

Compatibility notes

Goal: keep CLI flags, config file locations, and the outer { } naming-scheme template syntax compatible with FileBot conventions, so existing automation mostly keeps working.

One deliberate gap: FileBot's { } expressions ran arbitrary Groovy code (JVM-only). Renamr's Rust core has no Groovy engine, so expressions are evaluated with Rhai instead. Simple bindings ({n}, {s00e00}, {t}) are identical. More complex chained-method expressions will need small syntax tweaks (e.g. Groovy's .toUpperCase() → Rhai's .to_upper()) — Rhai already ships most of the common string/array methods FileBot's expression helpers wrapped, so most patterns translate directly.

Project layout

crates/renamr-core/   Pure Rust core: naming-expression engine (ported), local
                       filename-based season/episode matching (ported, `matching/`), a
                       TMDB metadata client (`web/tmdb.rs` — TV search + episode lookup,
                       tested against a mocked HTTP server via `mockito`), and the
                       on-disk rename engine (ported for the same-directory case,
                       `rename/`) — skip-on-conflict, no move/organize-into-folders yet.
                       Not yet ported: the fuzzy similarity engine, full media metadata
                       bindings, other web datasource clients (TVDB/AniDB/etc). No Tauri
                       dependency, so it builds and unit-tests standalone.
src-tauri/             Tauri app shell: exposes renamr-core as commands to the frontend
                       (naming-scheme rendering, filename matching, TMDB metadata fetch,
                       executing a rename plan, native file/folder dialogs, drag-and-drop
                       expansion), plus `settings.rs` (TMDB token, stored as JSON in the
                       OS app-config directory), app metadata/icons/window config
                       (tauri.conf.json).
src/                   React + TypeScript UI (Vite). Faithful recreation of the original
                       two-pane rename screen (Aurora theme) wired to real file loading,
                       drag-and-drop, live naming-scheme preview, local matching, TMDB
                       fetch (behind a Settings modal for the API token), and a
                       confirm-before-touching-disk modal for the actual rename.
scripts/gen_icons.py   Regenerates src-tauri/icons/ (placeholder branding — swap the
                       colors/glyph in the script, or replace the icons directly, to
                       change the look).

Building

Prerequisites: Rust (stable) + Cargo, Node.js 18+, and Tauri's platform prerequisites (see https://v2.tauri.app/start/prerequisites/ — on Linux this means libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev librsvg2-dev and a C toolchain; macOS/Windows need Xcode / the VS Build Tools + WebView2 respectively).

# Rust core (no UI deps needed):
cargo test -p renamr-core

# Full app in dev mode (opens a native window):
npm install
npm run tauri dev

# Production build (installer/bundle for your current OS):
npm run tauri build

Verified in the environment this was built in: cargo test -p renamr-core (all passing, including the TMDB client tests — those run against a local mock HTTP server via mockito, no live network or API key needed to build/test), cargo check -p renamr (compiles clean against real Tauri + GTK/WebKit system libraries), and npm run build (TypeScript type-checks, Vite bundles). The actual GUI window has not been visually verified anywhere yet — that sandbox has no display. Run npm run tauri dev on your machine to see and click through it for the first time.

Setting up TMDB (for "Fetch Data")

Everything else in the app works fully offline; "Fetch Data" is the one feature that needs a (free) TMDB account:

  1. Create a TMDB account, then go to Settings → API in your account and generate an API Read Access Token (not the older numeric "API Key" — Renamr uses the Bearer token method TMDB documents as the default).
  2. In the app, click the key icon ("TMDB Settings") next to Fetch Data and paste the token in. It's saved locally in the OS app-config directory and only ever sent to api.themoviedb.org.

Porting roadmap (not yet done)

Roughly in priority order — each references the original FileBot source file it's ported from, for anyone picking this up:

  1. Full naming-scheme bindings — net.filebot.format.MediaBindingBean (1354 lines): all the {n}, {s00e00}, {airdate}, {vf} (video format), etc. binding properties. Currently only whatever bindings you pass in manually are available.
  2. String/expression helper methods — net.filebot.format.ExpressionFormatMethods (636 lines): FileBot-specific Groovy string extensions like .pad(), .sortName(). Only a small subset (any, all_of, concat) is ported so far (crates/renamr-core/src/format/functions.rs); Rhai's built-ins cover some of the rest already.
  3. Matching/similarity engine — net.filebot.similarity.*. Local filename-based season/episode detection is done (crates/renamr-core/src/matching, ported from the pattern-matching half of SeasonEpisodeMatcher.java, adapted to Rust's regex crate which lacks lookahead/lookbehind — wired to the "Match" button). Now that TMDB is wired up (see item 5 below), EpisodeMetrics.java (849 lines, the fuzzy title-matching score cascade) is the next thing this actually blocks on: today "Fetch Data" just takes TMDB's first (TMDB-ranked) search result, which is right most of the time but has no way to catch a wrong pick among several similarly-named shows. DateMatcher also still not ported.
  4. Media detection — net.filebot.media.MediaDetection (1356 lines): ties file-name parsing + matching together to auto-identify what a file is.
  5. Web datasource clients — net.filebot.web.* (~40 files): TheMovieDB, TheTVDB, AniDB, OMDb, TVmaze, OpenSubtitles, etc. TMDB is done for TV (crates/renamr-core/src/web/tmdb.rs, reqwest + serde_json, Bearer-token auth) — search-by-name plus per-season episode lookup, wired to "Fetch Data". Picks the first (TMDB-ranked) search result rather than disambiguating between multiple plausible shows — a real fix needs the EpisodeMetrics fuzzy-matching port above. TMDB movie lookup and all other sources (TheTVDB, AniDB, OMDb, TVmaze, OpenSubtitles) are not yet started.
  6. Rename engine + CLI — net.filebot.cli.CmdlineOperations (1235 lines) and ArgumentBean (415 lines, the full flag surface: -rename, --db, --format, --action, --conflict, -get-subtitles, -script, etc.). The core same-directory rename operation is done (crates/renamr-core/src/rename, fixed skip-on-conflict policy, wired to the UI's Rename button behind a confirmation step). Not yet done: the --action variants beyond rename-in-place (move/copy/symlink to a different folder, which is what lets a naming scheme like {n}/{s00e00} organize files into subfolders), the --conflict variants beyond skip (auto-number, override), and the CLI flag surface itself.
  7. The rest of the UI — the Rename panel (file loading, drag-drop, live preview, local matching, confirmed rename) is built; the other five sidebar panels (Episodes/Subtitles/SFV/Filter/List) are still stub screens, plus Align up/down reordering, History, and Presets on the Rename panel itself are no-ops. There's also no per-item exclude inside the rename confirmation modal yet (it's all-or-nothing — use "Exclude Selected" on the file list beforehand to leave a file out entirely).
  8. Undo/history for renames — there is no undo yet; the confirmation modal before Rename executes is the only safety net right now. net.filebot.HistoryDialog/the original's rename-history log is the reference for what a real undo would look like.
  9. Packaging — code signing, auto-update, installers per platform via npm run tauri build.
S
Description
No description provided
Readme
4.5 MiB
2026-08-30 12:26:15 +00:00
Languages
Rust 61.8%
TypeScript 31.6%
CSS 6.3%
Python 0.3%