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>
330 lines
11 KiB
Markdown
330 lines
11 KiB
Markdown
# gamewrap
|
|
|
|
`gamewrap` is a small Linux launcher for Steam games that keeps Steam launch options short while managing MangoHud, GameMode, gamescope, launch hooks, and per-game history from readable local config.
|
|
|
|
The main idea is simple:
|
|
- keep Steam launch options short
|
|
- move behavior into a readable config file
|
|
- make common settings easy to understand and change
|
|
- provide diagnostics when a launch setup is broken
|
|
|
|
For a normal Steam setup, launch options can stay as short as:
|
|
|
|
```text
|
|
gamewrap %command%
|
|
```
|
|
|
|
`gamewrap` stores its configuration outside Steam, supports reusable profiles, can bind specific executables to profiles, and tries to explain technical behavior in plain language instead of expecting users to remember environment variable names.
|
|
|
|
## Features
|
|
|
|
- Short Steam launch options
|
|
- Friendly setting names like `mangohud` and `gamemode`
|
|
- Persistent config outside the Steam UI
|
|
- Named profiles for reusable setups
|
|
- Flat game-specific profiles layered on global defaults
|
|
- Game-specific profile binding through `game bind`
|
|
- Quick access to the last played game through `gamewrap last`
|
|
- Play time and launch count tracking per game
|
|
- Game notes for remembering per-title quirks
|
|
- Filtered game listing and fuzzy game lookup
|
|
- Observed game cleanup through `game forget`
|
|
- Config export/import for backup and sharing
|
|
- Direct config editing through `config edit`
|
|
- Profile export/import for sharing one setup at a time
|
|
- Per-profile environment variable overrides
|
|
- gamescope Wayland compositor integration
|
|
- FPS cap through MangoHud
|
|
- Pre-launch hooks
|
|
- vkBasalt and Proton esync/fsync/large-address-aware controls
|
|
- Graphical notification self-test
|
|
- Shell completion generation
|
|
- `doctor`, `status`, and `dry-run` commands for troubleshooting
|
|
- explicit `run` mode for command-name collisions
|
|
- Clear help text with both plain-language explanations and technical details
|
|
|
|
## Install
|
|
|
|
Recommended low-maintenance install:
|
|
|
|
```bash
|
|
cargo install --path . --force
|
|
```
|
|
|
|
This installs the binary to `~/.cargo/bin/gamewrap`, which is already on `PATH` for most users who have Rust installed.
|
|
|
|
```bash
|
|
# After installing, ensure ~/.cargo/bin is on your PATH.
|
|
# Most Rust setups do this automatically. If gamewrap isn't found
|
|
# in Steam launch options, add to ~/.bash_profile or ~/.zprofile:
|
|
# export PATH="$HOME/.cargo/bin:$PATH"
|
|
```
|
|
|
|
After that, Steam launch options can stay simple:
|
|
|
|
```text
|
|
gamewrap %command%
|
|
```
|
|
|
|
User-local install:
|
|
|
|
```bash
|
|
cargo install --path .
|
|
```
|
|
|
|
That installs the binary to `~/.cargo/bin/gamewrap`.
|
|
If Steam cannot find commands from `~/.cargo/bin` in your desktop session, use the full path in Steam launch options:
|
|
|
|
```text
|
|
$HOME/.cargo/bin/gamewrap %command%
|
|
```
|
|
|
|
## Quick Start
|
|
|
|
1. Put this in Steam launch options:
|
|
|
|
```text
|
|
gamewrap %command%
|
|
```
|
|
|
|
If Steam cannot find `gamewrap` by name, use:
|
|
|
|
```text
|
|
$HOME/.cargo/bin/gamewrap %command%
|
|
```
|
|
|
|
2. Turn MangoHud on by default:
|
|
|
|
```bash
|
|
gamewrap config set mangohud on
|
|
```
|
|
|
|
3. Turn GameMode on by default:
|
|
|
|
```bash
|
|
gamewrap config set gamemode on
|
|
```
|
|
|
|
4. Check your setup before launching a real game:
|
|
|
|
```bash
|
|
gamewrap doctor
|
|
```
|
|
|
|
5. Launch a game explicitly from the terminal when needed:
|
|
|
|
```bash
|
|
gamewrap run /path/to/game/executable
|
|
```
|
|
|
|
Add `--` only when the command or its arguments would otherwise look like gamewrap options.
|
|
|
|
6. Inspect what `gamewrap` would do without actually launching:
|
|
|
|
```bash
|
|
gamewrap dry-run /path/to/game/executable
|
|
```
|
|
|
|
7. Bind a known game executable to a profile:
|
|
|
|
```bash
|
|
gamewrap profile create benchmark
|
|
gamewrap game bind "Game.exe" benchmark
|
|
```
|
|
|
|
8. Add game-specific overrides while keeping shared values global:
|
|
|
|
```bash
|
|
gamewrap config set mangohud on
|
|
gamewrap profile create benchmark
|
|
gamewrap profile set benchmark verbose on
|
|
```
|
|
|
|
9. Export your config for backup or sharing:
|
|
|
|
```bash
|
|
gamewrap config export shared
|
|
```
|
|
|
|
10. Export one profile for sharing:
|
|
|
|
```bash
|
|
gamewrap profile export benchmark benchmark
|
|
```
|
|
|
|
11. Import a shared profile:
|
|
|
|
```bash
|
|
gamewrap profile import benchmark
|
|
```
|
|
|
|
12. Install shell completions:
|
|
|
|
```bash
|
|
gamewrap completion install zsh
|
|
```
|
|
|
|
You can still print the raw script with `gamewrap completion zsh`, but `install` is the user-friendly path.
|
|
The installed completion script asks `gamewrap` for live data, so new profiles and observed games show up automatically without reinstalling.
|
|
|
|
If the real command you want to launch has the same name as a `gamewrap` subcommand, force launch mode with:
|
|
|
|
```bash
|
|
gamewrap run -- /path/to/game/executable
|
|
```
|
|
|
|
## Common Commands
|
|
|
|
```bash
|
|
gamewrap --help
|
|
gamewrap help settings
|
|
gamewrap help settings gamescope
|
|
gamewrap help settings mangohud
|
|
gamewrap help doctor
|
|
gamewrap game list
|
|
gamewrap game list "elden"
|
|
gamewrap game show "Game.exe"
|
|
gamewrap game forget "Game.exe"
|
|
gamewrap status
|
|
gamewrap doctor
|
|
gamewrap notify test
|
|
gamewrap doctor /path/to/game/executable
|
|
gamewrap run /path/to/game/executable
|
|
gamewrap dry-run /path/to/game/executable
|
|
gamewrap completion zsh
|
|
gamewrap completion install zsh
|
|
gamewrap completion path zsh
|
|
gamewrap config show
|
|
gamewrap config show --effective
|
|
gamewrap config edit
|
|
gamewrap config reset --all
|
|
gamewrap config migrate
|
|
gamewrap config export shared
|
|
gamewrap config import shared
|
|
gamewrap last
|
|
gamewrap profile list
|
|
gamewrap profile create benchmark
|
|
gamewrap profile show benchmark
|
|
gamewrap profile show benchmark --effective
|
|
gamewrap profile duplicate benchmark benchmark-copy
|
|
gamewrap profile export benchmark benchmark
|
|
gamewrap profile import benchmark
|
|
gamewrap profile migrate old-benchmark
|
|
gamewrap profile set benchmark mangohud on
|
|
gamewrap profile reset benchmark mangohud
|
|
gamewrap profile env set benchmark DXVK_ASYNC 1
|
|
gamewrap profile env list benchmark
|
|
gamewrap profile env unset benchmark DXVK_ASYNC
|
|
gamewrap game bind "eldenring.exe" benchmark
|
|
gamewrap game unbind "eldenring.exe"
|
|
gamewrap game rename "eldenring.exe" "Elden Ring"
|
|
gamewrap game note "eldenring.exe" needs game-libs gamemode
|
|
gamewrap game clear-note "eldenring.exe"
|
|
```
|
|
|
|
## Friendly Settings
|
|
|
|
- `mangohud`: turns MangoHud on or off
|
|
- `gamemode`: turns GameMode on or off
|
|
- `steam-host-libs`: prefers host libraries inside Steam runtime environments and sets `STEAM_RUNTIME_PREFER_HOST_LIBRARIES=1`
|
|
- `game-libs`: controls whether `gamewrap` injects auto-detected host library directories into `LD_LIBRARY_PATH`
|
|
- `verbose`: shows more detail in diagnostic commands
|
|
- `log-file`, `log-path`: append gamewrap launch decisions to the default state log or a custom path
|
|
- `gamescope`: wraps the game in the gamescope Wayland compositor
|
|
- `gamescope-width`, `gamescope-height`: set output resolution with a pixel count or `native`; unset uses gamescope's 1280x720 default
|
|
- `gamescope-mode`: selects `windowed`, `borderless`, or `fullscreen`
|
|
- `gamescope-fps`: passes the `-r` target refresh value when gamescope is on
|
|
- `fps-cap`: caps frame rate through MangoHud when `mangohud` is on, for example `gamewrap config set fps-cap 60`
|
|
- `mangohud-log`, `mangohud-log-path`: enable full-session MangoHud performance logging and optionally choose its output path
|
|
- `vkbasalt`: enables vkBasalt post-processing with `ENABLE_VKBASALT=1`
|
|
- `vkbasalt-log-level`: sets `VKBASALT_LOG_LEVEL` to `debug`, `info`, `warning`, `error`, or `none` when vkBasalt is on
|
|
- `esync`: forces Proton esync on or off with `PROTON_NO_ESYNC`; leave unset to use Steam/Proton defaults
|
|
- `fsync`: forces Proton fsync on or off with `PROTON_NO_FSYNC`; leave unset to use Steam/Proton defaults
|
|
- `large-address-aware` / `laa`: sets `PROTON_LARGE_ADDRESS_AWARE=1` for older 32-bit Proton games that need more than 2 GB of address space
|
|
- `pre-launch`: runs a shell command through `sh -c` immediately before the game launches
|
|
- `post-launch`: runs a shell command after the game exits; when set, gamewrap spawns the game and waits for it to finish before running this hook
|
|
- `env-vars`: per-profile environment overrides managed with `gamewrap profile env set/list/unset/clear`
|
|
|
|
**hook-errors** (`warn` | `fail`, default: `warn`)
|
|
|
|
Controls what happens when a pre-launch hook exits nonzero or cannot be executed.
|
|
- `warn` — a message is printed to stderr and the game launches anyway.
|
|
- `fail` — gamewrap aborts with an error and the game is not launched.
|
|
|
|
The post-launch hook always runs after the pre-launch hook succeeds, even if the game itself fails to start.
|
|
|
|
Example:
|
|
gamewrap config set hook-errors fail
|
|
|
|
## How It Works
|
|
|
|
When `gamewrap` launches a game, it applies global defaults, then any matching profile overrides, prepares the needed environment variables, and prefixes the game command with `gamescope`, `mangohud`, and/or `gamemoderun` when those features are enabled.
|
|
|
|
If something important is missing, `gamewrap` is designed to fail clearly instead of silently skipping the requested behavior. The `doctor` and `status` commands help you verify that before launching through Steam.
|
|
|
|
For terminal usage, `gamewrap` distinguishes between management commands and explicit launches:
|
|
- use commands like `gamewrap game list`, `gamewrap profile list`, or `gamewrap game bind ...` for management
|
|
- `gamewrap game list <text>` filters observed games by executable or path substring
|
|
- `gamewrap last` shows the most recently observed launch
|
|
- `gamewrap game rename <text> <name>` gives an observed game a friendlier display name
|
|
- `gamewrap game forget <text>` removes an observed game from local state
|
|
- `gamewrap config edit` opens the config file in `$VISUAL`, `$EDITOR`, or `nano`
|
|
- use `gamewrap config export` and `gamewrap config import ...` for full-config backup and sharing
|
|
- use `gamewrap profile export` and `gamewrap profile import ...` for sharing one profile
|
|
- use `gamewrap profile env set <profile> <KEY> <VALUE>` for per-profile environment overrides
|
|
- use `gamewrap notify test` to verify graphical failure notifications
|
|
- use `gamewrap run <command>` when you want to explicitly launch from the terminal
|
|
- use `gamewrap dry-run <command>` when you want to inspect the resolved launch without running it
|
|
- add `--` only when the command or its arguments would otherwise look like gamewrap options
|
|
|
|
## Shell Completion
|
|
|
|
Recommended:
|
|
|
|
```bash
|
|
gamewrap completion install zsh
|
|
```
|
|
|
|
Then open a new shell.
|
|
|
|
Other useful commands:
|
|
|
|
```bash
|
|
gamewrap completion zsh
|
|
gamewrap completion path zsh
|
|
```
|
|
|
|
The installed completion script is live rather than static. That means:
|
|
- new profiles appear in completion results automatically
|
|
- newly observed games appear automatically
|
|
- you generally only need to reinstall if your shell startup setup changes
|
|
|
|
## Sharing Files
|
|
|
|
Suggested file names:
|
|
|
|
```text
|
|
shared.gamewrap.toml
|
|
benchmark.gamewrap-profile.toml
|
|
```
|
|
|
|
You do not need to type the full extension yourself. These commands are equivalent:
|
|
|
|
```bash
|
|
gamewrap config export shared
|
|
gamewrap config import shared
|
|
gamewrap profile export benchmark benchmark
|
|
gamewrap profile import benchmark
|
|
```
|
|
|
|
`gamewrap` automatically adds `.gamewrap.toml` or `.gamewrap-profile.toml` when needed.
|
|
|
|
`gamewrap config export` writes the sparse global defaults and profile overrides exactly as configured.
|
|
|
|
`gamewrap profile export` writes only explicitly configured profile settings. Imported profiles use the receiving machine's global defaults for every unset value.
|
|
|
|
## Files
|
|
|
|
- Config: `~/.config/gamewrap/config.toml`
|
|
- State: `~/.local/state/gamewrap/state.toml`
|