A desktop mod manager for PC games.
Scan, group, correlate, and manage your mods with Nexus Mods integration.
Built with Cyberpunk 2077 as the primary target, but designed to support any game on Nexus Mods.
This branch (main) is the Full edition with the Tauri in-app auto-updater. The Nexus-compliant edition without the auto-updater lives on nexus-compliant.
- Mod Scanner — Recursively discovers mod files from configured game paths, groups them by name similarity using TF-IDF + DBSCAN clustering, and computes file hashes for integrity tracking.
- Nexus Mods Integration — Connects to your Nexus account via SSO, syncs tracked/endorsed mods, fetches mod metadata, and searches Nexus by name via GraphQL v2.
- Endorse & Track — Toggle endorse/track status on any mod directly from card buttons, context menus, or the mod detail modal — syncs with the Nexus Mods API in real time.
- Auto-Correlation — Multi-tier matching pipeline: filename ID extraction, MD5 hash batch lookup, file content reverse lookup, endorsed/tracked sync, Nexus collection matching, mod requirement propagation, and Jaccard + Jaro-Winkler fuzzy matching. Manual reassign, confirm, and reject actions.
- Mod Installation — Install mods from downloaded archives with pre-install preview, conflict detection, skip/overwrite resolution, and enable/disable toggling. Includes FOMOD installer wizard for scripted mod packages.
- Clean Game Folder & Smart Deployment — Mod content stays in a managed staging directory (
<install>/downloaded_mods/). The game directory itself is untouched — only hardlinks (and REDmod junctions) are placed there when a mod is deployed via the/deployendpoint or auto-deploy on launch. Steam "Verify integrity" sees only vanilla files. Includes: Deploy / Undeploy controls, auto-compile REDmods (runsredMod.exe deployfor you on install/enable), drift detection (catches game patches or external tools that modify the game folder), one-time migration tool for pre-existing in-place installs, and instant profile switching via DB flag + link rebuild. - Conflict Detection — Multi-layer conflict engine: file-level overlap detection, archive-level resource conflicts with dependency-aware severity classification, redscript annotation analysis, TweakXL conflict scanning, and a conflict inbox for resolution. Disable, uninstall, or set load order preferences directly from the conflict view with Nexus Mods links on every archive.
- Load Order — View and manage archive load order with preference rules, modlist.txt generation, and dry-run previews.
- Archive Management — Browse archive contents, link/unlink archives to Nexus mods, delete, and clean up orphaned mod archives from the downloads staging folder.
- Download Manager — Download mod archives directly from Nexus Mods with progress tracking, NXM deep link handling, and premium account support.
- Trending Mods — Browse trending and recently updated mods from Nexus with one-click install, endorse, or track actions.
- Endorsed & Tracked Tabs — Browse your endorsed and tracked mods from Nexus with install actions or direct Nexus links.
- Mod Detail Modal — View full mod details including description, files, changelogs, requirements, DLC requirements, and action buttons without leaving the app.
- Profile Manager — Save, load, export, import, duplicate, and compare mod profiles to switch between mod configurations.
- Mod Update Checker — Compares local mod versions against Nexus metadata to surface available updates with one-click download.
- In-App Auto-Updater — Tauri updater checks the signed
latest.jsonendpoint on startup and prompts the user to download and install new versions in place. - Guided Onboarding — Three-step setup for Nexus Mods login, game configuration, and initial mod scan.
- Custom Titlebar — Native-feeling Tauri window with custom drag region and window controls.
| Layer | Technology |
|---|---|
| Backend | Python 3.12, FastAPI, SQLModel, SQLite |
| Nexus API | REST v1 + GraphQL v2, async httpx, respx (testing) — endpoint map |
| Matching | scikit-learn (TF-IDF, DBSCAN), jellyfish (Jaro-Winkler), tenacity (retry) |
| Hashing | xxhash (xxh64) |
| Frontend | React 19, TypeScript 5.9, Vite 7 |
| Styling | Tailwind CSS v4 |
| State | Zustand (client), TanStack React Query (server) |
| Desktop | Tauri v2 (Rust) |
| Bundling | PyInstaller (backend → sidecar .exe), NSIS (Windows installer) |
| Package Manager | uv (backend), npm (frontend) |
| Linting | Ruff (Python), ESLint (TypeScript) |
| Testing | pytest, pytest-asyncio, respx |
| CI/CD | GitHub Actions (consolidated CI gate, automated PR review, release pipeline) |
rippermod-manager/
├── backend/ # FastAPI + Python 3.12
│ ├── src/rippermod_manager/
│ │ ├── models/ # SQLModel tables
│ │ ├── schemas/ # Pydantic request/response models
│ │ ├── routers/ # API routers
│ │ ├── services/ # Business logic modules
│ │ ├── scanner/ # File discovery + grouping
│ │ ├── matching/ # TF-IDF, correlation, filename parsing
│ │ └── nexus/ # REST v1 + GraphQL v2 API clients
│ └── tests/ # 900+ tests
├── frontend/ # React 19 + TypeScript + Vite
│ ├── src/
│ │ ├── components/ # 25 mod components, 5 conflict components, 24 UI primitives
│ │ ├── pages/ # 6 pages
│ │ ├── hooks/ # 12 hooks (React Query, install, FOMOD, ...)
│ │ ├── stores/ # Zustand stores
│ │ └── lib/ # API client, SSE parser, utils
│ └── src-tauri/ # Tauri v2 Rust shell + sidecar lifecycle
├── docs/ # Architecture, Nexus API map, dual release strategy
├── scripts/ # Build + release helpers
└── .github/workflows/ # CI, release, PR review, CLA
Full file-level tree: docs/architecture.md
- Python 3.12+
- uv (Python package manager)
- Node.js 22+
- Rust (for Tauri desktop builds)
- Nexus Mods account (free — sign in via SSO)
git clone https://github.com/Y4rd13/rippermod-manager.git
cd rippermod-managercd backend
uv sync # Install dependencies
uv sync --extra test # Include test dependencies
# Start the dev server
uv run uvicorn rippermod_manager.main:app --reload --port 8425The API will be available at http://localhost:8425. The SQLite database is auto-created at %LOCALAPPDATA%\com.rippermod.app\ on Windows (or ~/.local/share/com.rippermod.app/ on Linux) on first startup.
Tip: Set
RMM_DATA_DIR=./datainbackend/.envto use a local data directory instead.
cd frontend
npm install
# Development (browser only, connects to backend at :8425)
npm run dev # Vite dev server at http://localhost:1420
# Development (Tauri desktop window)
npx tauri devOn first launch, the onboarding flow will guide you through:
- Nexus Mods login — Sign in with your Nexus Mods account via SSO
- Game setup — Configure your game install path (Cyberpunk 2077 auto-detects from Steam, GOG, and Epic)
- Initial scan — Discovers and groups your installed mods
Credentials are stored in the local SQLite database and masked in the settings UI.
cd backend
uv run uvicorn rippermod_manager.main:app --reload --port 8425 # Dev server
uv run ruff check src/ tests/ # Lint
uv run ruff format src/ tests/ # Format
uv run pytest tests/ -v # Tests (900+ tests)cd frontend
npm run dev # Vite dev server (port 1420)
npm run build # TypeScript check + Vite build
npm run lint # ESLint
npx tauri dev # Tauri desktop window
npx tauri build # Production desktop buildThe release build produces a standalone Windows installer (NSIS .exe) with the Python backend bundled as a sidecar:
# 1. Build backend as standalone .exe
cd backend
uv sync --extra build
uv run pyinstaller rmm-backend.spec --clean --noconfirm
# 2. Copy sidecar to Tauri binaries
.\scripts\build-backend.ps1
# 3. Build Tauri installer
cd frontend
npx tauri build
# Output: frontend/src-tauri/target/release/bundle/nsis/*.exeRipperMod ships two editions from a single repository. Releases are fully automated by semantic-release:
| Edition | Branch | Tags | App Auto-Updater | Distribution |
|---|---|---|---|---|
| Full | main |
vX.Y.Z |
Yes (Gist stable.json) |
GitHub Releases |
| Nexus | nexus-compliant |
vX.Y.Z-nexus.N |
No (manual download only) | Nexus Mods page |
- Full — Mod detail modal, trending, search, card images/stats, and in-app Tauri auto-updater
- Nexus — Nexus-policy-compliant build: redirects all discovery to nexusmods.com, no content display, no in-app auto-updater
Cherry-pick individual fixes between branches as needed. Never merge between branches — the editions are kept intentionally divergent.
Full details: docs/dual-release-strategy.md
All endpoints are prefixed with /api/v1/.
Games
| Method | Endpoint | Description |
|---|---|---|
GET |
/games/ |
List all configured games |
POST |
/games/ |
Add a new game |
GET |
/games/{name} |
Get game details |
DELETE |
/games/{name} |
Remove a game |
GET |
/games/{name}/version |
Get detected game version |
POST |
/games/validate-path |
Validate a game install path |
Mods
| Method | Endpoint | Description |
|---|---|---|
GET |
/games/{name}/mods/ |
List mod groups with files |
POST |
/games/{name}/mods/scan |
Scan and group mod files |
POST |
/games/{name}/mods/scan-stream |
Scan with SSE progress streaming |
POST |
/games/{name}/mods/correlate |
Match mods to Nexus downloads |
PATCH |
/games/{name}/mods/{id}/correlation/confirm |
Confirm a correlation |
DELETE |
/games/{name}/mods/{id}/correlation |
Reject correlation |
PUT |
/games/{name}/mods/{id}/correlation |
Reassign mod to different Nexus ID |
Install
| Method | Endpoint | Description |
|---|---|---|
GET |
/games/{name}/install/available |
List archives available for installation |
GET |
/games/{name}/install/installed |
List all installed mods |
POST |
/games/{name}/install/ |
Install a mod from an archive |
DELETE |
/games/{name}/install/installed/{id} |
Uninstall a mod |
PATCH |
/games/{name}/install/installed/{id}/toggle |
Enable/disable a mod |
GET |
/games/{name}/install/installed/{id}/dependents |
List mods that depend on this mod |
GET |
/games/{name}/install/preview |
Preview files before installation |
GET |
/games/{name}/install/conflicts |
Check for file conflicts |
GET |
/games/{name}/install/archives/{filename}/contents |
Browse archive file tree |
PUT |
/games/{name}/install/archives/{filename}/nexus-link |
Link archive to Nexus mod |
DELETE |
/games/{name}/install/archives/{filename}/nexus-link |
Remove Nexus link |
DELETE |
/games/{name}/install/archives/{filename} |
Delete an archive |
POST |
/games/{name}/install/archives/cleanup-orphans |
Clean up unused archives |
GET |
/games/{name}/install/redscript-conflicts |
Analyze redscript annotation conflicts |
POST |
/games/{name}/install/deploy |
Deploy all enabled mods to the game folder (hardlinks + REDmod junctions) |
POST |
/games/{name}/install/undeploy |
Remove all VFS links from the game folder (revert to vanilla) |
GET |
/games/{name}/install/deploy/status |
Drift report — counts of linked, missing, and foreign files per mod |
POST |
/games/{name}/install/migrate-to-vfs |
One-time migration: convert existing in-place installs to staged + linked layout |
GET |
/games/{name}/install/untracked-files |
List files in the game directory not owned by any installed mod |
FOMOD
| Method | Endpoint | Description |
|---|---|---|
GET |
/games/{name}/install/fomod/config |
Parse and return FOMOD configuration |
POST |
/games/{name}/install/fomod/preview |
Preview files with FOMOD selections |
POST |
/games/{name}/install/fomod/install |
Install archive with FOMOD selections |
Downloads
| Method | Endpoint | Description |
|---|---|---|
POST |
/games/{name}/downloads/ |
Start a download from Nexus |
GET |
/games/{name}/downloads/ |
List download jobs |
GET |
/games/{name}/downloads/{id} |
Get download job details |
POST |
/games/{name}/downloads/{id}/cancel |
Cancel a download |
POST |
/games/{name}/downloads/from-mod |
Download from mod detail page |
Profiles
| Method | Endpoint | Description |
|---|---|---|
GET |
/games/{name}/profiles/ |
List saved profiles |
POST |
/games/{name}/profiles/ |
Save current state as a profile |
GET |
/games/{name}/profiles/{id} |
Get profile details |
DELETE |
/games/{name}/profiles/{id} |
Delete a profile |
PATCH |
/games/{name}/profiles/{id} |
Update profile name/description |
POST |
/games/{name}/profiles/{id}/load |
Load a profile |
POST |
/games/{name}/profiles/{id}/preview |
Preview profile load changes |
POST |
/games/{name}/profiles/{id}/export |
Export profile as JSON |
POST |
/games/{name}/profiles/{id}/duplicate |
Duplicate a profile |
POST |
/games/{name}/profiles/import |
Import profile from JSON |
POST |
/games/{name}/profiles/compare |
Compare two profiles |
Nexus Mods
| Method | Endpoint | Description |
|---|---|---|
POST |
/nexus/sync-history/{name} |
Sync tracked/endorsed mods |
GET |
/nexus/downloads/{name} |
List synced downloads (filterable by ?source=endorsed|tracked) |
GET |
/nexus/downloads/{name}/search |
Search synced downloads by name |
GET |
/nexus/search/{name} |
Search Nexus Mods by name (GraphQL v2) |
GET |
/nexus/mods/{domain}/{mod_id}/detail |
Get full mod detail with files and changelogs |
GET |
/nexus/file-contents-preview?url=... |
Proxy Nexus file content preview |
POST |
/nexus/{name}/mods/{mod_id}/endorse |
Endorse a mod |
POST |
/nexus/{name}/mods/{mod_id}/abstain |
Remove endorsement |
POST |
/nexus/{name}/mods/{mod_id}/track |
Track a mod |
DELETE |
/nexus/{name}/mods/{mod_id}/track |
Untrack a mod |
POST |
/nexus/sso/start |
Start Nexus SSO session |
GET |
/nexus/sso/poll/{uuid} |
Poll SSO session status |
DELETE |
/nexus/sso/{uuid} |
Cancel SSO session |
Conflicts
| Method | Endpoint | Description |
|---|---|---|
GET |
/games/{name}/conflicts/ |
Detect conflicts between installed mods |
GET |
/games/{name}/conflicts/between |
Compare two specific mods |
GET |
/games/{name}/conflicts/summary |
Persisted conflict report (filterable by kind/severity) |
POST |
/games/{name}/conflicts/reindex |
Trigger full conflict re-scan |
GET |
/games/{name}/conflicts/archive-summaries |
Per-archive conflict summaries |
GET |
/games/{name}/conflicts/archive-details/{filename} |
Per-resource conflict details |
GET |
/games/{name}/conflicts/graph |
Conflict graph visualization data |
GET |
/games/{name}/conflicts/inbox |
List conflict inbox summaries |
GET |
/games/{name}/conflicts/inbox/{mod_id} |
Detailed conflicts for a mod |
POST |
/games/{name}/conflicts/inbox/{mod_id}/resolve |
Resolve conflicts by reinstalling |
POST |
/games/{name}/conflicts/inbox/{mod_id}/dismiss |
Dismiss mod's conflicts |
DELETE |
/games/{name}/conflicts/inbox/{mod_id}/dismiss |
Restore dismissed mod to inbox |
Load Order
| Method | Endpoint | Description |
|---|---|---|
GET |
/games/{name}/load-order/ |
Full archive load order with conflicts |
GET |
/games/{name}/load-order/modlist |
Ordered mod groups and preferences |
POST |
/games/{name}/load-order/prefer/preview |
Dry-run load order preference |
POST |
/games/{name}/load-order/prefer |
Add preference and write modlist.txt |
DELETE |
/games/{name}/load-order/preferences |
Remove all preferences |
DELETE |
/games/{name}/load-order/preferences/{winner}/{loser} |
Remove single preference |
Trending
| Method | Endpoint | Description |
|---|---|---|
GET |
/games/{name}/trending/ |
Get trending and recently updated mods (full edition only) |
Updates
| Method | Endpoint | Description |
|---|---|---|
GET |
/games/{name}/updates/ |
List available updates |
POST |
/games/{name}/updates/check |
Refresh update data from Nexus |
Settings, Onboarding
| Method | Endpoint | Description |
|---|---|---|
GET/PUT |
/settings/ |
Read/update app settings |
GET |
/settings/specs |
Get stored PC specs |
POST |
/settings/specs/capture |
Store PC specs |
GET |
/onboarding/status |
Get onboarding progress |
POST |
/onboarding/complete |
Complete onboarding |
POST |
/onboarding/reset |
Reset onboarding status |
The backend has a comprehensive test suite with 900+ tests covering all modules:
cd backend
uv sync --extra test
uv run pytest -vTests use an in-memory SQLite database for full isolation. External API calls are mocked with respx.
┌─────────────────────────────────────────────────┐
│ Tauri v2 Shell │
│ ┌───────────────────────────────────────────┐ │
│ │ React Frontend │ │
│ │ Zustand ─── React Query ─── SSE Parser │ │
│ │ ErrorBoundary ─── BackendGate │ │
│ └──────────────────┬────────────────────────┘ │
│ │ │
│ Sidecar Lifecycle Manager │
│ (spawn → health poll → events → kill on close) │
└─────────────────────┼────────────────────────────┘
│ HTTP / SSE (localhost:8425)
┌─────────────────────┼────────────────────────────┐
│ FastAPI Backend (PyInstaller sidecar .exe) │
│ ┌──────────┐ ┌──────────┐ │
│ │ Routers │ │ Scanner │ │
│ │ │ │ Grouper │ │
│ │ │ │Correlator│ │
│ └────┬─────┘ └────┬─────┘ │
│ │ │ │
│ ┌────┴─────────────┴────────────────────────┐ │
│ │ SQLite (SQLModel) │ │
│ │ %LOCALAPPDATA%/com.rippermod.app │ │
│ └───────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────┐ │
│ │ Nexus Mods API (httpx) │ │
│ │ REST v1 (mutations) │ GraphQL v2 (queries) │ │
│ └─────────────────────────────────────────────┘ │
└───────────────────────────────────────────────────┘
In production, the app ships as a single Windows installer (NSIS):
- Frontend → bundled by Vite into static assets inside the Tauri shell
- Backend → compiled by PyInstaller into
rmm-backend.exe, embedded as a Tauri sidecar - Startup → Tauri spawns the sidecar, health-polls
/health, emitsbackend-readyevent - Shutdown → Cancels active downloads, disposes DB engine, kills sidecar
- Data → Stored in
%LOCALAPPDATA%\com.rippermod.app\(DB, downloads) - Updates → Tauri updater plugin checks
stable.jsonon startup and downloads new signed installers in place
- Fork the repository
- Create a feature branch (
git checkout -b feat/my-feature) - Make your changes following the code style in CLAUDE.md
- Run tests (
cd backend && uv run pytest -v) - Commit using conventional commits (
feat:,fix:,refactor:, etc.) - Open a Pull Request — CI Gate must pass and an automated review is required before merge
All contributors must agree to the Contributor License Agreement before their PR can be merged. The main branch is protected: direct pushes, force pushes, and deletions are blocked.
This project is licensed under the GNU General Public License v3.0. See LICENSE for details.