comfy-cli

v2026.09.24

The `comfy` CLI for ComfyUI: install/update/bisect custom nodes, snapshot/restore state, publish to the registry, run workflows headlessly. Use when the user runs `comfy`, `comfy node`, or `comfy run`.

GitHub
安装命令
npx skhub add laurigates/comfy-cli
Markdown
SKILL.md

comfy CLI on this install

comfy (comfy-cli) is the upstream Comfy Org Python CLI. Installed here via uv tool at ~/.local/share/uv/tools/comfy-cli/ (binary symlink at ~/.local/bin/comfy). The default workspace is already pinned to your ComfyUI install's root — never pass --workspace, never run set-default once it's pinned.

The service runs via systemd on 0.0.0.0:8188 (see project CLAUDE.md). The CLI's lifecycle commands assume it owns the process. Most don't apply here. The useful surface is custom-node management, headless API execution, and snapshots. Almost everything else is either a no-op or actively conflicts with the systemd unit.

When to Use This Skill

Use this skill when...Use instead when...
The user asks to use the comfy CLI - install/update/bisect nodes, snapshot/restore, publish, run workflows headlesslyManaging custom nodes via the ComfyUI-Manager UI directly
Running a workflow via comfy run --workflow ... --port ...Running headlessly over the raw HTTP API -> comfyui-pack-live-smoke

What to use

