Files
steam_linux_launch_args/AGENTS.md
T
2026-08-05 20:27:01 +01:00

181 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AGENTS.md
## What this is
SvelteKit 5 (runes mode) static site that assembles Steam launch commands from
composable "program classes" (gamescope, MangoHud, Proton, obs-gamecapture,
gamemode). User flips toggles in a tabbed UI; the app renders one flat launch
command string like:
```
gamescope -f -- %command% mangohud waitforexecandrun %command%
```
Rendered by adapter-static (`prerender = true` in `src/routes/+page.ts`).
## Core model (`src/lib/`)
- `meow.ts` — the engine. `ArgEvaluatable` interface (`enabled()`, `envs()`,
`binary()`, `prefix()`, `suffix()`, `priority()`, `arguments()`); `ArgEval`
evaluates components: filter `enabled()`, sort by `priority()` (lowest =
outermost wrapper), envs as `VAR=VAL` space-joined, each program rendered
`prefix binary args suffix` (empty parts dropped), args sorted by `prio` and
rendered `arg val` (bare `arg` when val empty), then `%command%` appended.
- `programs.ts` — data types + `Program` class implementing `ArgEvaluatable`
from a `ProgramConfig`. Key fields: `enabled`, `name`, `binary`, `prefix`,
`suffix`, `priority`, `envs`, `args`, `options` (toggleable sub-flags),
`envSeparators` (per-var merge separators), option `conflicts` (see below).
- `presets.ts` — re-export index only; real factories live per-program in
`src/lib/preset/` (see file map).
- `preset/helpers.ts` — builders shared by presets: `envToggle(label, env,
val, category?)`, `group(program, labels)` (pairwise conflict keys).
(Mutually-exclusive flag choices like `-F` filter use ONE option with an
`args[].values` dropdown — do NOT reintroduce one-option-per-value.)
### Semantics to keep in mind
- Env vars with the same name merge into ONE var: values dedupe, joined by the
var's separator from `envSeparators` (default `,`).
- `conflicts` keys are `'programname'` (program-level) or
`'program:Option label'` (option-level). Only enabled vs enabled conflict;
conflicts are displayed as a non-blocking warning banner.
- Env merge destructuring: `var` is a reserved word in TS — use
`[varName, vals]` in destructures.
- Args are space-separated (`-W 1920`), never `arg=val`.
## File map
| file | role |
| ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `src/lib/meow.ts` | evaluation engine (see above) |
| `src/lib/programs.ts` | types + `Program` adapter + `findConflicts()` |
| `src/lib/presets.ts` | re-exports the eight preset factories |
| `src/lib/preset/helpers.ts` | shared option builders |
| `src/lib/preset/gamescope.ts` | gamescope args (fullscreen, filter/scale dropdowns, HDR, VR, …) |
| `src/lib/preset/proton-ge.ts` | GloriousEggroll Proton env toggles |
| `src/lib/preset/proton-cachyos.ts` | CachyOS Proton env toggles (largest set) |
| `src/lib/preset/obs.ts` | obs-gamecapture CLI |
| `src/lib/preset/gamemode.ts` | `gamemoderun` wrapper (priority 5 = outermost) |
| `src/lib/preset/mangohud.ts` | MANGOHUD env options + `MANGOHUD_CONFIG` separator merge |
| `src/lib/preset/mesa.ts` | Mesa Vulkan layers env toggles (anti-lag, overlay layer, fps-monitor) |
| `src/lib/preset/prime.ts` | `prime-run` wrapper for NVIDIA PRIME offload |
| `src/lib/ProgramForm.svelte` | per-program editor: enabled checkbox, options list, Advanced `<details>` (name/binary/prefix/suffix/priority, env vars, args, env separators) |
| `src/lib/decode.ts` | `applyCommand(cmd, programs)` — enable options/programs a pasted command references (only ever enables, never disables) |
| `src/routes/+page.svelte` | tabs + `pre.result` command preview + conflict banner; localStorage persistence; decode textarea |
| `launch_args_env_vars.md` | reference: gamescope args, Proton env-var tables, OBS, gamemode |
| `steam-tinker-launcher.md` | reference: STL v14 docs (gamescope CLI catalog §3.13.6, mangohud, proton, dxvk, wine) |
## Conventions
- New programs are preset factory functions in `src/lib/preset/<name>.ts`
returning a `ProgramConfig`, re-exported from `presets.ts`, imported into
`+page.svelte`'s `programs` array.
- Every option carries a `category: string`; ProgramForm groups options under
category headings (keep categories consistent within a preset).
- Every option should also carry a `desc: string`; it appears as a hover
tooltip (1 s delay, CSS-only) next to the option row.
- Default new presets to `enabled: false` so the default output stays stable.
- Preset files ≤ ~140 lines; split if they grow (that's why the directory
exists). Shared builders go in `helpers.ts`.
- `+page.svelte` uses PURE TAB indentation — never build edit oldText with
spaces.
- Mutual exclusivity is expressed via `conflicts` (options) or `group()`
(helpers), never via extra app state.
- `user-select: none` on tabs/labels to stop double-click selection; inputs and
`pre.result` stay selectable.
## Adding options & programs (agent playbook)
Every task in this repo ends with the verification loop below; a change is not
done until all three pass.
### Add an option to an existing program
1. Edit `src/lib/preset/<name>.ts` — the program's factory, inside
`options: [...]`. Mine the flag/env catalogs from `launch_args_env_vars.md`
and `steam-tinker-launcher.md`.
2. Pick the builder (from `./helpers`):
- Env toggle (checkbox sets `VAR=1`):
`envToggle('Label', 'ENV_VAR', '1', 'Category')` — pass a custom value as
the 3rd arg for non-`1` values.
- Flag with a value (gets an editable input in the UI while enabled):
```ts
{ label: 'Mouse sensitivity', enabled: false, args: [{ arg: '-s', val: '1.0', prio: 0 }], category: 'Window' }
```
- Flag with a fixed value set (gets a `<select>` dropdown instead of a
text input): add `values: ['auto', 'drm', 'wayland']` to the arg.
- Flag whose value must match a regex (input turns red + banner error
while invalid): add `pattern: NUM` or `pattern: NUM_DEC` (exported from
`./helpers`) or a custom regex source string.
- Bare flag: same shape with `val: ''` (checkbox only, no input).
- Mutually exclusive flag with a fixed value set (e.g. `-F fsr` vs
`-F nis`): ONE option with `values` on the arg:
`{ label: 'Filter', enabled: false, args: [{ arg: '-F', val: 'fsr', prio: 0, values: ['none', 'linear', 'fsr', 'nis'] }], category: 'Filter' }`.
Do NOT create one option per value.
3. `category` is required — reuse an existing one from that preset or add a new
one (it becomes a tab). Keep categories consistent within a preset.
4. Mutual exclusivity: `conflicts: ['other-program']` or
`conflicts: ['same-program:Other option label']`; `group()` generates
these automatically.
5. Presets only supply defaults — the form binds arg `val` to an input while
the option is enabled, so users can override values.
### Add a new program
1. Create `src/lib/preset/<name>.ts` exporting
`export function <name>(): ProgramConfig` (model on
`src/lib/preset/obs.ts` — the smallest real example).
2. Required config: `name`, `enabled` (default `false` so output stays stable),
`binary`, `prefix` (wrapper like `'gamemoderun'`), `suffix`
(`'waitforexecandrun'` for proton, `'--'` for gamescope-style), `priority`,
`envs: []`, `args: []`, `options: [...]`.
3. Re-export: add `export { <name> } from './preset/<name>';` to
`src/lib/presets.ts`.
4. Import it in `src/routes/+page.svelte` and append to the
`programs = $state([...])` array.
5. Keep the file ≤ ~140 lines; use `envToggle()`/`group()` for builders and
repetitive options.
Priority semantics: components sort ascending by `priority()` — the outermost
wrapper has the LOWEST number (gamemoderun=5, gamescope=10, proton=20,
mangohud=30).
## Verification (mandatory before yielding)
```bash
pnpm exec prettier --write <edited files> # lint runs prettier --check
pnpm check # svelte-check — authoritative type check
pnpm lint # prettier --check + eslint
pnpm build # adapter-static build
```
All four must pass. `pnpm check` is the authority — see the known quirk below.
Known traps for agents:
- **pi-lens/LSP diagnostics on `.svelte` files are stale all session** — they
falsely report `enabled` / `category` / `envSeparators` as missing from
`ProgramConfig` on every edit. They are noise: the fields verifiably exist in
`programs.ts`. Do NOT chase them; rely on `pnpm check` (returns 0 errors
every time). The `.ts` files' diagnostics are accurate.
- `+page.svelte` uses pure tabs — edit `oldText` must use tabs, not spaces. If
the edit tool reports content-drift, re-read the file verbatim before
retrying.
- This file (AGENTS.md) is auto-reformatted by prettier/markdownlint after
edits — always re-read it before further edits; it also uses real em-dashes
(``).
- `var` is a reserved word in TS destructuring — use `[varName, vals]`.
- A stale `vite dev` server can serve corrupted modules (missing exports).
Fix: kill all `vite` processes and restart — never `pkill -f` with a pattern
that also appears in your own command line (it kills your shell).
- Do not add options the docs mark as per-user paths or STL-internal settings
(Vortex/MO2/winetricks/Conty…); README.md is sv boilerplate, ignore it.
Reference docs to mine for new options: `launch_args_env_vars.md` and
`steam-tinker-launcher.md` (README.md is sv boilerplate, ignore it).