Releases: I4cTime/protonshift
ProtonShift v0.9.0
Highlights
AppImage compatibility (closes #13 follow-up)
The vendored-native-extension fix shipped in v0.8.11 was a no-op on read-only squashfs. v0.9.0 ships the real fix:
_vendor_compat.pymutatessys.pathin memory instead of trying toshutil.rmtreethe bundledpydantic_core. AppImage users on a different Python minor version now silently fall back to the system copy.electron/main.tsno longer setsPYTHONNOUSERSITE=""(CPython treats that as truthy and disables user site-packages — the opposite of what we wanted).- Bundled native deps trimmed from 5 to 1: switched
uvicorn[standard]-> bareuvicorn(drops uvloop / httptools / watchfiles, all unnecessary for a localhost workload).
Backend security hardening
- 2 critical command-injection fixes:
protontricks.py(whitelist Steam app id + winetricks verb) anddisplay.py:set_resolution(whitelist monitor name againstget_monitors(), bound width/height/refresh). - Removed
--print-tokenCLI flag (avoids credentials ending up in journald / Electron logs). - Defense-in-depth
validate_user_path()calls insideprefix.pyandsaves.pyso each FS function refuses paths outside the user-writable roots even when called directly. - Per-launch bearer-token auth on every API endpoint (except
/health//docs). - CORS narrowed to
127.0.0.1/localhost.
Reliability
- Atomic writes everywhere. All config / VDF / env / profile / MangoHud / Heroic writes go through
fsutil.atomic_write_text(tempfile + fsync +os.replace). VDF endpoints also refuse to write while Steam is running, so we can't clobberlocalconfig.vdfmid-session. - Centralized path sanitizer (
paths.py) at every API boundary: rejects.., absolute overrides, null bytes, anything outside~//run/media//media//mnt//tmp. - Hardened backup/restore against zip-slip and added size + file-count tripwires.
Refactor
- The 1183-LOC
api.pyis now anapi/package:_state.py,_models.py,_helpers.py,_app.py, and 8 domain-specific routers underroutes/(games, system, saves, mangohud, heroic, profiles, utility, health). - Consolidated FS helpers into
fsutil.py(dir_size, human_size, atomic writes). - Promoted
_resolve_heroic_root->resolve_heroic_root. - Centralized logging setup (
logging_setup.py). - TTL cache on
steam.discover_games(200 ms). - Real SDL controller GUIDs (16-byte little-endian bus/vendor/product/version).
gamescopereturns both an argv list and a shell-safe quoted string.
Cleanup
- Deleted dead GTK4 UI (
app.py,__main__.py,theme.css) and the obsoleteprotonshiftconsole script. - Single source of truth for the version (
game_setup_hub.__version__-> exposed via FastAPIapp.version).
Tests + tooling
- New
tests/suite: 96 cases (was 0), covering VDF round-trip, env-var management, gamescope arg building, controllers, paths, fsutil, vendor-compat, protontricks/display whitelists, and a FastAPI smoke suite. ruff+pyright(standard mode) both clean.
Compatibility
- Bundled vs system Python: when the AppImage runs against a Python whose minor version doesn't match the build, the API now falls back to a system copy of
pydantic_core. If neither matches, you'll get a loud actionable warning instead of a silentModuleNotFoundError. - Token auth: any external integration calling the API directly must now send
Authorization: Bearer <token>(the token is inPROTONSHIFT_API_TOKEN, set by Electron at launch).
Full changelog
ProtonShift v0.8.11
Fix: AppImage crash on Python 3.13 systems (#13)
The AppImage failed to start on distros with Python 3.13 (e.g. CachyOS, latest Arch) with:
ModuleNotFoundError: No module named 'pydantic_core._pydantic_core'
Cause: The vendored pydantic_core native extension was compiled for Python 3.12 and wouldn't load on 3.13 due to ABI mismatch.
Fix: Added a startup compatibility layer (_vendor_compat.py) that detects when vendored native extensions don't match the running Python version and removes them so the system-installed packages are used instead. Also added python3-pydantic as a package dependency for .deb and .rpm builds.
Other changes
- CI now pins Python 3.12 via
actions/setup-python - Vendor script cleans up
__pycache__and dist-info bloat
Install
| Format | File |
|---|---|
| AppImage | ProtonShift-0.8.11.AppImage |
| Debian/Ubuntu | protonshift_0.8.11_amd64.deb |
| Fedora/RHEL | protonshift-0.8.11.x86_64.rpm |
| Flatpak | ProtonShift-0.8.11-x86_64.flatpak |
Full Changelog: v0.8.10...v0.8.11
ProtonShift v0.8.10
Fixes
- Controllers page crash — Fixed "This page couldn't load" error on the Controllers page. The HeroUI Alert component was missing a required
Alert.Contentwrapper, causing a React render crash when the error state was shown (e.g. backend unreachable).
Install
| Format | File |
|---|---|
| AppImage | ProtonShift-0.8.10.AppImage |
| Debian/Ubuntu | protonshift_0.8.10_amd64.deb |
| Fedora/RHEL | protonshift-0.8.10.x86_64.rpm |
| Flatpak | ProtonShift-0.8.10-x86_64.flatpak |
Full Changelog: v0.8.9...v0.8.10
ProtonShift v0.8.9
Fix: Tool detection on Bazzite & immutable distros
Gamescope, MangoHud, GameMode, and Protontricks were reported as "Not Installed" on Bazzite and other immutable Fedora Atomic distros (Kinoite, Silverblue, SteamOS) even when present on the system. (#10)
What changed
- New
tool_check.pymodule — all tool detection now uses a three-tier strategy: normal PATH lookup → extra immutable-distro bin directories (/var/usrlocal/bin,/usr/lib/extensions/, NixOS paths) → tool-specific known paths - Electron PATH augmentation — the Python backend now inherits additional bin paths that AppImage/Flatpak wrappers may strip
- Bazzite/SteamOS install hints — the "Not Installed" screens for Gamescope and MangoHud now list Bazzite/SteamOS as the first entry (pre-installed)
- All detection in
gamescope.py,mangohud.py,presets.py,protontricks.py, anddisplay.pymigrated to the shared helper
Install
Download the package for your distro below. Requires Python 3.12+.
| Format | File |
|---|---|
| AppImage | ProtonShift-0.8.9.AppImage |
| Debian/Ubuntu | protonshift_0.8.9_amd64.deb |
| Fedora/RHEL | protonshift-0.8.9.x86_64.rpm |
| Flatpak | ProtonShift-0.8.9-x86_64.flatpak |
Full Changelog: v0.8.8...v0.8.9
ProtonShift v0.8.8
What's Changed
Full Changelog: v0.8.7...v0.8.8
ProtonShift v0.8.7
Fix: packaged UI looked broken (unstyled / blank)
The Electron build loaded the Next static export with file://. Root-relative URLs such as /_next/static/... and /splash.png do not resolve correctly in that context, so scripts and CSS never loaded.
0.8.7 serves renderer/out/ from http://127.0.0.1:<ephemeral-port> when packaged (same idea as dev on http://localhost:3000), then opens that URL in the window.
Install
.deb:sudo apt install ./protonshift_0.8.7_amd64.deb- AppImage:
chmod +x ProtonShift-0.8.7.AppImage && ./ProtonShift-0.8.7.AppImage
ProtonShift v0.8.6
Fix: packaged app would not start
0.8.5 shipped the Python source tree but not FastAPI / Uvicorn / VDF, so the backend exited immediately and the window never appeared. 0.8.6 vendors those dependencies into the AppImage and .deb.
Install
- .deb:
sudo apt install ./protonshift_0.8.6_amd64.deb(orsudo dpkg -i …thensudo apt-get install -fif needed) - AppImage:
chmod +x ProtonShift-0.8.6.AppImage && ./ProtonShift-0.8.6.AppImage
You still need Python 3.12+ as python3 on your PATH; everything else for the API is bundled.
Debug from a terminal
If anything still fails, run /opt/ProtonShift/protonshift from a terminal and check [python] lines on stderr.
ProtonShift v0.8.5
ProtonShift v0.8.5
Linux game configuration toolkit — unified library, launch options, Proton/Wine tools, Gamescope builder, MangoHud editor, environment profiles, saves, and more.
Stack
- Electron 39 + Next.js 16 + React 19 + Tailwind CSS v4 + HeroUI v3
- Python FastAPI backend
- AppImage and
.debbuilds
Installation
Download ProtonShift-0.8.5.AppImage or protonshift_0.8.5_amd64.deb from the assets below.
# AppImage
chmod +x ProtonShift-0.8.5.AppImage
./ProtonShift-0.8.5.AppImage
# .deb
sudo dpkg -i protonshift_0.8.5_amd64.deb