TaskCommand
List installed custom nodescomfy node simple-show installed
Install a custom node by registry namecomfy node install <name>
Install a node directly from the comfy registry by ID (use when Manager's curated list lags or the node was just published)comfy node registry-install <node-id>
Install all custom nodes referenced by an imported workflowcomfy node install-deps --workflow path/to/workflow.json
Update one or more nodescomfy node update <name> [<name> ...]
Update every custom node + Comfy corecomfy node update all
Reinstall a node's requirements.txt (after a venv rebuild or import error)comfy node fix <name>
Snapshot current node state to JSONcomfy node save-snapshot --output snapshots/$(date -I).json
Restore a snapshotcomfy node restore-snapshot snapshots/<file>.json
Bisect which custom node is breaking startupcomfy node bisect start then good/bad
Generate a dep manifest for a workflow you're sharingcomfy node deps-in-workflow --workflow X.json --output X.deps.json
Run an API-format workflow against the running servercomfy run --workflow path.json --port 8188 --timeout 600 --verbose
Show installed models in a tablecomfy model list
Inspect workspace / running-server statecomfy which, comfy env

What NOT to use here

CommandWhy not
comfy launch [--background]Spawns a second ComfyUI process competing for port 8188 and the GPU against the systemd unit. Use sudo systemctl start/stop comfyui.service instead — the project CLAUDE.md covers this.
comfy stopOnly stops a comfy launch --background process — has no effect on the systemd-managed instance.
comfy installAlready installed. The directory is the install.
comfy update comfy / comfy update allThese do git pull + pip install -r requirements.txt inside .venv/. Functionally identical to the manual recipe in project CLAUDE.md, but update all ALSO mass-updates every custom node (often breaks pinned workflows). Prefer the manual git pull + .venv/bin/python -m pip install -r requirements.txt, then comfy node update <specific> only when needed.
comfy standaloneBuilds a portable Python interpreter — irrelevant; we have .venv/.
comfy set-defaultAlready pinned to your install root — re-running it is a no-op at best.
comfy manager enable-gui / disable-gui / clearOperates on ComfyUI-Manager's reserved-startup-action state. The Manager web UI handles this fine; the CLI flags are rarely needed.

Recipes

Importing a workflow with unknown custom nodes

When a downloaded workflow references nodes that aren't installed, the page shows red boxes on load. Instead of hunting through ComfyUI-Manager:

comfy node install-deps --workflow user/default/workflows/<topic>/<file>.json
# Then ask the user to:
# ! sudo systemctl restart comfyui.service

Restart is required so the new nodes import. --workflow accepts both .json and embedded-metadata .png exports.

Running a workflow headlessly

comfy run --workflow X.json requires the API-format export, not the regular UI workflow JSON. To get one: open the workflow in the web UI → Settings → "Enable Dev mode Options" → top menu shows "Save (API Format)".

comfy run \
  --workflow path/to/workflow_api.json \
  --port 8188 \
  --timeout 600 \
  --verbose

The default --timeout 30 is too low for any video or multi-step workflow on this install (Wan 2.2 I2V at 8 steps is ~60–120 s on a 4090). Bump it.

--host defaults to localhost; the systemd unit binds 0.0.0.0:8188 so local connection works without flags. Output files land in output/ as usual — the CLI doesn't relocate them.

Safe mass node update (with the post-install venv-mismatch workaround)

Bulk updates frequently break a workflow somewhere. The non-obvious gotcha: comfy node update's post-install pip step runs against comfy-cli's pipx venv, not ComfyUI's .venv/ — every newly-introduced custom-node Python dep ends up in the wrong interpreter where ComfyUI can't see it. You have to reinstall each pack's requirements.txt against .venv/ manually.

Full recipe (verified 2026-05-08):

# 1. Snapshot for rollback
mkdir -p snapshots
comfy node save-snapshot --output snapshots/$(date -I)-pre-update.json

# 2. User stops the service (sudo, not the agent's shell)
#    ! sudo systemctl stop comfyui.service

# 3. Update core
git -C <comfyui-root> pull --ff-only
.venv/bin/python -m pip install -r requirements.txt

# 4. Update every custom node (DO NOT trust its post-install pip step)
comfy node update all

# 5. Manually reinstall every node's requirements into the CORRECT venv
for req in custom_nodes/*/requirements.txt; do
  echo ">>> $(dirname "$req" | sed 's|custom_nodes/||')"
  ./.venv/bin/python -m pip install --quiet -r "$req" 2>&1 | tail -3
done

# 6. Pin transformers <5 (see Pitfalls — diffusers/peft chain breaks otherwise)
.venv/bin/python -m pip install 'transformers>=4.50.3,<5'

# 7. Re-apply local hot-patches (project CLAUDE.md tracks them, e.g. WanVideoWrapper)

# 8. User restarts the service
#    ! sudo systemctl restart comfyui.service

The snapshot captures git refs of every custom node + the core ComfyUI commit

  • the pip freeze of .venv/. Restoring rolls all three back:
comfy node restore-snapshot snapshots/$(date -I)-pre-update.json
git -C <comfyui-root> reset --hard <pre-update-sha>

After restart, verify health with the PID-filtered journal query (see "Reading the right service boot in journalctl" pitfall).

Bisecting a startup IMPORT FAILED

Project CLAUDE.md lists two known-broken packs (comfyui-depthflow-nodes, comfyui_magicclothing) that fail on every startup and are non-fatal. If a new pack is breaking the service:

sudo systemctl stop comfyui.service
comfy node bisect start
# CLI launches ComfyUI with half the nodes disabled. Test load.
comfy node bisect bad   # if the failure reproduces
comfy node bisect good  # if it doesn't
# Repeat until a single node is identified, then:
comfy node bisect reset
sudo systemctl start comfyui.service

Run this only with the systemd unit stopped — bisect spawns its own comfy launch instances and will fight the unit for port 8188 otherwise.

Reinstalling a node's deps after a venv rebuild

If python3 -m venv --upgrade .venv (or a full venv recreate to fix the broken-shebang issue from project CLAUDE.md) leaves a custom node missing its Python deps:

comfy node fix <node-name>             # one node
comfy node fix all                     # every installed node

This re-runs each node's requirements.txt against the current .venv/. Faster than reinstalling the node itself, which clones the repo again.

Pitfalls

  • comfy run rejects UI workflow JSON. It needs the API-format export. The error is unhelpful — usually a JSON parse failure or KeyError: 'class_type'. If a workflow is imported from user/default/workflows/, those are UI exports — re-export through the web UI as API format first.

  • --port 8188 is required for comfy run here. The CLI defaults to hitting the port the CLI would launch on, not the systemd unit's port. Without --port, the run hangs until --timeout.

  • comfy node install <repo-url> is registry-only. It takes a registry name (matched against ComfyUI-Manager's custom-node-list.json), not a GitHub URL. To install from a URL, git clone into custom_nodes/ and comfy node fix <dirname> to install its requirements.

  • comfy node install <node-id> 404s with Node 'X@unknown' not found for recently-published nodes. The default channel checks the bundled ComfyUI-Manager custom-node-list.json, which is rebuilt on a separate cadence from the comfy registry itself. New publishes — and any version still in NodeVersionStatusPending while the auto security scan runs — aren't there yet. Workaround: comfy node registry-install <node-id> (hidden subcommand) downloads the published node.zip straight from cdn.comfy.org via the registry API at api.comfy.org/nodes/<id>/versions — same artifact, bypasses the curated list. Use this for first-party installs of your own packs right after comfy node publish.

  • NodeVersionStatusPending transitions to Active automatically. Every published version is held as Pending until the (private) automated security scan finishes — no publisher action required, just wait (observed ≤ a few hours). Check status with curl -s 'https://api.comfy.org/nodes/<id>/versions' | jq '.[] | {version,status}'. Until it transitions, comfy node install won't see it but comfy node registry-install will.

  • NodeVersionStatusFlagged does NOT auto-clear (distinct from Pending). The scan flagged the version; it stays non-installable and comfy node install falls back to the older Active version. The public API exposes no reason — it's only on registry.comfy.org. Republishing re-runs the scan; flags can be false positives (an identical change flagged some laurigates packs but not their siblings). Full publishing/status playbook: .claude/rules/comfy-registry-publishing.md.

  • A green comfy node publish can still ship a broken tarball. For TS-built packs the registry node.zip shipped an empty web/dist/ (dead frontend) for weeks despite passing runs — root cause was publish-node-action@v1 lacking skip_checkout. Always verify by downloading the node.zip from the version's downloadUrl and checking for web/dist/index.js. See comfy-registry-publishing.md.

  • Restart is not automatic. comfy node install/update/uninstall modifies custom_nodes/ but does not signal the running server. New nodes don't load until the service restarts. The CLI prints a "restart required" notice; honor it via ! sudo systemctl restart comfyui.service (the agent can't sudo — ask the user).

  • comfy model download ignores this install's family-subfolder convention. Project CLAUDE.md requires placement under models/<category>/<family>/.... The CLI takes a --relative-path but no awareness of family layout, so prefer the hf download → /tmp/staging → mv recipe in project CLAUDE.md for any model that has a family folder. comfy model download is acceptable for one-off files at category root (e.g. a .pth upscaler going to models/upscale_models/).

  • comfy model remove physically deletes files. If a workflow still references the model, it crashes on next run. Prefer mv to a backup dir for anything you might want back.

  • Updating comfy-cli. When the CLI prints a "New version available" notice on each invocation, upgrade via uv tool upgrade comfy-cli (per global tool-installation priority — uv tool replaced the prior pipx install here). Verify with comfy --version. Don't pip install --upgrade against the system Python or the ComfyUI .venv/ — the binary is a uv-tool symlink to its own isolated venv at ~/.local/share/uv/tools/comfy-cli/, so pip-into-other-interpreters is a no-op for the comfy command. If a stray comfy-cli is still installed inside the ComfyUI .venv/ from a previous era, uninstall it (.venv/bin/python -m pip uninstall -y comfy-cli) — the in-venv copy is unused now that uv tool owns the symlinks.

  • comfy node update's post-install pip uses the WRONG venv. The ComfyUI-Manager subprocess that handles requirements.txt for newly- updated nodes is invoked with comfy-cli's sys.executable (~/.local/pipx/venvs/comfy-cli/bin/python), not the install's .venv/. Symptom: post-update logs show EXECUTE => ['~/.local/pipx/ venvs/comfy-cli/bin/python', '-m', 'uv', 'pip', 'install', ...], and the new packages don't appear in .venv/bin/python -m pip list. Fix: loop over custom_nodes/*/requirements.txt and reinstall against the correct interpreter (see "Safe mass node update" recipe). The same bug affects comfy node fix and comfy node install for the same reason.

  • transformers 5.x breaks the diffusers/peft chain. ComfyUI core's requirements.txt is transformers>=4.50.3 with no upper bound, so any pip re-resolve may pull transformers==5.x. transformers 5.0 removed HybridCache and FLAX_WEIGHTS_NAME; peft<0.18 and most installed diffusers releases (≤0.35.x as of 2026-05) import those symbols at the top level, so half the diffusion-using custom nodes (brushnet, hunyuanvideowrapper, fluxtrainer, HiDream-Sampler, FramePackWrapper, nunchaku, …) fail with ImportError: cannot import name 'HybridCache' from 'transformers'. Fix: pip install 'transformers>=4.50.3,<5' (and optionally pip install --upgrade peft to 0.19+ for forward compatibility). Re-pin after every core upgrade until either (a) ComfyUI core adds transformers<5 upper-bound, or (b) installed diffusers/peft releases support transformers 5.x.

  • ComfyUI-Manager-installed packs are tarball snapshots, not git clones. The Manager pulls registry zip/tarballs and unpacks into custom_nodes/<name>/, with no .git directory. So git pull / git log won't work, and the version is pinned to whatever the registry served at install time — often weeks behind upstream master. Before patching a pack's source, check upstream: a closed issue with a recent release tag may already contain the fix. Quick recipes:

    # See current upstream of one file without cloning
    gh api repos/<owner>/<repo>/contents/<path> --jq '.content' | base64 -d
    
    # Install/upgrade pack from upstream master, replacing the snapshot
    rm -rf custom_nodes/<dir-name>
    git -C custom_nodes clone https://github.com/<owner>/<RepoName>
    ./.venv/bin/python -m pip install -r custom_nodes/<RepoName>/requirements.txt
    

    After a fresh clone, the dir name is the GitHub repo's CamelCase form (e.g. ComfyUI-Thumbnails), not Manager's lowercase form. That can matter — see the next pitfall.

  • Custom-node JS hardcodes the GitHub CamelCase dir name in relative imports. ComfyUI serves a pack's web/ at /extensions/<dir-name>/..., where <dir-name> is the on-disk directory. Many packs' JS does import "../../<RepoName>/js/foo.js" with the GitHub CamelCase name — fine for a fresh git clone, broken when ComfyUI-Manager normalized the dir to lowercase. Symptom: console errors on relative imports / [vite:preloadError] / 404s on the pack's own JS in the network tab. Fix: rename the dir to match the JS imports (mv custom_nodes/<lower> custom_nodes/<RepoName>), then restart the service. (Do not also fix the JS — upstream churns it.)

  • Reading the right service boot in journalctl. journalctl -u comfyui.service -b is system boot, not service restart — every ComfyUI run since the last reboot is in there. Filter to the current service run by MainPID:

    PID=$(systemctl show comfyui.service -p MainPID --value)
    journalctl _PID=$PID --no-pager
    

    Or --since "$(systemctl show comfyui.service -p ActiveEnterTimestamp --value | cut -d' ' -f2-)" if filtering by date. The -b form will silently match the first "Import times for custom nodes:" block, which is whichever ComfyUI run came first after the last reboot — a trap when comparing pre/post update.

References

发现
标签

此技能尚未发布标签。

版本
最新版本元数据

版本

v2026.09.24

发布时间

Sep 24, 2026

分类

未分类

许可证

MIT

源路径

comfyui-plugin/skills/comfy-cli

默认分支

main

最新提交

1668324

Tree SHA

b2d4cc3