# DeckyVault Decky Loader Plugin — Design Spec ## Overview A Decky Loader plugin that records Steam Deck (and other Linux handheld) performance metrics during gameplay, then exports or uploads them to DeckyVault as benchmark entries. The plugin uses **MangoHud** for FPS/power logging, reads **system files** for hardware/OS/Proton detection, and lets the user fill in the few fields that can't be auto-detected (upscaler, frame gen, in-game settings, load times). ## Architecture ``` plugins/decky-vault/src/ ├── index.tsx # Entry point — registers plugin with Decky Loader ├── components/ │ ├── main-panel.tsx # Record/Stop button, session status, recent recordings │ ├── session-form.tsx # Post-session summary with manual inputs + export/upload │ └── settings-panel.tsx # API key, export path, hardware, MangoHud setup ├── lib/ │ ├── mangohud.ts # Start/stop MangoHud logging, parse log for FPS stats │ ├── system-info.ts # Read hardware model, OS version, Proton version, TDP │ ├── api-client.ts # Upload to DeckyVault via API key │ ├── exporter.ts # Save .deckyvault.json to disk │ └── store.ts # Plugin state (settings, current session, recent sessions) └── types.d.ts # Decky Loader API declarations (exists) ``` Each module has one clear purpose: - **`mangohud.ts`** — writes MangoHud logging config, reads/parses the log file after a session. Computes FPS avg/min/max/1% low and average TDP. - **`system-info.ts`** — reads `/sys/class/dmi/id/product_name` for hardware detection, `SteamClient.System.GetOSVersion()` for OS, Steam app info for Proton version. - **`api-client.ts`** — wraps `fetch` calls to DeckyVault's `/api/performance/import` with `x-api-key` header. Also calls `/api/games/lookup` to verify the API key. - **`exporter.ts`** — builds a `DeckyVaultImportV1` object and writes it as JSON to the configured export path. - **`store.ts`** — holds plugin settings (API key, export path, hardware override) and session state (recording status, current app ID, start time, parsed results). Also persists the last 5 recent sessions to Decky Loader's plugin storage so they survive plugin reloads. The single source of truth that components read from. ## Recording Flow ### Start Recording 1. User presses "Start Recording" in the plugin panel. 2. Plugin writes a MangoHud config that enables logging. The config sets `output_folder=/tmp`, `output_file=deckyvault-mangohud.log`, and enables: `fps`, `frame_timing`, `cpu_power`, `gpu_power`, `cpu_temp`, `gpu_temp`. MangoHud's log includes a summary section with benchmark percentiles (configurable via `benchmark_percentiles`, default `97,AVG,1,0.1`). The plugin can parse either the raw frame data or the summary section for FPS stats. 3. Plugin records the current timestamp and (if a game is running) the active app ID via `SteamClient.Apps`. 4. Plugin checks if MangoHud is running. If not, shows a warning guiding the user to enable MangoHud for their game (via Steam launch options `mangohud %command%` or the Decky MangoHud toggle). Recording continues regardless — the log file will be populated once MangoHud is active. ### During Recording - The main panel shows a live status: "Recording — [game name]" with an elapsed timer. - The MangoHud log file accumulates FPS and power samples in the background. - User plays their game normally. ### Stop Recording 1. User presses "Stop Recording". 2. Plugin reads the MangoHud log file at `/tmp/deckyvault-mangohud.log` and computes: - `fpsAvg` — mean of all FPS samples - `fpsLow` — minimum FPS - `fpsHigh` — maximum FPS - `fpsOnePercentLow` — 1st percentile of frame times, converted to FPS - `tdpWatts` — average power draw across samples (if logged) 3. Plugin reads system info: - `hardwareSlug` — from `/sys/class/dmi/id/product_name` ("Jupiter" → `steamdeck-lcd`, "Galileo" → `steamdeck-oled`; falls back to user-configured default) - `osVersion` — `SteamClient.System.GetOSVersion()` - `protonVersion` — from the Steam app info or process environment 4. Plugin transitions to the session summary form. ### Edge Cases - **No MangoHud log found** → error: "MangoHud logging not detected. Make sure MangoHud is enabled for this game." with a link to the Settings → MangoHud Setup section. - **Log file is empty** → error: "Recording was too short or MangoHud didn't capture data. Try again." - **No game running when Record pressed** → allowed, but shows a warning that game info won't be auto-filled. User can still manually enter the Steam App ID in the form. - **MangoHud log parsing fails** (corrupt/unexpected format) → error with raw log preview, fall back to manual FPS entry in the form. ## Session Summary Form After stopping, the plugin shows a form with two sections: ### Auto-Captured (read-only summary card) - Game name + Steam App ID - FPS: avg / min / 1% low / max - TDP (watts, average) - Hardware (e.g. "Steam Deck OLED") - OS version - Proton version ### Manual Inputs (user fills in) | Field | Type | Required | Notes | |---|---|---|---| | Upscaler type | dropdown | yes (default: None) | None / FSR / DLSS / XeSS / LSFG / Other | | Upscaler version | text | no | e.g. "2.4" | | Frame gen method | dropdown | yes (default: None) | None / FSR FG / DLSS FG / LSFG / Other | | In-game settings | free text (stored as JSON array) | no | preset, graphics quality, resolution, etc. Maps to `settingsJson` in the import format. | | Load time (SSD) | number (seconds) | no | | | Load time (SD card) | number (seconds) | no | | | Launch options | text | no | auto-filled from Steam if available | | User notes | textarea | no | max 5000 chars | ### Export / Upload Actions Two buttons at the bottom of the form: - **Export to File** — builds a `DeckyVaultImportV1` payload and saves it as `[game-name]-[date].deckyvault.json` to the configured export path. - **Upload to DeckyVault** — builds the same payload and POSTs to `/api/performance/import` with the `x-api-key` header. Shows success or error response. Both build the identical `DeckyVaultImportV1` payload. If upload fails (invalid API key, game not in DeckyVault DB, network error), the error message is shown inline and the user can retry or fall back to file export. ## Plugin UI Layout Two tabs in the Decky Loader Quick Access panel: ### Tab 1: DeckyVault (Main) **Idle state:** - Big "Start Recording" button - Brief instructions: "Enable MangoHud for your game, then press Record before launching." **Recording state:** - "Stop Recording" button - Live elapsed timer - Current game name (or "No game detected" if none running) **Stopped state:** - The session summary form (above) replaces the button area. **Below (always visible):** - "Recent recordings" list — last 5 sessions showing game name, FPS avg, date. Clickable to re-view the form and re-export/re-upload. ### Tab 2: Settings - **API Key** — text input (prefixed `dv_`), with a "Test Key" button that calls `GET /api/games/lookup?steamAppId=0` to verify the key works. Shows ✓ valid or ✗ invalid. - **Export Path** — text input, defaults to `/home/deck/Downloads`. Where `.deckyvault.json` files are saved. - **Default Hardware** — auto-detected but overrideable dropdown. Options from `KNOWN_HARDWARE_SLUGS`. Useful for non-standard setups. - **MangoHud Setup** — see below. ### MangoHud Setup Section - **"Check MangoHud status" button** — runs `which mangohud` and reports: installed/not installed + version if available. - **Installation guide** (collapsible): - **Steam Deck (SteamOS)**: MangoHud is pre-installed. Enable per-game via Steam launch options (`mangohud %command%`) or the Decky MangoHud toggle plugin. - **Other Linux handhelds** (ROG Ally, Legion Go, etc.): install via Flatpak (`flatpak install flathub org.freedesktop.Platform.VulkanLayer.MangoHud`) or system package manager. - Link to MangoHud GitHub (`https://github.com/flightlessmango/MangoHud`) for manual builds. - **Configuration guide** — shows the exact MangoHud config the plugin writes (so users can verify). Includes a "Write config now" button that writes the logging config to `~/.config/MangoHud/MangoHud.conf`. - **Troubleshooting** (collapsible): - Log file empty → check MangoHud is enabled for the game, check the log path. - Wrong path → ensure the plugin has write access to `/tmp/`. - MangoHud not attaching → try adding `mangohud %command%` to the game's Steam launch options explicitly. ## Data Flow ``` [Start Recording] │ ▼ [MangoHud logs to /tmp/deckyvault-mangohud.log] │ ▼ (user plays game) [Stop Recording] │ ├──► mangohud.ts parses log → FPS stats, TDP ├──► system-info.ts reads → hardware, OS, Proton │ ▼ [Session Summary Form] │ (user fills manual fields) ├──► exporter.ts → .deckyvault.json on disk └──► api-client.ts → POST /api/performance/import │ ▼ [DeckyVault database] ``` ## Error Handling - **MangoHud not installed** → Settings tab shows installation guide. Main tab warns when Record is pressed. - **MangoHud not enabled for game** → post-session error with link to Settings → MangoHud Setup. - **Invalid API key** → upload fails with 401, message shown in form. User directed to Settings to re-enter key. - **Game not in DeckyVault DB** → upload returns 404, message: "This game isn't in DeckyVault yet. Submit it on the website first, or export to file for now." - **Network error during upload** → message shown, user can retry or export to file. - **Filesystem write error (export)** → message: "Couldn't write to [path]. Check the path in Settings." ## Testing Since the plugin runs on Steam Deck hardware in the Decky Loader environment, testing is primarily manual: 1. **MangoHud log parsing** — unit-testable with sample log files. Create test fixtures of MangoHud CSV output and verify FPS computation. 2. **System info reading** — testable on any Linux machine with mock `/sys` files. 3. **API client** — testable with mock fetch responses (success, 401, 404, network error). 4. **Exporter** — testable by writing to a temp directory and verifying JSON structure matches `DeckyVaultImportV1`. 5. **End-to-end** — manual testing on a Steam Deck with MangoHud enabled, recording a game session and verifying upload/export. ## Dependencies - `@deckyvault/shared` — workspace package (types: `DeckyVaultImportV1`, `KNOWN_HARDWARE_SLUGS`) - React — provided by Decky Loader runtime - MangoHud — external dependency, must be installed by the user (pre-installed on Steam Deck) ## Out of Scope (for this phase) - Auto-detection of upscaler / frame gen / in-game settings (manual input only) - Automatic recording on game start (manual start/stop only) - Real-time performance overlay in the plugin (MangoHud already provides this) - Multi-session batch upload (one session at a time) - Support for non-Steam games (requires manual Steam App ID entry, which is handled in the form)