Files
44r0n7 f984acf0e3 feat: hook reliability, hook-errors setting, sparse config, and logging
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>
2026-06-14 09:35:24 -04:00

16 KiB
Raw Permalink Blame History

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:

  1. install with cargo install
  2. ensure ~/.cargo/bin is 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 rename for human-readable game names
  • game forget to remove entries from observed history
  • gamewrap last to 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
  • status command
  • doctor preflight checks with color-coded output
  • dry-run launch plan preview
  • config edit to open config in $EDITOR
  • Config and profile export/import for sharing
  • notify test for 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, verbose
  • gamescope, gamescope-width, gamescope-height, gamescope-fps
  • fps-cap, vkbasalt
  • esync, fsync, large-address-aware
  • pre-launch, post-launch
  • env-vars (via profile env subcommands)

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, and dry-run are 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 install remains supported but is not the ideal end-user distribution path

Planned packaging targets:

  • Arch Linux / AUR
  • Debian / Ubuntu
  • Fedora / RPM

Packaging goals:

  • install gamewrap to 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:

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:

  • gamescope integration
  • vkBasalt integration
  • ✓ 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> to ProfileConfig and SharedProfileFile, shown at the top of exported .gamewrap-profile.toml files so ProtonDB/forum posts are self-documenting. CLI: gamewrap profile describe <name> <text> and profile clear-describe <name>. Preserved through import and shown in profile show/profile list. No tags, AppIDs, or author fields — those belong on the posting platform, not in the file.

Items 13 are now implemented. Remaining if development continues:

  1. Benchmark / recording profile presets — named templates that bundle several settings into a shareable starting point
  2. Graphics API detection (advisory only — see separate section)
  3. 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 doctor and 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=1 silently does nothing. Detection could skip the env var or warn in doctor.
  • Gamescope compatibility — Gamescope is Vulkan-only. If gamescope = on is 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 1 only 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 running doctor.
  • 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.dll in the game directory → DXVK (D3D9/10/11 via Vulkan)
  • Check for d3d12.dll → VKD3D-Proton (D3D12 via Vulkan)
  • Check for .dxvk-cache / .d3d12.cache files → reliable secondary signals
  • Native Linux ELFs: inspect imported libs with ldd or file — harder, lower priority

Guardrails if this is ever added:

  • Detection should be advisory only — never silently override user config
  • Emit warnings in doctor and dry-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/bin is on PATH in your desktop session so Steam can find it by name

Reason:

  • low maintenance
  • easy updates
  • Steam can resolve gamewrap by name if ~/.cargo/bin is 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_pretty likely 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-dynamic feature: may have been renamed to unstable-command in 4.6.x. Run cargo update && cargo test — if it fails, rename the feature flag in Cargo.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 settings outputs 36 settings in a flat, ungrouped list with no visual separation by tool
  • overlay (MangoHud) and performance (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 overlaymangohud (the MangoHud enable/disable toggle), consistent with mangohud-log
  • Rename performancegamemode (the GameMode enable/disable toggle)
  • Group gamewrap help settings into 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() in src/help.rs to accept an optional tool filter: gamewrap help settings gamescope
  • Propagate renames everywhere: Settings struct 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 list grows 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 an archived flag on the state entry, excluded from default game list
  • game list --all shows archived entries alongside active ones (visually marked)
  • game forget remains for permanent removal
  • game list shows 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 show output (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() and render_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 --json flag 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 gamewrap as 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.