Agent skill

Authoring VPhone Patch Sets

by Lakr233 in Lakr233/vphone-cli

Explains how to declare a firmware patch in a vphone patch set, add a new set, or write a preset, including naming, gating and the checks that catch undeclared patches.

MITAuto-check passedDevelopment

Install Authoring VPhone Patch Sets

skills CLI
$ npx skills add Lakr233/vphone-cli --skill authoring-patch-sets -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install Lakr233/vphone-cli authoring-patch-sets --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/Lakr233/vphone-cli.git skills-src && mkdir -p .claude/skills && cp -r skills-src/Skills/authoring-patch-sets .claude/skills/authoring-patch-sets && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
authoring-patch-sets
GitHub stars
15k
Token cost
~4.6k tokens
SKILL.md length
2,086 words
Files
1
Skills in repo
3
Repo updated
First seen
Licence
MIT

At a glance

Explains how to declare a firmware patch in a vphone patch set, add a new set, or write a preset, including naming, gating and the checks that catch undeclared patches.

  • Works in 4 steps: Write the patch as usual. Nothing about… → Note the record identifier your patch… → Declare it in the right set, with the… → …
  • Adding or changing a patch in FirmwarePatcher
  • SKILL.md covers The Three Layers, Adding a Patch to an Existing…, Version Gates and Boot-Essential Patches, plus 4 more sections
  • Calls xcodebuild

What it does

In the vphone project every firmware patch is declared in a patch set, selected by a preset and written only if its gate allows. A patch that exists in code but in no manifest still applies; it just cannot be turned off and prints a warning on every run. The skill explains the three layers: a patch (`VPhonePatchDeclaration`) listed in a set's patches array, a set (`VPhonePatchSetManifest`) in a Swift file under `FirmwarePatcher/PatchSets/` or in a `.vphonepatchset` bundle's manifest, and a preset (`VPhonePatchPreset`) in a plist.

To add a patch, you write it as usual with the ARM64 disassembler and encoder, note the `patchID` it emits, declare it in the right set, then build, run the golden corpus and grep the logs to confirm the line 'declared by no patch set' is absent. Identifiers follow a component-effect-name scheme, where the component names the boot stage or file the bytes land in (for example kernel, devicetree, dyld or a system binary) and the effect (boot, exp or cfw) is derived from the patch's flags. The excerpt is cut off before the sections on version gates, presets and out-of-tree sets.

When your agent uses it

  • Adding or changing a patch in FirmwarePatcher
  • Putting a version gate on a patch
  • Making a patch selectable or off by default
  • Building an out-of-tree .vphonepatchset

Example prompts

  • “Declare my new kernel boot patch in the right patch set and verify nothing is left undeclared.”
  • “Make this patch off by default and add it to a preset.”
  • “Create an out-of-tree vphonepatchset for the new device tree patch.”

Requirements

  • A checkout of the vphone-cli repository

Workflow steps

4 steps, taken from the first numbered list in SKILL.md.

  1. Write the patch as usual. Nothing about patch code changes: same
  2. Note the record identifier your patch emits — the patchID: you pass to
  3. Declare it in the right set, with the identifier being the record
  4. Build and run the golden corpus. A record no declaration covers prints

What it can do on your machine

Read from SKILL.md and the folder at commit aa20eb8. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • xcodebuild

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Authoring VPhone Patch Sets loads about 4.6k tokens when it runs. Until then it costs about 77 tokens; SKILL.md has 2,086 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~77
When it runs · the whole SKILL.md, loaded when a task matches
~4.6k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from Lakr233/vphone-cli at commit aa20eb8, republished under its MIT licence (© Lakr233). 2,086 words, ~4,554 tokens.

