A CLI/TUI mod manager for Bethesda games on Linux.
ModSanity provides:
- Game detection for supported Steam installs.
- GOG/manual game path registration and detection.
- Mod install/remove/enable/disable workflows.
- Deployment to game directories (symlink, hardlink, or copy).
- FOMOD support with interactive wizard in the TUI.
- Plugin/load-order management.
- Nexus catalog population + mod browsing/import tooling.
- Queue-based download/install processing.
- Database-backed modlists.
- External tool launch via Proton.
- Automatic Steam library scanning and game detection.
- Proton prefix detection via
steamapps/compatdata/<app_id>. - Active game selection persisted in config.
- Install mods from archives (
.zip,.7z,.rar). - Remove, enable, disable, list, and inspect installed mods.
- Priority-based conflict resolution during deployment.
- Case-insensitive path normalization during deployment to avoid duplicate folder casing splits.
- Deployment methods:
symlink,hardlink,copy. - SKSE override behavior:
- SKSE runtime binaries (
skse*.exe,skse*.dll) are deployed next to the game executable. - SKSE-related files are always hard-copied (never linked), regardless of global deploy method.
- SKSE runtime binaries (
- Rescan staging directory to add/update existing mods in DB, re-index files/plugins, and report added/updated/unchanged/failed stats.
- FOMOD detection and parsing (
ModuleConfig.xml/info.xmlhandling, case-insensitive search). - Interactive TUI wizard flow for option selection and conditional installs.
- FOMOD plan persistence support in DB.
- CLI install path explicitly fails when a wizard is required (TUI required for interactive FOMOD).
- Plugin scanning (
.esp,.esm,.esl) from gameData. - Read/write
plugins.txtandloadorder.txt(Proton AppData paths). - Manual reorder and save from TUI.
- Native Rust auto-sort.
- Optional LOOT CLI sort if LOOT executable is available.
- Create/list/switch/delete profiles.
- Export/import profile files.
- Save modlists to file:
- Native JSON format.
- MO2-style text format.
- Load modlists from file (native and MO2 paths).
- Persist saved/imported modlists in SQLite (
modlists+modlist_entries). - TUI modlist editor for saved modlists (create/rename/delete modlists, enable/disable/reorder/delete entries).
- Import matching pipeline with DB catalog support and plugin-name-assisted matching.
- MO2 migration bridge command to apply plugin enabled/disabled state to installed mods.
- Local Nexus catalog population (REST-backed) and resume/status tracking.
- TUI browse/search with sort and pagination, file selection, and queueing.
- Requirement checks for selected mods in TUI (API key required).
- Persistent queue entries in DB.
- Batch processing with concurrent downloads.
- Optional download-only mode.
- Retry failed items and clear batch.
- Selectable Steam-managed Proton runtime detection (
steamapps/commonandcompatibilitytools.d). - Optional custom Proton command/path fallback.
- Per-tool runtime mode override (
protonornative). - Configurable tool executable paths for:
- xEdit, SSEEdit, FNIS, Nemesis, Symphony, BodySlide, Outfit Studio.
- Launch configured tools via Proton from CLI or TUI Settings.
- Configurable downloads directory override.
- Configurable staging/installed-mods directory override.
- Both are configurable from CLI and TUI Settings.
Current GameType implementations:
- Skyrim Special Edition (
skyrimse) - Skyrim VR (
skyrimvr) - Fallout 4 (
fallout4) - Fallout 4 VR (
fallout4vr) - Starfield (
starfield)
- Linux
- Rust toolchain (for source builds)
- Optional for
.rarextraction:unrar - Optional for LOOT sort:
lootexecutable - Nexus API key for Nexus features (browse/import/download/catalog populate)
git clone https://github.com/modsanity/modsanity.git
cd modsanity
cargo build --release
cp target/release/modsanity ~/.local/bin/./install.shXDG-backed paths used by the app:
- Config:
~/.config/modsanity/config.toml - Data:
~/.local/share/modsanity/ - Cache:
~/.cache/modsanity/
Important config keys:
active_gameactive_profilenexus_api_key[deployment]withmethod,backup_originals,purge_on_exitdownloads_dir_overridestaging_dir_override[external_tools]withproton_command, optionalproton_runtime, and tool paths
Example deployment config:
[deployment]
method = "symlink" # symlink | hardlink | copy
backup_originals = true
purge_on_exit = false# 1) Detect and select game
modsanity game scan
modsanity game list
modsanity game select skyrimse
# 2) Install a mod archive
modsanity mod install /path/to/mod.zip
# 3) Deploy
modsanity deploy
# 4) Check status
modsanity statusFor interactive workflows (FOMOD wizard, browse, queue review, modlist editor), launch:
modsanityExtended guides:
docs/quickstart.mddocs/migration/mo2.mddocs/ui/accessibility.mdCLI-Documentation.mddocs/verification/questions_phase_status.md
modsanity(launch TUI)modsanity --mods-dir <path> <command...>(runtime staging override)modsanity tuimodsanity statusmodsanity deploy [--method symlink|hardlink|copy]modsanity doctor [--verbose]modsanity init [--game-id ... --platform ... --game-path ... --downloads-dir ... --staging-dir ... --proton-prefix ...]modsanity audit --dry-runmodsanity getting-started
modsanity game listmodsanity game scanmodsanity game select <name>modsanity game infomodsanity game add-path <game_id> <path> [--platform steam|gog|manual] [--proton-prefix <path>]modsanity game remove-path <game_id> <path>
modsanity mod listmodsanity mod install <path>modsanity mod enable <name>modsanity mod disable <name>modsanity mod remove <name>modsanity mod info <name>modsanity mod rescan
modsanity profile listmodsanity profile create <name>modsanity profile switch <name>modsanity profile delete <name>modsanity profile export <name> <path>modsanity profile import <path>
modsanity import modlist <path> [--auto-approve] [--preview]modsanity import status <batch_id>modsanity import apply-enabled <path> [--preview]
modsanity queue listmodsanity queue process --batch-id <id> [--download-only]modsanity queue retrymodsanity queue clear --batch-id <id>
modsanity modlist save <path> [--format native|mo2]modsanity modlist load <path> [--auto-approve] [--preview]
modsanity nexus populate --game <domain> [--reset] [--per-page N] [--max-pages N]modsanity nexus status --game <domain>
modsanity deployment showmodsanity deployment set-method <symlink|hardlink|copy>modsanity deployment set-downloads-dir <path>modsanity deployment clear-downloads-dirmodsanity deployment set-staging-dir <path>modsanity deployment clear-staging-dirmodsanity deployment migrate-staging <from> <to> [--dry-run]
modsanity tool showmodsanity tool list-protonmodsanity tool use-proton <runtime-id|auto>modsanity tool clear-proton-runtimemodsanity tool set-proton <path-or-command>modsanity tool set-path <tool> <path>modsanity tool set-runtime <tool> <proton|native>modsanity tool clear-runtime <tool>modsanity tool clear-path <tool>modsanity tool run <tool> [-- <args...>]
Tool IDs:
xedit,ssedit/sseedit,fnis,nemesis,symphony,bodyslide,outfitstudio
Function keys:
F1ModsF2PluginsF3ProfilesF4SettingsF5ImportF6QueueF7Nexus CatalogF8Modlists
Global keys:
?helpggame selectqquit
Help overlay:
?opens/closes the full help overlay.- Help is paginated and includes TUI keybindings plus a CLI command map.
- Navigate help pages with
n/Right/PgDnandp/Left/PgUp.
Settings notes:
- Deployment method, backup toggle, API key, default mod directory, downloads/staging overrides.
- Proton runtime selection, Proton command, and external tool paths are editable.
llaunches the selected tool when a tool-path row is selected.
- Nexus-powered flows require a configured
nexus_api_key. - CLI install cannot complete interactive FOMOD wizards; use TUI for those installs.
- RAR extraction requires
unraron the system.
cargo build
cargo test
cargo build --releaseMIT (LICENSE)