1
0
Fork 0
An overlayfs based game mod manager
Find a file
2026-07-01 16:10:00 +01:00
src feat(modset): snapshot overlay upperdir into a reusable local mod 2026-07-01 16:10:00 +01:00
tests fix(import): keep already-archived mods, overwrite collection on re-import 2026-07-01 16:10:00 +01:00
.gitignore chore: mise 2026-04-23 20:57:20 +01:00
Cargo.lock build: drop unused tokio and async-trait deps 2026-06-12 19:14:28 +01:00
Cargo.toml build: drop unused tokio and async-trait deps 2026-06-12 19:14:28 +01:00
clippy.toml feat(config): self-heal config with defaults 2026-06-12 19:04:14 +01:00
LICENSE docs: add LICENSE, README, and Cargo package metadata 2026-05-01 22:44:06 +01:00
mise.toml feat: embed game in ModId, URL-only mod get 2026-05-21 21:22:52 +01:00
README.md docs: reword readme bullets and topic index entries 2026-05-31 22:15:07 +01:00
rustfmt.toml feat: fs mod store 2026-04-27 00:43:13 +01:00

stratum

Overlay-based mod manager for Linux games. Mods stack via FUSE + overlayfs over a read-only game directory. Collections and modsets are declarative TOML. Switch loadouts atomically; never touch the original game tree.

Handles Cyberpunk 2077 and Dyson Sphere Program.

Why

  • Game dir stays read-only. Verify integrity, hot-patch, redownload — none of it disturbs your mods.
  • Atomic loadout switching. Activate a different modset in one mount; no install / uninstall churn.
  • Per-modset saves. Optional saveset bind-mount redirects the game's save dir per loadout.
  • Deterministic state. Collections, modsets, savesets are TOML. Same config on two machines = same overlay.
  • Hexagonal core. Ports + adapters. Providers, games, and materializer passes are independent modules.

Install

cargo install --path .

Or mise run deploy to install and write zsh completions in one step (assumes mise + chezmoi).

Runtime binaries on PATH:

Binary Provides
fuse-overlayfs overlay filesystem in user space
unshare, mount, mountpoint mount namespace setup
fusermount3 (or fusermount) FUSE unmount

Gentoo:

emerge sys-fs/fuse-overlayfs sys-apps/util-linux sys-fs/fuse:3

Other distros: install the equivalent packages for your system.

Configure

~/.config/stratum/config.toml:

catalog_root = "~/.config/stratum/catalog"
data_root    = "~/.local/share/stratum"

[[store]]
name    = "personal"
path    = "~/mods/personal"
accepts = ["local"]

[[store]]
name    = "archive"
path    = "/mnt/games/stratum-archive"
accepts = ["nexus", "thunderstore"]

[game.cp2077]
dir = "~/games/cyberpunk2077"

[game.dsp]
dir = "~/games/dyson-sphere-program"

Mod files live in [[store]] blocks (one per concern; writes route by provider). Per-mod metadata lives single-store under catalog_root. [game.<abbrev>] dirs are fallbacks — when stratum runs as a Steam wrapper, STEAM_COMPAT_INSTALL_PATH wins.

Set NEXUS_API_KEY in your shell env for Nexus downloads. Never in TOML — config is dotfiles-trackable.

Store-config rules + migration recipes live in the config module docs (cargo doc --no-deps --open).

Use

Catalog names are game-prefixed (cp2077:base, dsp:main). Pass -g <abbrev> for commands that don't take a scoped name.

# Archive a downloaded mod manually
stratum -g cp2077 mod add local:my_mod:v1 --name "My Mod" --version "1.0" --path ./mod-files

# Or pull from Nexus / Thunderstore by URL (interactive file picker; FOMOD runs if present)
stratum mod get https://www.nexusmods.com/cyberpunk2077/mods/2987

# Group mods into a collection
stratum collection create cp2077:base
stratum collection add cp2077:base cp2077:nexus:2987:125853

# Build a modset from collections
stratum modset create cp2077:main
stratum modset add cp2077:main cp2077:base

# Saveset (optional) — per-modset save redirection
stratum saveset create cp2077:main

# Dry-run: show the overlay plan + env block
stratum run -n --modset cp2077:main

Steam launch

Primary use: invoke stratum as Steam's %command% wrapper. In Steam game properties → Launch Options:

/home/you/.cargo/bin/stratum run --modset cp2077:main -- %command%

STEAM_COMPAT_INSTALL_PATH and STEAM_COMPAT_APP_ID tell stratum which game dir + Proton prefix to target. Per-game env vars (WINEDLLOVERRIDES for hook DLLs, etc.) get applied automatically.

Manual launch

stratum run --modset cp2077:main -- ./start-game.sh

Dev

mise run check     # fmt + clippy + build
mise run test:all  # all tests, all features

Repo layout:

Path Role
src/core/ pure logic, ports, models. No IO.
src/adapters/ IO impls slotting into core ports
src/cli/ clap dispatch, structural validation
src/config.rs, src/deps.rs wiring
tests/ integration, system, litmus tests

API reference:

cargo doc --no-deps --open

Design notes live in module-level rustdoc (the crate root indexes them).

License

GPLv2. Code flows freely; improvements come back. See LICENSE.