Download SKILL.mdSave it as .claude/skills/authoring-patch-sets/SKILL.md (or your agent's skills folder).
name
authoring-patch-sets
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.

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

LayerTypeWhere
A patchVPhonePatchDeclarationa set's patches array
A setVPhonePatchSetManifestFirmwarePatcher/PatchSets/*.swift, or a .vphonepatchset's Contents/Resources/Manifest.plist
A presetVPhonePatchPresetVPhoneExecutable/VPhoneVirtualization/Resources/patches_presets/*.plist

The types live in VPhoneExecutable/VPhoneCommand/VPhonePatchKit/PatchSet/. The nine in-tree sets and the two 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:

    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,
    )
  4. Build and run the golden corpus. A record no declaration covers prints [!] <component>: <id> is declared by no patch set; applying it anyway. Grep the logs for declared by no patch set — it must be absent.

Naming

A patch identifier is {component}-{effect}-{name}, hyphen-separated:

  • component — where the bytes land: avpbooter, ibss, ibec, llb, txm, kernel, devicetree, dyld (the shared cache), preboot, or system-<binary> for a guest system binary or file (system-seputil-boot-gigalocker_uuid, system-vphoned-boot-install).
  • effect — derived, never chosen: boot if bootEssential, else exp if standard leaves it off, else cfw. A patch that changes either property is renamed with it.
  • name — snake_case, [a-z0-9_], no dots or hyphens.

Every patch identifier names its component, effect and patch in FirmwarePatchSetCatalogTests checks the shape, the effect and uniqueness for every bundled declaration.

Identifiers Are the Contract

A declaration covers its own record and any record <identifier>.<site> — only a dot starts a site:

  • kernel-boot-kcall10 covers kernel-boot-kcall10.sy_call, kernel-boot-kcall10.sy_munge, …
  • kernel-boot-sandbox_ext covers kernel-boot-sandbox_ext.3 and every other index
  • kernel-boot-post_validation does not cover kernel-boot-post_validation_unsigned
  • kernel-cfw-debugger does not cover kernel-cfw-debuggerless

An underscore continues a snake_case name, so it never separates a site: emit .1, not _1.

Pick the granularity a user would want to tick. One declaration per patch method is usually right — a patch writing four sites that only work together is one checkbox, because half of it would not boot. Where sites are genuinely independent, declare them separately: kernel-*-sandbox_* is five declarations, one per MACF hook, because turning one hook off is a sensible thing to want.

Never let one declaration read as a site of another. No patch identifier is a record-site prefix of another fails if you do.

Version Gates

applicability is the only correct way to say "this patch is for release X". It is a structured enum, never a string:

swift
VPhonePatchApplicability(iOSBase: .major(27))                        // every 27.x
VPhonePatchApplicability(iOSBase: .release(major: 26, minor: 0))     // exactly 26.0
VPhonePatchApplicability(cloudOS: .atLeast(major: 26, minor: 4))     // 26.4 and later
VPhonePatchApplicability(iOSBase: .oneOf([.release(major: 26, minor: 0), .major(18)]))

iOSBase is the iPhone base whose userland is restored into the guest; cloudOS is the release supplying the kernel and boot chain. Only major and minor are compared, so 18.6.2 satisfies .major(18).

An unreadable version satisfies only .any. That is deliberate: a patch pinned to a release must not apply when nothing knows which release this is.

Two rules follow, and they are the ones people get wrong:

  • A version gate is not a preference. Use it when applying the patch elsewhere would patch the wrong shapes or break the guest. Do not use it to express "most people want this off" — that is what a preset's block list is for.
  • A preset cannot widen a gate. Checking a box in the UI changes the selection, never the applicability. So a patch pinned to iOS 18 is unreachable on 26.x, by design. If a patch genuinely needs to be available everywhere and off by default, give it .any applicability and block it in standard.

Do not add a boolean flag to FirmwarePipeline or a --force-something CLI flag for this. The patches behind --frida, --force-exc-guard and --force-dsc-maxslide are declarations now, and all three flags are gone. Adding another is a regression.

Boot-Essential Patches

Set bootEssential: true when the guest does not boot without the patch. This does not prevent it being turned off — an external set replacing it is a supported case — but it makes the consequence visible: the resolver reports it in droppedBootEssentials, fw patch logs [!] Boot-essential patches are off:, and the Launchpad editor warns before letting it be unticked.

A boot-essential declaration must have a summary. The test enforces it: it is the text someone reads before unticking a box that stops their VM booting.

Adding a New Patch Set

A set is worth creating when its patches share a reason to be on or off together. Copy the shape of FirmwareKernelFridaPatchSet.swift — it is the smallest one:

swift
public enum FirmwareMyPatchSet {
    public static let identifier = "com.vphone.patchset.my"

    public static let manifest = VPhonePatchSetManifest(
        identifier: identifier,
        name: "My Patches",
        summary: "One line on what this set is for",
        patches: [ /* declarations */ ],
        requires: ["vphone.kernel.base"],
        provides: ["vphone.my"],
        conflictsWith: [],
        after: ["vphone.kernel.base"],
    )
}

