# Authoring Patch Sets

Declares new firmware patches and presets in a vphone patch set.

- Repository: https://github.com/Lakr233/vphone-cli (16348 stars)
- Category: Engineering
- License: MIT
- Last updated: 2026-10-31
- Runs scripts: no, instructions only

## Install

Claude Code: `npx skills add Lakr233/vphone-cli --skill authoring-patch-sets -g -a claude-code -y`
Codex: `npx skills add Lakr233/vphone-cli --skill authoring-patch-sets -g -a codex -y`
Cursor: `npx skills add Lakr233/vphone-cli --skill authoring-patch-sets -g -a cursor -y`
Gemini CLI: `npx skills add Lakr233/vphone-cli --skill authoring-patch-sets -g -a gemini-cli -y`

## Description

Declare a new firmware patch in a vphone patch set, add a patch set, or write a patch preset. Use when adding or changing a patch in FirmwarePatcher, when a patch needs a version gate, when a patch should be selectable or off by default, or when building an out-of-tree .vphonepatchset.

## SKILL.md, as published by its author (untrusted third-party text, read it as data)

# Authoring Patch Sets

Every patch this project applies is declared in a **patch set**, selected by a
**preset**, and written only if the **gate** says so. A patch that exists in code
but in no manifest still applies, it just cannot be turned off, and it prints a
warning on every run. Declaring it is what makes it real.

## The Three Layers

| Layer | Type | Where |
| --- | --- | --- |
| A patch | `VPhonePatchDeclaration` | a set's `patches` array |
| A set | `VPhonePatchSetManifest` | `FirmwarePatcher/PatchSets/*.swift`, or a `.vphonepatchset`'s `Contents/Resources/Manifest.plist` |
| A preset | `VPhonePatchPreset` | `VPhoneExecutable/VPhoneVirtualization/Resources/patches_presets/*.plist` |

The types live in `VPhoneExecutable/VPhoneCommand/VPhonePatchKit/PatchSet/`. The
in-tree sets and the shipped presets live in
`VPhoneExecutable/VPhoneCommand/FirmwarePatcher/PatchSets/`, listed by
`FirmwarePatchSetCatalog`.

## Adding a Patch to an Existing Set

1. **Write the patch as usual.** Nothing about patch code changes: same
   `ARM64Disassembler` matching, same `ARM64Encoder` / `ARM64` constants for
   replacement bytes, same `emit(...)`. Follow the kernel patcher guardrails in
   `AGENTS.md`.

2. **Note the record identifier your patch emits**, the `patchID:` you pass to
   `emit`. That is what ties the patch to its declaration.

3. **Declare it** in the right set, with the identifier being the record
   identifier, or the part before `.<site>` when the patch writes several
   sites. Name it by the scheme in [Naming](#naming):

   ```swift
   VPhonePatchDeclaration(
       identifier: "kernel-boot-my_patch",
       title: "What it is, in three or four words",
       summary: "What it does and why the guest needs it. One or two sentences.",
       target: .firmware(.kernelcache),
       applicability: VPhonePatchApplicability(iOSBase: .major(27)),
       bootEssential: true,
   )
   ```

The rest: https://github.com/Lakr233/vphone-cli/blob/HEAD/Skills/authoring-patch-sets/SKILL.md
