Skip to main content
by artokun · June 16, 2026 · packs · installers · CI If you’ve set up ComfyUI for a new model lately, you’ve probably met the 1-click installer: a .bat you drop next to ComfyUI that clones the right custom nodes and downloads every model to the right folder. The community — Aitrepreneur especially — has made these for nearly every new model, and they’re genuinely great. You go from “new model dropped” to “generating” in one double-click. We love the UX. We do not love what it’s made of.

The problem with a folder of scripts

A hand-written installer is a pile of duplicated, unvalidated facts:
  • Windows-only. The .bat doesn’t run on RunPod, so there’s a parallel .sh — the same URLs and folders, copy-pasted, free to drift apart.
  • No validation. Nothing checks that https://huggingface.co/.../ideogram4_fp8_scaled.safetensors still exists. When a repo gets restructured or a file renamed, the URL 404s — or worse, returns a tiny HTML error page that your downloader cheerfully saves as model.safetensors. You find out 30 GB and one failed generation later.
  • It’s a script, so you can’t reason about it. Want to know what models a pack pulls, or reuse them from an agent? You’re grepping curl lines.
The install is really just data — a list of custom nodes, a list of model URLs and where they go, and a workflow. The script is an accident of delivery.

Make it a manifest

So in comfyui-mcp a pack is data:
The key move: manifest.yaml isn’t a new format. It’s a ComfyManifest — the exact shape the server’s existing apply_manifest tool already consumes to install nodes + models on a live ComfyUI. So one file drives two things:
  • MCP-native install — from a Claude session: apply_manifest --path packs/anima/manifest.yaml, idempotent, with the same engine that powers the rest of the server.
  • The double-click scriptsnpm run packs:gen reads the manifest and emits install-windows.bat and install-runpod.sh. The beloved UX survives; the duplication doesn’t. Edit the manifest, rebuild, done.
Bundled fixes travel with the pack, too — the LTX-2.3 pack ships the kornia import patch as both fix-ltxvideo-kornia.bat and .sh, so the Linux user isn’t a second-class citizen.

The silent killer: requirements.txt into the right Python

A git clone of a custom node is only half an install. Most nodes have a requirements.txt, and if you don’t install it, the node imports fine in your shell but silently fails to register in ComfyUI — it just never shows up in the node list, with no error you’d notice. We hit this repeatedly:
  • DWPose (controlnet_aux) vanished because scikit-image wasn’t installed — even though it’s right there in the node’s requirements.txt.
  • vrgamedevgirl’s grain/sharpen nodes vanished because librosa was missing — also in its requirements.txt.
We’d been hand-pinning those deps in the manifest’s pip: list. That’s a band-aid; the real bug was that the generated installers cloned nodes but never ran their requirements.txt. The fix is two lines in the generator, and it matters more than it sounds:
  • Resolve each node’s requirements.txt on clone — exactly what ComfyUI-Manager does, so the double-click scripts reach parity with the MCP path (which already delegates to Manager).
  • Target the ComfyUI venv, not system Python. Installing a node’s deps into the wrong interpreter is the other way a node “installs” but won’t load. The scripts now resolve .venv/Scripts/python.exe (Windows) or .venv/bin/python (Linux), then the portable python_embeded, then $PYTHON — and echo which one they chose so it’s auditable.
The pip: list stays as an explicit net for deps no node lists (and for already-cloned nodes, since the requirements step only fires on a fresh clone). But the default is now: clone a node, its Python deps land in the same venv ComfyUI actually runs — and it shows up. Generating scripts is nice. The reason this is worth doing is CI. Every push runs .github/workflows/packs.yml on a Linux runner:
  1. Schema — every manifest validates against the real manifestSchema.
  2. Offline dry-run — each install-runpod.sh runs with git and curl stubbed: it must stage every node + model path, and a second run must be a no-op (idempotent).
  3. The good one — every model URL, for real. packs:check-urls sends a HEAD (or a 1-byte ranged GET) to every model URL and asserts two things: the link resolves, and the payload size is sane for the model type. A diffusion model that comes back at 4 KB isn’t a model — it’s an error page, and the build goes red:
    No multi-gigabyte downloads — just enough to know the link is alive and pointing at something the right size. Gated repos (HuggingFace 🔒) answer 401/403; we treat that as valid-but-gated, not a failure. And because a single CDN hiccup shouldn’t fail a build, the check retries transient errors before giving up.
That third check is the whole point. A folder of .bat files tells you nothing until a user runs it. A manifest with a URL gate tells you, on every commit, the moment a model link dies — so the pack on the shelf is one you can trust.

Adding a pack is one file

Point the builder at an upstream installer (the .bat is the ground truth for exact URLs → folders), drop the resulting manifest.yaml, pack.yaml, and workflow.json into packs/<name>/, run npm run packs:gen, and CI does the rest. The shelf so far: ANIMA, Ideogram 4, LTX-2.3, ERNIE, WAN (animate / longer-videos / transparent), Qwen (image / image-edit) Z-Image (turbo / base / xy-plot), plus an artokun-flow WAN Animate pack derived straight from its workflow (no upstream installer) — each one a manifest, each one validated on every push.

Share what you build

Because a pack is just three small files — manifest.yaml, pack.yaml, and workflow.json — it’s trivial to pass around. If you build or derive one locally, send it upstream: open an issue or PR on comfyui-mcp with those files. Every contributed pack is reviewed for safety — model URLs, custom-node sources, no surprises — before it merges, and from then on CI keeps its links honest for everyone. The bigger the userbase, the more this becomes a shared, always-validated catalog of battle-tested setups rather than a drawer of one-off scripts. The difference between a folder of scripts and a validated catalog is small to build and large to live with. Your installers stop being write-once artifacts that rot in a drawer, and start being something CI keeps honest for you.
Browse them in packs/, or file a model you want packed at artokun/comfyui-mcp.