> ## Documentation Index
> Fetch the complete documentation index at: https://docs.patch.gg/llms.txt
> Use this file to discover all available pages before exploring further.

# Recipe reference

> Every field of a release recipe: games, loaders, components, paths, settings, tests and validation errors.

Every field of the [release recipe](https://docs.patch.gg/recipe.md), for agents and for mods that need more than a game and a folder. It's plain JSON in snake\_case; the JSON Schema is at `https://patch.gg/schemas/recipe/v1.json`.

## Fields

Every field is optional; what you leave out takes the default shown.

| Field | Default | Meaning |
| - | - | - |
| `mode` | `browser`, or `installed` with a `host` game | `browser`: plays in Patch's game window. `installed`: into a game on the player's PC. `standalone`: a program of its own. `workshop`: a Steam Workshop item. `manual`: players install it by hand. |
| `games` | none | The games it names (below) |
| `components` | one `main` component holding every file | The parts of your files (below) |
| `mappings` | none | Where each component goes on the player's PC: `component`, `from` (`""` for all of it, `"folder/"` or one file) and `to`, a folder unless `from` names one file: then `to` can end in the name it should have. Needed for `installed` and `standalone`. |
| `requirements` | none | What else it needs: `{ "kind": "loader", "loader": "bepinex-5" }` for a mod loader Patch installs and removes with your release ([Loaders](#loaders)), or `{ "kind": "external", "label": "…", "url": "https://…" }` for something players get themselves. A release can't require another project on Patch: put a mod it needs inside it, with credit to its author |
| `launch` | `browser` at `index.html`, or the game itself | `{ "kind": "browser", "component", "entry", "aspect_ratio" }`, `{ "kind": "game", "args" }`, `{ "kind": "exe", "path", "cwd", "args", "env" }` (up to 8 variables), `{ "kind": "uri", "uri" }` or `{ "kind": "none" }` |
| `settings` | none | Up to 4 config files: `file`, `format` (`ini`, `json`, `xml` or `cfg`), literal values in `set`, and optional install-path values in `paths` |
| `test` | none | How Patch tests it: `checks`, up to 12 specific things it reports itself, which a run plays until they all pass; `move_keys`, up to 4 keys that move a browser game or block forward (`KeyW`), which the test holds and expects to move the picture ([Review](https://docs.patch.gg/review.md#the-test)); and `args` for test runs. `minutes` is accepted and ignored |
| `notes` | none | `before_install` and `first_launch`: short notes players see |
| `runtime_data` | none | Folders of its own data on the player's PC, such as `{localappdata}/Lantern`, never the game's |
| `players` | none | `{ "min": 1, "max": 4 }` |
| `workshop` | none | `steam_app_id` and `file_id`, for `workshop` |
| `credits` | none | Licences of bundled work by others: `files` (a glob), `license` (an SPDX id such as `CC0-1.0`), and optionally `source` (a URL) and `author` |

### Games

| Field | Meaning |
| - | - |
| `game` | The game's slug on Patch, such as `hollow-knight` |
| `role` | `host` (the default): the game it plays in. `companion`: another game it needs on the player's PC, for its files or to run beside it. `related`: one it's only related to. |
| `version` | The game versions it works with, such as `>=1.6` |
| `stores` | The stores the game can come from: `steam`, `epic`, `gog`, `xbox`, `ea`, `ubisoft`, `battlenet` or `microsoft` |
| `builds` | Exact builds per store, such as `{ "steam": ["15873461"] }`. Leave it out to accept any build. |

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:

```json theme={null}
{ "games": { "half-life-2": { "role": "companion", "folder": "C:\\Program Files (x86)\\Steam\\steamapps\\common\\Half-Life 2" } } }
```

### Loaders

A `loader` 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`.

| `loader` | Games | Notes |
| - | - | - |
| `bepinex-5` | Any but `peak` | In `how-to-fish` it goes in `{game}/How to Fish`: map plugins to `{game}/How to Fish/BepInEx/plugins` |
| `bepinex-peak` | `peak` | |
| `ultimate-asi-loader` | Any | Goes beside the game's program. In `rocket-league` that's `{game}/Binaries/Win64`: map `.asi` files there |
| `cet`, `red4ext` | `cyberpunk-2077` | |
| `reshade-addon` | `grand-theft-auto-v-legacy`, `grand-theft-auto-v-enhanced` | Name the edition your mod is for. Experimental on Enhanced |
| `ue4ss-hello-neighbor` | `hello-neighbor` | Experimental |
| `metamod-source`, `sourcemod` | `left-4-dead-2` | |
| `metamod-source-2`, `counterstrikesharp` | `counter-strike-2` | |
| `fabric`, `quilt`, `neoforge`, `forge` | `minecraft-java` | Needs that game's exact `version`, and takes an optional loader `"version"` |

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.

| Field | Meaning |
| - | - |
| `id` | Its name, such as `main` |
| `file` | `"plugins/"`, `"pack.zip"` or `""` |
| `label` | What players see, such as `HD textures` |
| `kind` | `main` (players need it, the default), `optional` (players can turn it on) or `extra` (not installed) |
| `required` | Install it even though it isn't `main` |
| `extract` | It's a single `.zip` to unpack when it's installed |

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:

| Folder | Is |
| - | - |
| `{profile}` | The profile folder Patch keeps for this game and set of mods |
| `{game}` | The host game's install folder |
| `{game:slug}` | Another listed game's install folder |
| `{saves}` | The game's save folder |
| `{documents}`, `{saved-games}`, `{appdata}`, `{localappdata}`, `{locallow}`, `{userprofile}` | The player's own 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 like `PROGRA~1`. Use `{appdata}`, `{documents}` and the other folders, not their paths through `{userprofile}`.
* An `exe` launch 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 like `CON` or `NUL`.

### 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](#tests) 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 in `settings` 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`:

* `ini` and `cfg`: `Section.Key` sets `Key = value` under `[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.c` sets that member, making the objects on the way.
* `xml`: `Root.Audio.Volume` sets that element's text, each step being the first child of that name, and `Root.Audio.@volume` sets 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 lists `test.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](https://docs.patch.gg/review.md#the-test) 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](https://docs.patch.gg/mcp-server.md).

## Validation

Patch checks the recipe and the file list when you create a release. Each problem comes back as an [error code](https://docs.patch.gg/api-reference/introduction.md#errors) with the details:

| Code | When |
| - | - |
| `recipe_invalid` | The recipe doesn't match the schema or its rules, or doesn't match the files: a component holds nothing, a file is in no component, or the browser game's entry isn't there. `details.issues` lists each problem with its place, such as `mappings.0.to`. |
| `files_invalid` | A file's path, SHA-256 or size is wrong, or a path is listed twice |
| `version_invalid` | The release's `version` isn't semver, such as `1.2.0` |
| `unknown_host_game` | A game in `games` isn't one Patch knows |
| `manifest_retired` | The request sent a `patch.json` manifest, which Patch no longer takes |

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.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.