Adaptive-trigger profiles for the OpenDS5 companion app.
This is the library the app fetches at runtime, and it is open to contributions. If you have tuned a trigger profile for a game you like, open a pull request — once it is merged, it shows up in everyone's in-app library browser. No app release is needed.
1. Export it from the app. Tune the profile in OpenDS5, then Trigger Profiles → Export. Export it rather than writing the JSON by hand: the app writes the exact shape the validator expects, and it fills in the trigger data for you.
2. Fork this repo and drop the file at profiles/library/<game-slug>.json. The name must be a
lowercase slug — cyberpunk-2077.json, nier-replicant.json. It is interpolated into the URL the
app fetches, so anything else is rejected.
3. Fill in meta:
{
"name": "Cyberpunk 2077",
"meta": {
"game": "Cyberpunk 2077",
"author": "your-github-handle",
"description": "Weapon-aware resistance: heavy pull on power weapons, light click on tech."
},
"triggers": { "...": "exported by the app" }
}game— the game's official name, spelled the way its store page spells it (e.g.Ghost of Tsushima Director's Cut, apostrophe and all). This is the heading shown on the library card, and the app uses it to connect profiles, native flags, and the user's own game entries. Matching ignores case, punctuation, and spacing (DIRECTORS CUTstill findsDirector's Cut) — but the exact string is what users see, so use the canonical spelling. Editions count as different games: aDirector's Cutprofile does not attach to the base game.author— how you want to be credited.description— one sentence on what the triggers feel like in game. Write what a player would want to know, not what the JSON contains.- Leave
tierout. See Tiers.
4. Open a pull request. CI validates your profile using the same validator the app runs at install time, so if it passes here it will load in the app. If it fails, the error message names the exact field.
5. A maintainer reviews and merges it. They hardware-test it on a DualSense. If it passes, they
mark it verified and merge; otherwise it still merges, as community.
profiles/library/index.json is generated on merge. Contributors never touch it — a hand-edited
index would conflict on every concurrent pull request, and it could claim capabilities a profile
does not actually have. CI rebuilds it from the profiles themselves, and a PR that modifies it
fails.
npm install
npm run validateThis runs every profile through the validator and prints the derived capability line for each one. It is exactly what CI runs on your pull request.
Profiles can carry states — named per-weapon/per-vehicle trigger feels — plus the switching
block that tracks them: button rules, a menu guard, and the analog wheel (stickWheel) that
mirrors stick-driven weapon wheels, including per-slot widths for games with unequal slices. Export
from the app as usual; the whole block travels with the profile and the library card describes it
(12 states · analog wheel · 4 switch rules).
Two things to know when contributing one:
- Model every slot the game's wheel draws (melee, throwables, locked slots) — a missing slot shifts every pick past it and reviewers will bounce it back.
- Multi-state profiles need an app version with states support (post-v1.8.0); older apps reject them at import with an error naming the field. That is expected, not a bug in your profile.
Every profile in the catalog carries a tier:
| Tier | Meaning |
|---|---|
verified |
Hardware-tested by a maintainer. |
community |
Submitted and valid, not yet hardware-tested. |
A profile with no tier is treated as community, so an unlabelled profile never presents itself as
verified. Only a maintainer sets verified, at merge time — leave the field out of your PR.
Profiles ported from an existing game mod also carry an origin
({ "kind": "port", "from": "<mod name>" }). That is independent of tier: a port can be verified or
community.
profiles/library/native.json lists games with native adaptive-trigger support, sourced from
PCGamingWiki. These need
no profile — OpenDS5 passes the game's own trigger effects through, and the app shows them as
Native with nothing to install.
The list covers games the wiki marks as native or limited-native. Games that only work with a manual fix are not included. It is maintainer-curated; if a game is missing, open an issue rather than a pull request.
Your description is your own sentence. The capabilities line the app shows next to it
(L2 multi-zone · R2 slope · 2 modifiers) is derived from the profile itself by CI, using the
same code the app runs — so it can never claim an effect the profile does not have. You do not
write it, and you cannot override it.
profiles/library/<game>.json profiles — you add these
profiles/library/index.json the catalog the app reads — generated by CI
profiles/library/native.json games with native trigger support — maintainer-curated
validator/ the app's validator, vendored verbatim
scripts/build-index.mjs validates profiles; regenerates index.json
scripts/validate-profile.mts the validation harness build-index.mjs calls
Profiles are contributed under AGPL-3.0-or-later, matching OpenDS5.