https://patch.gg/schemas/recipe/v1.json.
Fields
Every field is optional; what you leave out takes the default shown.Games
An
installed or workshop release has exactly one host game. A browser game has none.
A mod reads a companion game’s files from the player’s own copy, never from the release. While it runs, Patch Desktop puts patch-games.json in the host game’s folder (a standalone program’s working folder) and removes it afterwards. It gives each listed game’s folder by its slug:
Loaders
Aloader requirement installs that loader with your release and removes it with it. It targets the host game; to install it for a companion game instead, add that game’s slug as game, such as { "kind": "loader", "loader": "fabric", "game": "minecraft-java" }. That game must be listed as a host or companion, never related.
Patch Desktop fetches each loader from its publisher at a version Patch pins and checks it before installing. A loader added recently needs an up-to-date Patch Desktop. That a loader installs doesn’t mean a mod works with every build of its game: use
builds for that.
Components
A component names part of your files: one file, a folder ending in/, or "" for every file. Every file you upload belongs to at least one component.
A browser game’s files are uploaded as they are, never as a zip, and
launch.entry is a path inside its component.
Paths
Paths on the player’s PC start with one of these folders:
No path can use
... Prefer {profile} wherever the game and its mod loader allow it: the game’s own folder stays untouched, and uninstalling just removes the profile.
Where things go:
- Code (programs, DLLs, scripts, shortcuts) goes in
{game},{game:slug}or{profile}. The player’s own folders are for data, such as settings and saves. - In the player’s own folders, use a folder of the release’s own, such as
{localappdata}/Lantern, never the folder itself. - A release can’t write to Patch’s own folders, programs’ settings (the dot folders in
{userprofile}), the Start menu, PowerShell’s folders, or a short folder name likePROGRA~1. Use{appdata},{documents}and the other folders, not their paths through{userprofile}. - An
exelaunch starts a program in a game’s folder, or one the release places through its mappings. - File and folder names are ones Windows keeps as written: none of
< > : " | ? *, no name ending in a dot or space, and no device names likeCONorNUL.
Between plays
Patch Desktop installs a release once and keeps it installed. Each Play puts back only the files that are missing or changed, and keeps a config file the mod or the player changed since. Between plays it switches the mod off, so the game started outside Patch is the plain game: your code (.dll, .asi, .lua, .pak, .upk and the like) and your loader’s hook file (such as winhttp.dll) get .patch-off added to their names, and any file they replaced is back in its place. Play switches on only the mod being played, so two mods for one game don’t run together. Removing it from Library takes its files out and puts back what they replaced.
A test leaves nothing of a release that wasn’t installed before it: what the test installed comes out when its run ends, however it ends, and so does a loader only it needs. A release that was installed before stays installed, switched off, at the version tested.
Settings
Each entry insettings sets values in one config file before the game starts. Patch Desktop reads the file as it is (the game’s own, or one your release just placed; a file that isn’t there starts empty), sets the values and writes it, and puts it back as it was when the game stops. Keys by format:
iniandcfg:Section.KeysetsKey = valueunder[Section], the section being everything before the last dot. A key without a dot goes above the first section. Missing keys and sections are added.json:a.b.csets that member, making the objects on the way.xml:Root.Audio.Volumesets that element’s text, each step being the first child of that name, andRoot.Audio.@volumesets an attribute. A missing last element is added to its parent; a missing parent is an error.
set always contains literal values, including any braces in a string. For a value that must name a folder on the player’s PC, use the separate paths map and a supported install path. A key may occur in either map, never both. For example, "set": { "INSTALL.Logging": 0 }, "paths": { "INSTALL.BasePath": "{game:minecraft-java}/gta-legacy/reshade" } writes the resolved companion profile path, provided Minecraft Java is a listed required game. This needs Desktop support for resolving setting paths. The write uses the same restore-on-exit behavior as other settings; it does not create or delete the folder named by the value.
Tests
Patch Desktop tests a browser game or a mod it installs on its creator’s PC before it goes live: it runs it as players get it and records it. If the recipe liststest.checks, it reports each one while it’s tested. Patch opens a browser game with ?patch-test=1, and the game logs one console line per check, pass level-loads or fail level-loads: the map didn't load. A mod appends the same lines to patch-test.txt, which is there only while it’s tested, in the game’s folder. A run counts only when every check passed. Review has what else a test checks.
Blocks
A block is a repo that isn’t a game, and its README’s front matter says what it is:kind: effect, for example. Opening the repo is what puts a block of kind effect, system or tool on its shelf in the toolbox, within about 5 minutes. Kinds character and asset get a page and search, but no shelf.
A demo is optional. To add one, publish a release with a block section once the repo is open: a private repo’s public release is refused. A block with nothing to demo, such as a tool, needs no release.
The full steps are in the guide tool on Patch’s MCP server.
Validation
Patch checks the recipe and the file list when you create a release. Each problem comes back as an error code with the details:
A recipe has at most 16 games, 64 components, 64 mappings, 32 requirements and 500 credits, and a path in it at most 512 characters.
POST /recipes/validate takes a body of up to 4 MB.
Versions of the format
This is version 1 of the recipe (schema_version: 1). New optional fields can be added to it; anything that would break an existing recipe becomes version 2.