f984acf0e3
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>
340 lines
16 KiB
Markdown
340 lines
16 KiB
Markdown
# 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:
|
||
|
||
```text
|
||
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:
|
||
|
||
- [x] Steam launch works reliably with the chosen install method
|
||
- [x] MangoHud enable/disable works correctly
|
||
- [x] GameMode enable/disable works correctly
|
||
- [x] `doctor`, `status`, and `dry-run` are trustworthy for normal troubleshooting
|
||
- [x] launch failures are visible and understandable
|
||
- [x] README and CLI help are clear enough for a new user
|
||
- [x] no major known bugs remain in the core launch path
|
||
- [x] native Linux games validated in real testing
|
||
- [x] Proton / Windows games validated in real testing
|
||
- [x] 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:
|
||
- 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:
|
||
- ✓ `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.
|
||
|
||
## Recommended Expansion Order
|
||
|
||
Items 1–3 are now implemented. Remaining if development continues:
|
||
|
||
4. Benchmark / recording profile presets — named templates that bundle several settings into a shareable starting point
|
||
5. Graphics API detection (advisory only — see separate section)
|
||
6. 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 `overlay` → `mangohud` (the MangoHud enable/disable toggle), consistent with `mangohud-log`
|
||
- Rename `performance` → `gamemode` (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.
|