Files
ComfyUI/docs/magic-patch.md

9.3 KiB

Magic Patch CLI

Magic Patch converts a pristine or partially converted ComfyUI custom-node pack into a new, complete V2 pack folder. It delegates implementation work to an already-installed and authenticated Codex or Claude Code CLI, then applies deterministic local acceptance gates. Comfy does not hold the contributor's model credentials or pay for the conversion inference.

Prerequisites

  • Python 3.13 for the current Comfy runtime and V2 contract.
  • Either Codex CLI or Claude Code, installed, authenticated, and usable from the current shell:
    • Codex CLI: follow OpenAI's current Codex CLI setup. On macOS or Linux, its documented standalone install is curl -fsSL https://chatgpt.com/codex/install.sh | sh. Run codex in a project directory and choose Sign in with ChatGPT (or another offered sign-in method) the first time it starts. OpenAI documents all supported methods on the Codex authentication page.
    • Claude Code: follow Anthropic's current Claude Code setup guide. Its recommended macOS/Linux/WSL native install is curl -fsSL https://claude.ai/install.sh | bash. Run claude and follow the browser login prompts. claude --version and claude doctor verify the installation. Anthropic documents account and provider choices on the Claude Code authentication page.
  • Node.js on PATH when converting frontend JavaScript, for an additional syntax check.
  • git and an authenticated gh CLI only when using --create-pr.
  • A ComfyUI checkout containing comfy_api and nodes.py to prove the result loads through the normal local V2 entrypoint. The current checkout is used automatically; override it with --core-root or COMFY_CORE_ROOT.
  • Optionally, an executable implementing the Magic Patch verifier protocol. The Secure Nodes project can provide comfy-secure-verify-pack, but Magic Patch does not import or require that project.

The command invokes only the contributor's ambient CLI login. It does not read an API key or call a model API directly. Run codex or claude once and finish its login before starting Magic Patch.

Convert a pack

From this repository:

export COMFY_CORE_ROOT=/path/to/ComfyUI

/path/to/python3.13 -m tools.magic_patch \
  /path/to/Original-Pack \
  /path/to/Original-Pack-converted \
  --agent auto

auto prefers Codex and falls back to Claude Code. Select one explicitly with --agent codex or --agent claude; use --model only when a provider-specific override is needed.

The input is never modified. The output path must not already exist. Magic Patch creates a sibling staging directory, clones the whole original pack into v2/, overlays any existing V2 draft, and permits the agent to edit only that staged copy.

Patch identity is the pack's upstream Git commit: x plus the first seven commit characters. When the input folder is the root of its Git checkout, Magic Patch discovers it automatically. For an extracted archive or a pack nested inside a monorepo, pass the pinned upstream commit explicitly with --source-sha; use --pack-slug when the registry slug cannot be derived from the input folder name.

A successful run publishes four sibling artifacts as one no-overwrite set:

Original-Pack-converted/
  ... unchanged original files ...
  v2/
    ... complete converted pack ...
    comfy-api.pyi
    comfy-api.d.ts
    pyproject.toml
    secure-nodes.json
    V2_CONVERSION.md
Original-Pack-converted.zip
Original-Pack-converted.patches/
  original-pack-x1a2b3c4.json
  original-pack-x1a2b3c4.diff
Original-Pack-converted.magic-patch.json

The ZIP contains exactly one top-level Original-Pack-converted/ folder with the pristine source files at its root and the complete conversion under its v2/ child. It can be submitted directly as a V2 pack. ZIP member order, timestamps, contents, and modes are deterministic. Override its destination with --pack-zip, or omit it with --no-pack-zip.

The .patches/ directory contains the same .json manifest and reviewable .diff pair used by the backend deployment path. Magic Patch applies the pair to a fresh copy of the original and requires the result to match the published v2/ tree byte-for-byte before it exposes any artifact. Override that directory with --patch-output.

On failure, no output folder, ZIP, report, or patch directory is published. The command prints the preserved staging path, containing agent logs and FAILURE.txt, so a subsequent run can be diagnosed without losing evidence.