Then:

  1. Add the manifest to FirmwarePatchSetCatalog.bundled.
  2. If the set maps to a whole patcher, gate that patcher's construction in FirmwarePipelineComponents.buildComponentList on includesSet(...). This matters: a patcher left in place while its set is out of the preset emits records nothing declares, and undeclared records apply. Leaving the set out has to mean leaving the patcher out.
  3. Add the set to both shipped preset plists (both name every set; presets differ by their selection, not by which sets they draw on).
  4. Run the catalogue tests.
Capabilities, Requires, Conflicts, After

provides names capabilities; a set implicitly provides its own identifier. requires must be satisfied by some set in the plan or resolution fails. conflictsWith is enforced symmetrically — either side naming the other is a conflict, so an older set need not be edited to learn about a newer rival. There is no Supersedes: a conflict is an error, not a silent winner. after orders the sets, and a cycle is an error.

Two sets may not declare the same patch identifier. A set that replaces another set's patch gives its version a new identifier, and the preset blocks the original.

Writing a Preset

Presets are prewritten and reviewed. Nothing in the tool writes one; a VM records only which boxes its owner changed, and those compose on top.

standard is what every VM gets. Any other preset must be asked for with --preset. Both shipped presets name all nine sets and differ only in their selection:

xml
<key>Selection</key>
<dict>
	<key>Kind</key>
	<string>Block</string>
	<key>Patches</key>
	<array>
		<string>kernel-exp-frida_thread_set_state_entitlement_flag</string>
	</array>
</dict>

Kind is All, Allow or Block — never both lists, because a manifest able to carry both invites a preset where one silently wins. Use Block for "everything except"; use Allow only for a deliberately minimal preset, remembering that a patch added later will not be in it.

When you add or change a preset plist, mirror it in FirmwarePatchSetCatalog — that Swift copy is what a dev build with no staged bundle falls back to, and The shipped preset plists match the built-in copies fails if they drift.

Show full SKILL.md (943 more words)Show less
What a VM Records

A VM carries three patch records, each with its own writers:

FileWhat it saysWritten by
<vm>/PatchSelection.plistwhat the owner wants: a preset plus the boxes they changedfw set-patches; vm create (preset only); fw patch (rewrites it with what it ran, --preset included)
<vm>/PatchPlan.plistwhat the last fw patch resolvedfw patch
<vm>/PatchReceipt.plistwhat is live in the guest, part by parteach step that puts patched bytes into the guest

fw set-patches is how a person changes the first:

zsh
vphone-cli fw set-patches lab --preset extended --block kernel-cfw-debugger
vphone-cli fw set-patches lab                       # back to the preset alone

Each run writes the whole record, and only differences survive it — an identifier the preset already agrees with is dropped, so a later preset revision still reaches a VM whose boxes were never touched. The Launchpad's patch editor reads fw patches --json and writes through this verb rather than touching a VM bundle itself. Blocking a boot-essential patch is allowed; it warns on stderr.

A selection reaches the guest only through the step that owns the bytes, which depends on where the patch lands; changing it on a machine that already exists is covered in Research/Firmware/post_creation_patch_changes.md. In short: the boot chain follows the plan and reaches the guest only through a restore (or, for AVPBooter, the next fw patch); guest-side patches follow the current selection, and cfw install and cfw update-environment apply them both ways — on, or reverted when turned off — and record the Guest part of the receipt. vphone-cli fw patches <vm> compares all three records.

