A Playnite extension that runs SISR
(Steam Input System Redirector) only for games with the Enable SISR feature, and only
while that game is running. By default it just applies your global SISR profile; a per-game config
and per-game Steam Input layout are opt-in.
Every line of this repository was written by an AI (Claude Opus 4.8, via Claude Code): the C#, the Steam VDF parser, this README, the commit messages, and AGENTS.md. A human set the goal and made the design calls; a human did not hand-write or line-by-line audit the code.
What that means for you:
- It genuinely works. It was tested end-to-end on a real install, in both modes: a game with the
feature starts SISR, closing the game stops it, and a game without the feature triggers nothing.
The Steam VDF writer was verified to round-trip a real
shortcuts.vdfbyte-for-byte. - It has had exactly one user and one machine's worth of testing. Edge cases involving other Steam setups, multiple Steam accounts, or unusual SISR versions are unexplored.
- It writes to
shortcuts.vdf, the file holding all your non-Steam shortcuts. The code backs it up (shortcuts.vdf.sisrhelper.bak), writes via a temp file, and re-parses the bytes before committing them — but back it up yourself if you care about it. - No warranty. Read the MIT license. If that trade-off isn't for you, that's a completely fair call.
Bug reports are welcome, and will most likely be fixed by an AI too.
| Event | Behaviour |
|---|---|
| A game with the feature starts | Starts SISR (default: your global profile; opt-in: that game's own config + Steam shortcut), waits for its emulated controllers, then lets the game launch |
| Game exits | Stops the SISR instance started for that game — and only that one |
| Startup cancelled | Same cleanup, so a cancelled launch leaves nothing behind |
| Playnite exits | Ends any still-tracked session |
| Game without the feature | Nothing happens at all |
Default — global profile. SISR launches with your own global profile (no --config, no Steam
shortcut, nothing written to Steam). The extension only ties SISR's lifetime to the game: it starts
when the game starts and stops when it exits. This is all most people want.
Opt-in — per-game config. Turn on Use a per-game config in settings and each game gets its own SISR config file. Turn on Create a Steam shortcut per game as well and each game also gets its own Steam Input layout via a per-game non-Steam shortcut. See the section below for the one caveat.
- Grab the
.pextfrom Releases and open it with Playnite (or drag it onto the window). - Restart Playnite.
- Check the SISR.exe path in the extension's settings (it auto-detects
%LOCALAPPDATA%\SISR\SISR.exe). - Right-click a game → SISR Helper → Add the "Enable SISR" feature.
(Features are a Playnite metadata field, shown next to Tags in a game's edit window. Using a feature rather than a tag keeps SISR out of your tag list.)
Right-click a game → SISR Helper:
- Add / Remove the "Enable SISR" feature — works on a multi-selection. (Always available.)
- Edit SISR config for this game — per-game mode only; creates the config if needed, opens it.
- Open SISR interface with this game's config — per-game mode only; SISR's own UI for that config.
- Remove SISR config and Steam shortcut — per-game mode only; deletes both, after confirming.
Main menu → SISR Helper:
- Edit global SISR config — opens SISR's global profile (
%APPDATA%\SISR\config\SISR.toml), the one used in the default mode. Writes an all-commented starter file if none exists yet. - Open the per-game config folder.
This applies only when Create a Steam shortcut per game is on. The extension writes a SISR - <Game>
entry into Steam's shortcuts.vdf and launches it via steam://rungameid/.
Steam only reads shortcuts.vdf at startup. So the first time you launch a game after its shortcut
is created, you get a notification and SISR is started directly for that one session — restart Steam
once and that game's own layout applies from then on. If Steam isn't running, it falls back to a direct
launch and tells you the per-game layout won't apply. This constraint is inherent to the approach
(GlosSI Integration has the same one), not a bug.
In per-game mode each game gets GameConfigs/<playnite-game-id>.toml in the extension's data
directory. That path is unique per game and stable across renames, and it's what identifies both the
SISR process (matched via its command line) and the Steam shortcut (matched via its launch options).
In the default (global) mode there is no config path, so the instance is tracked by process id,
guarded against pid recycling with the process name and start time. Either way the extension only
ever acts on the instance it started — one you started yourself is never killed.
Per-game configs live in the extension's own directory rather than %APPDATA%\SISR\config on purpose:
SISR auto-discovers configs in its own directory, and a stray one there would apply to every game.
1. Nested TOML tables don't work. SISR flattens [window] show = true to window-show and
refuses to start with unknown configuration keys. Nested keys must be quoted dotted keys:
"window.show" = true # correct
"log.level" = "info" # correct
[window] # WRONG — SISR will not start
show = trueUse TOML literal strings for Windows paths ('C:\path\file.log'). Nested JSON works; nested YAML is
accepted and then silently ignored, so avoid it.
2. Steam shortcut appids are random, not CRC32. The widely repeated
crc32(exe + appname) | 0x80000000 formula does not match what current Steam clients write — none
of the real entries checked matched it. This extension mints a random id with the high bit set (as
Steam does) and persists it.
Requires the .NET SDK (Visual Studio's C++-only workload can't compile C#):
dotnet build -c Releasenet462 is targeted via the Microsoft.NETFramework.ReferenceAssemblies package, so no Visual
Studio targeting pack is needed. To deploy manually, copy bin/Release/* into:
%APPDATA%\Playnite\Extensions\SisrHelper_8f3a1c62-4d77-4a19-9b2e-1c7b5d0e6a34\
Extensions load at startup only — restart Playnite afterwards.
See AGENTS.md for the full technical context, including the constraints that aren't obvious from the code.
- SISR by Peter Repukat (Alia5) — the tool this drives.
- Special K Helper by darklinkpower — the plugin pattern this is modelled on (no code copied).
- Playnite by Josef Nemec.
0 comments
log in to comment.