| created | "2026-07-07T00:00:00.000Z" |
| modified | "2026-07-07T00:00:00.000Z" |
| reviewed | "2026-07-07T00:00:00.000Z" |
| name | comfy-cli |
| description | 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`. |
| allowed-tools | Bash, Read, Grep, Glob |
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
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):
mkdir -p snapshots
comfy node save-snapshot --output snapshots/$(date -I)-pre-update.json
git -C <comfyui-root> pull --ff-only
.venv/bin/python -m pip install -r requirements.txt
comfy node update all
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
.venv/bin/python -m pip install 'transformers>=4.50.3,<5'
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
comfy node bisect bad
comfy node bisect good
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>
comfy node fix all
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
falls back to the older Active version. The public
API exposes no reason — it's only on . 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: .
References