If your patch targets the guest, make it revertible: back the file up before the first write (.bak beside it) or, for the dyld cache, write through a DyldSharedCacheChunkSet with undo capture so its bytes land in the undo log. A guest patch with no way back is reported "not revertible" and stays live.

Out-of-Tree Patch Sets

Start from VPhoneExecutable/VPhoneCommand/VPhonePatchSetExample. It is a complete, building set — one iBEC string rewrite — and the loader tests load it, so it is kept working. Copy the target, change the identifier, replace the patcher.

An external set is a macOS loadable bundle with the .vphonepatchset extension:

Mine.vphonepatchset/
  Contents/
    Info.plist                 CFBundleExecutable names the binary
    MacOS/Mine                 exports vphone_patch_set_principal
    Resources/Manifest.plist    what the set declares
    _CodeSignature/             written by `vphone-cli patchset import`

Build it against the VPhonePatchKit.framework the bundle ships — it is built with library evolution and ships its .swiftinterface, so an out-of-tree set links against the same copy vphone-cli loads rather than statically linking a second disassembler. The target needs LD_RUNPATH_SEARCH_PATHS = @executable_path/../Frameworks so the framework beside vphone-cli is the one that resolves.

Three things make up the code side, and there is nothing else to implement:

swift
// 1. The entry point. One exported C symbol, copied verbatim.
@_cdecl("vphone_patch_set_principal")
public func makeMyPatchSetPrincipal() -> UnsafeMutableRawPointer {
    VPhonePatchSetPrincipal.export(MyPatchSet())
}

// 2. The principal, asked for one patcher per component the manifest declares
//    an enabled patch for. The inherited default throws for anything else, so a
//    manifest promising a component the code does not handle is a loud error.
public final class MyPatchSet: VPhonePatchSetPrincipal {
    public override func makePatcher(
        for component: VPhoneFirmwareComponent,
        data: Data,
        context: VPhonePatchSetContext,
    ) throws -> any BufferedPatcher {
        guard component == .iBEC else {
            return try super.makePatcher(for: component, data: data, context: context)
        }
        return MyPatcher(data: data, gate: context.gate, verbose: context.verbose)
    }
}

// 3. A BufferedPatcher per component: `patchedData` is how the pipeline reads the
//    bytes back, and `gate` is how a per-VM checkmark reaches your patch sites.

Not NSPrincipalClass, even though that is the usual way a loadable bundle names its entry point. PatchKit is built for library evolution, so a subclass of VPhonePatchSetPrincipal has a resilient superclass and its metadata is realized at first use, not at image load; the class is therefore not registered with the ObjC runtime when the bundle is mapped, NSClassFromString cannot find it, and Bundle.principalClass silently returns whichever class was registered. The exported symbol has none of that.

context carries what the plan resolved: iOSBase and cloudOS, the gate, the preset's parameters, and verbose. Ask the gate before you write, never after — a patch whose records are already in the buffer cannot be turned off.

Set MinimumPatchKitVersion to the API version you need. A set requiring a newer PatchKit than the bundle has is refused with a readable error instead of failing in the dynamic loader.

Then import it, which is also what signs it:

zsh
vphone-cli patchset import ./Mine.vphonepatchset   # copies into ~/.vphone/patchsets, ad hoc signs
vphone-cli patchset list                           # and says whether it still matches the import

A set straight out of Xcode is linker ad hoc signed: the Mach-O has a signature but the bundle seals no resources, so codesign --verify rejects it. Import runs one codesign --force --sign - pass over the bundle, which is what fixes that. The signature is re-checked from disk at every load, so a set edited afterwards stops loading until it is imported again.

A preset references one by identifier and path:

xml
<dict>
	<key>Kind</key><string>External</string>
	<key>Identifier</key><string>com.example.patchset.mine</string>
	<key>Path</key><string>/path/to/Mine.vphonepatchset</string>
</dict>

