Hook reliability: - Add hook-errors = "warn" | "fail" setting (default: warn); in fail mode, abort launch when pre-launch hook exits nonzero or can't execute - Ensure post-launch hook runs unconditionally, even when execute_wait() fails to spawn the game - Propagate game's real exit status via std::process::exit(); report post-hook failures clearly to stderr - Centralize hook execution via run_hook() helper (sh -c) New features in this batch: - Sparse config and profile support: only configured fields are written; unset fields fall back through profile → global chain - config show --effective flag: renders the fully-resolved view - Config migration: upgrades legacy flat config to current schema - Structured decision logging (src/log.rs) for session-level audit trail - Gamescope improvements: additional flags and validation - CHANGELOG.md tracking template releases Schema / UX: - HookErrors enum (Warn/Fail) added to Settings and ResolvedSettings - hook-errors key in keys.rs, mod.rs rendering, completion candidates, doctor output, help text, README, and dry-run display - 9 focused tests covering warn/fail behavior, exit propagation, round-trip (set/show/reset), profile round-trip, export/import Co-Authored-By: claude-flow <ruv@ruv.net>
16 KiB
gamewrap Roadmap
Purpose
gamewrap is a Steam-first Linux game launcher wrapper that keeps Steam launch options short while moving launch behavior into a readable, persistent config.
The project is designed to make features like MangoHud and GameMode easier to use without requiring users to remember long launch commands, environment variables, or per-game flag combinations.
Core product goals:
- keep Steam launch options simple
- prefer human-friendly configuration over flag-heavy one-off commands
- fail clearly when launch requirements are not met
- keep runtime overhead low
- support both quick default usage and deeper profile-based customization
Current Direction
The current preferred Steam usage is:
gamewrap %command%
The preferred low-maintenance install approach is:
- install with
cargo install - ensure
~/.cargo/binis on PATH in the desktop session
This lets Steam resolve gamewrap by name without committing to long-term package maintenance yet.
Current Feature Set
Implemented features:
- Steam-first launcher flow with
gamewrap %command% - Default launch mode with MangoHud and GameMode
- Friendly setting names for all launch options
- Named game-specific profiles (flat two-tier: global defaults + per-game overrides)
- Per-profile environment variable overrides (
profile env set/unset/list/clear) - Manual executable-to-profile bindings
- Observed game history with launch count, timestamps, and display names
- Play time tracking per game (when post-launch hook is configured)
game renamefor human-readable game namesgame forgetto remove entries from observed historygamewrap lastto see the most recently played game- gamescope Wayland compositor integration
- vkBasalt post-processing integration
- FPS cap via MangoHud
- Proton esync/fsync/large-address-aware controls
- Pre-launch and post-launch shell hooks
statuscommanddoctorpreflight checks with color-coded outputdry-runlaunch plan previewconfig editto open config in$EDITOR- Config and profile export/import for sharing
notify testfor graphical notification verification- ANSI color output (respects NO_COLOR, CLICOLOR, CLICOLOR_FORCE)
- Shell completion with live candidates (profiles, games, settings)
- Clear runtime dependency checks and actionable error messages
Friendly settings supported:
mangohud,gamemode,steam-host-libs,game-libs,verbosegamescope,gamescope-width,gamescope-height,gamescope-fpsfps-cap,vkbasaltesync,fsync,large-address-awarepre-launch,post-launchenv-vars(viaprofile envsubcommands)
v1 Done Criteria
The project can be considered functionally complete for v1 when all of the following are true:
- Steam launch works reliably with the chosen install method
- MangoHud enable/disable works correctly
- GameMode enable/disable works correctly
doctor,status, anddry-runare trustworthy for normal troubleshooting- launch failures are visible and understandable
- README and CLI help are clear enough for a new user
- no major known bugs remain in the core launch path
- native Linux games validated in real testing
- Proton / Windows games validated in real testing
- one intentional failure case tested
v1 complete — 2026-05-31.
Validation Still Desired
Real-world validation to finish before calling v1 done:
- test at least one native Linux game
- test at least one Proton / Windows game
- test one intentional failure case
- confirm Steam launch behavior with the preferred install method
- confirm notification behavior for internal launcher failures
- confirm that profile binding works on an actual game executable
Packaging and Distribution Plan
Long-term packaging direction:
- distro-native packages first
cargo installremains supported but is not the ideal end-user distribution path
Planned packaging targets:
- Arch Linux / AUR
- Debian / Ubuntu
- Fedora / RPM
Packaging goals:
- install
gamewrapto a system-visible path such as/usr/bin/gamewrap - allow Steam launch options to use
gamewrap %command% - avoid requiring absolute paths for normal packaged installs
Packaging status:
- deferred for now in favor of low maintenance
- still an explicit project direction, not abandoned
Repository:
- Gitea: https://git.44r0n.cc/44r0n7/gamewrap.git (canonical for now)
- Issue tracker: https://git.44r0n.cc/44r0n7/gamewrap/issues
Still undecided:
- homepage URL
- release hosting / distribution channels
- whether to mirror to GitHub
Deferred Feature Expansion
Features that were deferred from the initial scope and are now implemented:
- ✓
gamescopeintegration - ✓
vkBasaltintegration - ✓ Custom environment presets (per-profile env var overrides)
- ✓ Proton and Wine compatibility toggles (esync, fsync, large-address-aware)
Features still deferred:
- Benchmark and recording profile presets (named templates that bundle several settings)
- Additional launcher helpers beyond the current set
- Profile description field for community sharing — add
description: Option<String>toProfileConfigandSharedProfileFile, shown at the top of exported.gamewrap-profile.tomlfiles so ProtonDB/forum posts are self-documenting. CLI:gamewrap profile describe <name> <text>andprofile clear-describe <name>. Preserved through import and shown inprofile show/profile list. No tags, AppIDs, or author fields — those belong on the posting platform, not in the file.
Recommended Expansion Order
Items 1–3 are now implemented. Remaining if development continues:
- Benchmark / recording profile presets — named templates that bundle several settings into a shareable starting point
- Graphics API detection (advisory only — see separate section)
- Additional launcher helpers only if they clearly improve the main use case
Future Proton and Compatibility Controls
One planned expansion area is support for common Steam/Proton launch adjustments that users often copy from compatibility guides, community comments, or ProtonDB reports.
Examples of future controls that may be worth supporting:
- DXVK-related toggles
- VKD3D-related toggles
- esync/fsync toggles
- Wine debug environment controls
- fullscreen and compositor-related tweaks
- launch-time environment overrides for specific games
- Proton-specific compatibility presets that bundle several known-good settings
This should not become a free-form dump of obscure environment variables by default. The intended direction is:
- expose the most common useful adjustments with friendly names
- keep raw environment overrides available only as an advanced escape hatch if ever added
- prefer reusable presets and profiles over forcing users to remember low-level variables
- use
doctorand help text to explain what a toggle actually changes
Potential sources of future ideas:
- recurring compatibility patterns seen in ProtonDB reports
- common launch command snippets shared in Linux gaming communities
- settings that repeatedly solve real issues in actual testing
Guardrails for this work:
- do not blindly mirror every ProtonDB workaround
- avoid adding toggles that are highly game-specific unless they can be grouped into a sensible preset model
- keep the main UX readable and non-intimidating
- require a clear explanation in help text for every added compatibility control
Graphics API Detection (Maybe)
A potential future addition: detect a game's graphics API at launch time and use that to surface warnings or skip inapplicable settings. Not on the roadmap yet, but worth revisiting.
Specific cases where it would help:
- vkBasalt safety — vkBasalt only works with Vulkan. For OpenGL or WineD3D games,
ENABLE_VKBASALT=1silently does nothing. Detection could skip the env var or warn indoctor. - Gamescope compatibility — Gamescope is Vulkan-only. If
gamescope = onis set but the game uses OpenGL, it will fail or fall back unexpectedly. A preflight warning would catch this. - DXVK vs VKD3D-Proton env hints — Per-profile overrides like
DXVK_ASYNC 1only matter for D3D9/10/11 games (DXVK). D3D12 games use VKD3D-Proton with a different set of vars. Detection could surface a mismatch warning when runningdoctor. - MangoHud invocation method — MangoHud works as both a command prefix and an env var injection. The env var path works better for some Vulkan games. Detection could pick the right method.
How detection would likely work in practice:
- Check for
d3d9.dll/d3d11.dll/dxgi.dllin the game directory → DXVK (D3D9/10/11 via Vulkan) - Check for
d3d12.dll→ VKD3D-Proton (D3D12 via Vulkan) - Check for
.dxvk-cache/.d3d12.cachefiles → reliable secondary signals - Native Linux ELFs: inspect imported libs with
lddorfile— harder, lower priority
Guardrails if this is ever added:
- Detection should be advisory only — never silently override user config
- Emit warnings in
doctoranddry-run, not at actual launch time - Degrade gracefully when detection is inconclusive (most common case)
- Do not make profile selection automatic based on detection results
The "avoid" note in Product Boundaries refers to automatic profile selection based on detection, not to using detection for diagnostics and warnings. Those are meaningfully different.
Product Boundaries
Things gamewrap should continue to optimize for:
- simple Steam usage
- low system impact
- minimal always-on behavior
- understandable configuration
- useful diagnostics
Things to avoid unless clearly justified:
- automatic profile selection based on graphics API or runtime detection (advisory warnings are fine)
- heavy background services
- large dependency trees just to support optional extras
- turning the project into a general desktop/session manager
Installation Strategy for Now
Short-term recommended install strategy:
cargo install --path . --force— installs to~/.cargo/bin/gamewrap- Ensure
~/.cargo/binis on PATH in your desktop session so Steam can find it by name
Reason:
- low maintenance
- easy updates
- Steam can resolve
gamewrapby name if~/.cargo/binis on session PATH - no distro package maintenance burden yet
Dependency Maintenance (post-1.0)
Checked 2026-05-31. Most crates are on current patch versions via cargo update. Two deferred upgrades:
- toml 0.8 → 1.x: top-level
from_str/to_string_prettylikely unchanged but the 1.x release has low-level Deserializer/Serializer API changes. Verify against 1.x docs before upgrading. Low urgency — 0.8 is still maintained. - owo-colors 1.x → 4.x: major version jump. Our usage (
.green(),.bold(),.dimmed(),.cyan(),OwoColorize) is fundamental and unlikely to have changed, but read the changelog before upgrading. Low urgency — 1.x works fine. - clap_complete
unstable-dynamicfeature: may have been renamed tounstable-commandin 4.6.x. Runcargo update && cargo test— if it fails, rename the feature flag inCargo.toml. Low risk, one-line fix if needed.
Notes for Future Work
Before starting packaging or deferred features, re-check:
- whether the install story should remain PATH-based for personal use
- whether the project is going public
- whether package maintenance is worth the overhead
- whether v1 behavior is stable enough to freeze the main CLI/config model
Post-v1 Backlog
Logged 2026-06-06. Priority order reflects dependencies — B1 sets naming used by B5, and JSON output (B6 Phase 1) is prerequisite for any GUI work.
B1 + B4 — Settings grouping, tool-prefixed names, help system overhaul
Problem:
gamewrap help settingsoutputs 36 settings in a flat, ungrouped list with no visual separation by tooloverlay(MangoHud) andperformance(GameMode) have no tool prefix while every gamescope/vkbasalt/mangohud-log setting already does- A gamescope configuration note currently sits orphaned between log options and the gamescope settings block in help output
Proposed changes:
- Rename
overlay→mangohud(the MangoHud enable/disable toggle), consistent withmangohud-log - Rename
performance→gamemode(the GameMode enable/disable toggle) - Group
gamewrap help settingsinto tool-based sections: Core, MangoHud, GameMode, Gamescope, vkBasalt, Proton/Wine, Hooks & Logging - Move the gamescope configuration note into the Gamescope section header (fixes B4)
- Enhance
topic_text()insrc/help.rsto accept an optional tool filter:gamewrap help settings gamescope - Propagate renames everywhere:
Settingsstruct fields, CLI parser,config/keys.rs, TOML serialization, shell completion, tests, README, docs - Add a migration path for existing configs using the old names (clear error pointing to new name, or silent rename on load)
Note: Breaking change — existing config files and profiles using overlay or performance will need migration. Sets the naming foundation for B5.
Key files: src/help.rs, src/config/schema.rs, src/config/keys.rs, src/config/mod.rs, src/cli.rs, src/completion.rs, tests/, README.md
B2 — Large game list management
Problem:
- After using gamewrap on many games (demos, uninstalled games, one-offs),
game listgrows without bound - The only removal option is
game forget(hard deletion); no way to soft-hide entries
Proposed changes:
- Add
game archive <name-or-exe>/game unarchive <name-or-exe>— sets anarchivedflag on the state entry, excluded from defaultgame list game list --allshows archived entries alongside active ones (visually marked)game forgetremains for permanent removalgame listshows an entry count and a hint if the list exceeds a threshold (e.g. 20 entries)
Key files: src/cli.rs, state file handling in src/config/mod.rs, src/detect.rs, tests
B3 — Profile export semantics
Question: When a profile is exported to share:
- Option A — sparse: Export only what was explicitly set in the profile. Recipient's globals fill the rest at their end. Simple and portable; behavior depends on recipient's global config.
- Option B — effective: Export fully resolved settings (profile + globals baked in). Recipient gets a "known good" snapshot but must manually strip their own preferences.
- Option C — sparse + informational context: Export sparse profile, plus a
# context:comment block showing what the exporter's globals were at export time. Informational only — not interpreted by import.
Current behavior: Option A (sparse).
Resolved: Sparse export implemented. Profiles are now flat (no inheritance). Export produces only explicitly set settings.
B5 — Grouped, cleaner config show / profile show display
Problem:
config showoutput (especially--effective) has no visual grouping — 30+ settings appear in struct field order- No section headers separating e.g. gamescope settings from MangoHud settings
Proposed changes:
- Refactor
render_resolved_settings()andrender_profile_settings_with_indent()to emit settings under dimmed section headers using the same tool groups as B1 - Configured mode (default): only show a section header if that section has at least one configured value
- Effective mode (
--effective): always show section headers; show(nothing configured)per-section if empty
Dependency: Best done after B1, which defines the canonical section groupings. Can be scoped independently by hardcoding groups if B1 is deferred.
Key files: src/config/mod.rs, tests
B6 — JSON output flag + GUI (discussion needed)
Phase 1 — JSON flag (independent):
- Add
--jsonflag to read commands:config show,profile show,game list,status,dry-run - Write/mutating commands return
{"ok": true}or the updated state on success - Useful for scripting independently of any GUI
Phase 2 — GUI (dependent on Phase 1):
- Build a GUI that invokes
gamewrapas a subprocess and renders the JSON output - CLI remains the authoritative source of truth; GUI is a frontend only
Discussion points before Phase 2:
- Framework: egui (Rust, self-contained), iced (Rust async), Tauri (web frontend, heavier), GTK4 (gtk-rs)?
- Scope: full settings editor, profile manager, game list browser, or read-only status overlay?
- Packaging: GUI as an optional Cargo feature flag to keep the base CLI install slim?
Recommended starting point: Phase 1 JSON flag only.