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 headlessly |
Managing 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
| Task | Command |
|---|---|
| List installed custom nodes | comfy node simple-show installed |
| Install a custom node by registry name | comfy 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 workflow | comfy node install-deps --workflow path/to/workflow.json |
| Update one or more nodes | comfy node update <name> [<name> ...] |
| Update every custom node + Comfy core | comfy 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 JSON | comfy node save-snapshot --output snapshots/$(date -I).json |
| Restore a snapshot | comfy node restore-snapshot snapshots/<file>.json |
| Bisect which custom node is breaking startup | comfy node bisect start then good/bad |
| Generate a dep manifest for a workflow you're sharing | comfy node deps-in-workflow --workflow X.json --output X.deps.json |
| Run an API-format workflow against the running server | comfy run --workflow path.json --port 8188 --timeout 600 --verbose |
| Show installed models in a table | comfy model list |
| Inspect workspace / running-server state | comfy which, comfy env |
What NOT to use here
| Command | Why 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 stop |
Only stops a comfy launch --background process — has no effect on the systemd-managed instance. |
comfy install |
Already installed. The directory is the install. |
comfy update comfy / comfy update all |
These 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 standalone |
Builds a portable Python interpreter — irrelevant; we have .venv/. |
comfy set-default |
Already pinned to your install root — re-running it is a no-op at best. |
comfy manager enable-gui / disable-gui / clear |
Operates 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 freezeof.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 runrejects UI workflow JSON. It needs the API-format export. The error is unhelpful — usually a JSON parse failure orKeyError: 'class_type'. If a workflow is imported fromuser/default/workflows/, those are UI exports — re-export through the web UI as API format first.--port 8188is required forcomfy runhere. 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'scustom-node-list.json), not a GitHub URL. To install from a URL,git cloneintocustom_nodes/andcomfy node fix <dirname>to install its requirements.comfy node install <node-id>404s withNode 'X@unknown' not foundfor recently-published nodes. The default channel checks the bundled ComfyUI-Managercustom-node-list.json, which is rebuilt on a separate cadence from the comfy registry itself. New publishes — and any version still inNodeVersionStatusPendingwhile the auto security scan runs — aren't there yet. Workaround:comfy node registry-install <node-id>(hidden subcommand) downloads the publishednode.zipstraight fromcdn.comfy.orgvia the registry API atapi.comfy.org/nodes/<id>/versions— same artifact, bypasses the curated list. Use this for first-party installs of your own packs right aftercomfy node publish.NodeVersionStatusPendingtransitions toActiveautomatically. Every published version is held asPendinguntil the (private) automated security scan finishes — no publisher action required, just wait (observed ≤ a few hours). Check status withcurl -s 'https://api.comfy.org/nodes/<id>/versions' | jq '.[] | {version,status}'. Until it transitions,comfy node installwon't see it butcomfy node registry-installwill.NodeVersionStatusFlaggeddoes NOT auto-clear (distinct from Pending). The scan flagged the version; it stays non-installable andcomfy node installfalls back to the older Active version. The public API exposes no reason — it's only onregistry.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 publishcan still ship a broken tarball. For TS-built packs the registrynode.zipshipped an emptyweb/dist/(dead frontend) for weeks despite passing runs — root cause waspublish-node-action@v1lackingskip_checkout. Always verify by downloading thenode.zipfrom the version'sdownloadUrland checking forweb/dist/index.js. Seecomfy-registry-publishing.md.Restart is not automatic.
comfy node install/update/uninstallmodifiescustom_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'tsudo— ask the user).comfy model downloadignores this install's family-subfolder convention. ProjectCLAUDE.mdrequires placement undermodels/<category>/<family>/.... The CLI takes a--relative-pathbut no awareness of family layout, so prefer thehf download → /tmp/staging → mvrecipe in projectCLAUDE.mdfor any model that has a family folder.comfy model downloadis acceptable for one-off files at category root (e.g. a.pthupscaler going tomodels/upscale_models/).comfy model removephysically deletes files. If a workflow still references the model, it crashes on next run. Prefermvto 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 withcomfy --version. Don'tpip install --upgradeagainst 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 thecomfycommand. If a straycomfy-cliis 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 handlesrequirements.txtfor newly- updated nodes is invoked withcomfy-cli'ssys.executable(~/.local/pipx/venvs/comfy-cli/bin/python), not the install's.venv/. Symptom: post-update logs showEXECUTE => ['~/.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 overcustom_nodes/*/requirements.txtand reinstall against the correct interpreter (see "Safe mass node update" recipe). The same bug affectscomfy node fixandcomfy node installfor the same reason.transformers 5.x breaks the diffusers/peft chain. ComfyUI core's
requirements.txtistransformers>=4.50.3with no upper bound, so any pip re-resolve may pulltransformers==5.x. transformers 5.0 removedHybridCacheandFLAX_WEIGHTS_NAME;peft<0.18and most installeddiffusersreleases (≤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 withImportError: cannot import name 'HybridCache' from 'transformers'. Fix:pip install 'transformers>=4.50.3,<5'(and optionallypip install --upgrade peftto 0.19+ for forward compatibility). Re-pin after every core upgrade until either (a) ComfyUI core addstransformers<5upper-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.gitdirectory. Sogit pull/git logwon'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.txtAfter 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 doesimport "../../<RepoName>/js/foo.js"with the GitHub CamelCase name — fine for a freshgit 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 -bis system boot, not service restart — every ComfyUI run since the last reboot is in there. Filter to the current service run byMainPID:PID=$(systemctl show comfyui.service -p MainPID --value) journalctl _PID=$PID --no-pagerOr
--since "$(systemctl show comfyui.service -p ActiveEnterTimestamp --value | cut -d' ' -f2-)"if filtering by date. The-bform 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
- comfy-cli source: https://github.com/Comfy-Org/comfy-cli
- API workflow format: https://docs.comfy.org/development/comfyui-server/comms_overview
- ComfyUI-Manager registry: https://github.com/ltdrdata/ComfyUI-Manager
- Snapshot format: https://github.com/Comfy-Org/comfy-cli/blob/main/comfy_cli/command/custom_nodes/cm_cli_util.py