Both are required: the manifest found at that path must declare that identifier, or replacing the file would silently change which patches a preset applies.

Such a preset goes in ~/.vphone/patches_presets/, not in the bundle: shipped presets live in a sealed bundle and never reference anything outside it. A user preset cannot claim an identifier a shipped one already has, so nothing can redefine standard.

A loaded set patches the boot chain only. Every declared patch must target a firmware component; a guest-side target is refused at import, because the guest half of an install is the privileged step and loads no external set at all.

Security boundary. Root cfw install loads bundled sets only. An external set reaches a privileged run only after the Launchpad helper has imported it and pinned its cdhash. Unsigned or invalidly signed sets are ad hoc re-signed at import, not at load. Do not add a path that lets root open an arbitrary file.

The honest limit: a loaded set is code in the patching process. The gate is what makes its patches selectable, and a patcher that ignores the gate applies anyway. What does hold is the signature check at load and the rule above.

Checking Your Work

zsh
# Build
xcodebuild -workspace VPhone.xcworkspace -scheme VPhoneCommand -configuration Debug \
    -destination 'platform=macOS,arch=arm64' -derivedDataPath .build/XcodeCommand build

# What the catalogue now says
vphone-cli fw patches                 # for a person
vphone-cli fw patches --json          # what the Launchpad editor reads

# The model and catalogue tests
xcodebuild -workspace VPhone.xcworkspace -scheme FirmwarePatcherTests -configuration Debug \
    -destination 'platform=macOS,arch=arm64' -derivedDataPath .build/XcodeCommand test-without-building

The suites that must pass: Version requirements, Patch selection, Patch declarations, Plan resolution, Patch gate, Bundled patch set catalogue. Reference-fixture suites fail on machines without ipsws/ref_extract; that is an environment gap, not a regression.

Then verify byte-identity for anything you did not intend to change. Patching the same firmware with the same preset must produce the same bytes, and standard must keep producing what it produced before your change unless changing that was the point.

Finally: for any change applying new patches, update Research/0_binary_patch_comparison.md. That is a standing rule in AGENTS.md, and a new declaration with no research note is an incomplete change.

© Lakr233, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in Skills/authoring-patch-sets of Lakr233/vphone-cli.

Open the folder on GitHubat commit aa20eb8

Compare with similar skills

Authoring VPhone Patch Sets next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Authoring VPhone Patch Sets compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Authoring VPhone Patch Sets this skillLakr233/vphone-cli15k—~4.6kAutomated safety check: PassMIT
Sipeed I2C and SPI Hardware Controlsipeed/picoclaw30k—~578Automated safety check: PassMIT
RuView Hardware Setupruvnet/RuView97k—~1.8kAutomated safety check: NotesMIT
Esp32 Firmware Engineeralxv2016/folloup-sticky1151 repos~3.8kAutomated safety check: PassGPL-3.0
ExecuTorch Binary Size Reductionpytorch/executorch5.1k—~793Automated safety check: PassCustom licence
RuView mmWave Radar Setupruvnet/RuView97k—~907Automated safety check: NotesMIT

Similar skills

  • Reads and controls I2C and SPI peripherals on Sipeed boards such as LicheeRV Nano, MaixCAM and NanoKVM through the i2c and spi tools.

    30k GitHub stars~578 tokensUpdated 12 days ago
    DevelopmentAuto-check passed
  • Brings a RuView CSI sensing node online by building ESP32-S3 or ESP32-C6 firmware, flashing the board, provisioning WiFi and checking the serial output.

    97k GitHub stars~1.8k tokensUpdated today
    DevelopmentAuto-check: notes
  • Esp32 Firmware Engineer

    alxv2016/folloup-sticky

    ESP32 firmware engineering for ESP-IDF projects. An agent skill from alxv2016/folloup-sticky.

    115 GitHub starsUsed in 1 repo~3.8k tokens
    DevelopmentAuto-check passed
  • Measures and shrinks the ExecuTorch runtime binary by building a size test, analyzing it with bloaty and landing each reduction as its own pull request.

    5.1k GitHub stars~793 tokensUpdated today
    DevelopmentAuto-check passed
  • Sets up and runs 60 GHz and 24 GHz mmWave radar sensing on ESP32 boards in RuView, alone or fused with WiFi CSI.

    97k GitHub stars~907 tokensUpdated today
    DevelopmentAuto-check: notes
  • Driver Review

    FastLED/FastLED

    Review and implement hardware driver code — DMA safety, interrupt correctness, timing constraints, peripheral register usage, channel drivers, and peripheral mock implementations.

    7.5k GitHub stars~3.1k tokensUpdated today
    DevelopmentAuto-check passed