Use --dry-run to check paths, bundled contracts, the selected agent, and PR prerequisites without invoking a model.

Agent loop and acceptance gates

Each pass receives the complete pack plus trusted Python/frontend conversion guidance. It returns a schema-constrained census and test record. Deterministic findings become the repair prompt for the next pass, up to --max-passes.

Publishing requires all of the following:

  • the original pack tree is byte-for-byte and mode-for-mode unchanged;
  • pack-owned AGENTS.md, CLAUDE.md, .agents/, .claude/, and .codex/ content was not exposed as agent control input and is restored correctly;
  • v2/ is a complete pack with no symlinks, caches, or nested v2/;
  • the bundled published .pyi and .d.ts contracts are unchanged;
  • Python parses and has no ambient ComfyUI imports;
  • declared frontend JavaScript parses when Node.js is available and contains no known legacy host surfaces;
  • secure-nodes.json is safe and agrees with pyproject.toml;
  • the normal local ComfyUI V2 loader registers exactly the manifest node ids;
  • the optional secure verifier passes when it is installed;
  • a generated JSON/diff pair recreates the complete v2/ tree byte-for-byte;
  • the agent census has zero pending items and lists passing tests.

Source code remains untrusted data, but a coding agent necessarily reads it. The normal local V2 load executes the converted entrypoint in a child process; it is not an operating-system security boundary. Run deliberately hostile repositories in a disposable machine or use the optional secure verifier.

Optional secure-sandbox verification

Sandbox verification is auto by default. Magic Patch looks for comfy-secure-verify-pack on PATH, or for the command named by COMFY_MAGIC_PATCH_SANDBOX_VERIFIER. If no verifier is installed, all public validation still runs and conversion can succeed. The public utility never imports the secure runtime.

Use --sandbox-verification required when publication must have sandbox evidence, or --sandbox-verification off to skip discovery. An explicit verifier can be selected with --sandbox-verifier /path/to/command; its time limit is controlled by --sandbox-timeout.

The public utility and optional verifier communicate through versioned JSON request and result files. A discovered verifier that crashes, returns malformed evidence, or reports an escape blocks publication even in auto mode. Passing dynamic checks is evidence that the exercised imports and operations remained inside the sandbox; it is not a mathematical proof that every possible code path is incapable of escaping.

Magic Patch invokes the verifier without a shell:

comfy-secure-verify-pack --request REQUEST.json --output RESULT.json

The request format is comfy-magic-patch-verifier-request/1 and supplies absolute pack, source, optional core_root, and python_executable paths. The verifier must write comfy-magic-patch-verifier-result/1 with a non-empty verifier name, status equal to passed, failed, or unavailable, and string arrays named checks and errors. Failed and unavailable results require at least one error; passing results may not contain errors. In auto mode, an unavailable platform backend is treated like an uninstalled verifier; in required mode it blocks publication. This narrow protocol lets other sandbox implementations integrate without coupling ComfyUI to private modules.

Open a pull request

Add --create-pr to publish the validated v2/ tree with the ambient gh authentication:

/path/to/python3.13 -m tools.magic_patch \
  /path/to/upstream-pack-checkout \
  /path/to/upstream-pack-converted \
  --agent codex \
  --create-pr

Magic Patch discovers the GitHub repository and default branch from the source checkout. It clones that repository into a disposable directory, checks out the source revision when available, commits only the new or updated v2/ tree, pushes a generated branch, and opens a formatted PR against the original repository. The body records the backend/frontend census, tests, validation evidence, and conversion notes. The input checkout remains untouched.

If the authenticated user cannot push to the original repository, Magic Patch creates or reuses their GitHub fork and opens a cross-fork PR. Direct the PR at a different repository or a pack nested within a monorepo with:

--pr-repo owner/repository \
--pr-pack-path path/to/pack \
--pr-base main \
--pr-draft

--pr-branch and --pr-title override the generated branch and concise commit title. PR publication happens only after local conversion succeeds. A GitHub failure does not remove the converted pack or its local report.