More from Lakr233/vphone-cli

  • Looks up symbols and addresses in vphone600 release and research kernel datasets, and cross-references XNU source, with findings that separate fact from inference.

    15k GitHub stars~530 tokensUpdated today
    Auto-check passed
  • VPhone Guest Control

    Lakr233/vphone-cli

    Drives a virtual iPhone running on an Apple Silicon Mac through the vphone-launchpad-cli, from checking host setup and starting a machine to tapping, typing and installing apps in the guest.

    15k GitHub stars~1.6k tokensUpdated today
    Auto-check passed

Categories

Questions about Authoring VPhone Patch Sets

What does Authoring VPhone Patch Sets do?

Explains how to declare a firmware patch in a vphone patch set, add a new set, or write a preset, including naming, gating and the checks that catch undeclared patches. In the vphone project every firmware patch is declared in a patch set, selected by a preset and written only if its gate allows. A patch that exists in code but in no manifest still applies; it just cannot be turned off and prints a warning on every run.

When should I use Authoring VPhone Patch Sets?

Authoring VPhone Patch Sets fits situations like: adding or changing a patch in FirmwarePatcher; putting a version gate on a patch; making a patch selectable or off by default; building an out-of-tree .vphonepatchset.

How do I install Authoring VPhone Patch Sets in Claude Code?

Run `npx skills add Lakr233/vphone-cli --skill authoring-patch-sets -a claude-code`. Or copy the skill folder (Skills/authoring-patch-sets in Lakr233/vphone-cli) into .claude/skills/authoring-patch-sets in your project. Claude Code loads it when a task matches its description.

How do I install Authoring VPhone Patch Sets in Codex?

Run `npx skills add Lakr233/vphone-cli --skill authoring-patch-sets -a codex`. Or copy the skill folder (Skills/authoring-patch-sets in Lakr233/vphone-cli) into .agents/skills/authoring-patch-sets in your project. Codex loads it when a task matches its description.

Can I use Authoring VPhone Patch Sets in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add Lakr233/vphone-cli --skill authoring-patch-sets -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/authoring-patch-sets, .gemini/skills/authoring-patch-sets, .github/skills/authoring-patch-sets and .opencode/skills/authoring-patch-sets in your project.

What does Authoring VPhone Patch Sets need to run?

Going by SKILL.md and its folder, Authoring VPhone Patch Sets needs the command-line tools its instructions call (xcodebuild). Our summary lists: A checkout of the vphone-cli repository.

Does Authoring VPhone Patch Sets access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Authoring VPhone Patch Sets safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Authoring VPhone Patch Sets use?

Authoring VPhone Patch Sets is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Authoring VPhone Patch Sets use?

About 4.6k tokens (SKILL.md is roughly 18k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Authoring VPhone Patch Sets?

Skills that share tags, products or a category with Authoring VPhone Patch Sets: Sipeed I2C and SPI Hardware Control (sipeed/picoclaw, 30k stars), RuView Hardware Setup (ruvnet/RuView, 97k stars), Esp32 Firmware Engineer (alxv2016/folloup-sticky, 115 stars) and ExecuTorch Binary Size Reduction (pytorch/executorch, 5.1k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Authoring VPhone Patch Sets?

Lakr233 (a GitHub user) maintains it in Lakr233/vphone-cli, which has 14,949 GitHub stars. The repository holds 3 skills in this directory. The repository was last updated on October 7, 2026.

Source: Lakr233/vphone-cli on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.