Comfy CLIは、ターミナルやシェルスクリプトからComfyUIのインストール・起動・workflow実行を行う公式のコマンドラインツールで、comfy run --workflow <file.json> --waitが自動化の基本形です。HTTP APIを自分で書くほどではないが、GUIを開かずにBatch処理やCIで画像を作りたい場面に向きます。位置づけ、導入、1回実行、Batch、Shell/CIからの呼び出し、仕様変更への備えを順に解説します。
情報確認日:2026年8月22日(日本時間)
確認時点のCLI状態:2026年8月22日に公式ドキュメント(docs.comfy.org)とGitHubのREADME・ソースで確認。Python 3.10以上が前提。comfy runは既定で非同期投入となり、完了まで待つには--waitが必要です(「旧既定」と注記あり)。コマンド名や引数は変わる可能性があるため、実行前にcomfy --helpとcomfy run --helpで現在の表示を確認してください。
結論:対話せずに「固定workflowを何度も回す」ならCLI、アプリ統合ならAPI
責任範囲
- CLI・HTTP API・MCPの三つを「誰が呼ぶか」で分け、CLIの守備範囲を決める
pip install comfy-cliから接続確認までの導入手順を示す- 最小workflowを
comfy runで1回実行し、成功条件を決める - prompt違いを逐次実行するBatchスクリプトと、Exit Codeの記録表を載せる
- Shell/CIからの呼び出しでSecret・Exit Code・Logをどう扱うかを整理する
- HTTP APIのルート詳細、MCPの登録手順は扱わない
CLIとAPI・MCPをどう分けるか
ComfyUIを画面以外から動かす手段は三つあり、違いは「呼び出す主体」です。同じworkflowを実行する点は共通で、どれを選んでもComfyUI本体は/promptで受け取ります。
| 手段 | 呼び出す主体 | 向いている場面 | 詳しい記事 |
|---|---|---|---|
| Comfy CLI | 人のターミナル、シェルスクリプト、CI | 固定workflowの反復実行、環境構築の自動化 | この記事 |
| HTTP API | 自分で書いたアプリのコード | Webアプリ統合、Queue制御、進捗表示 | ComfyUI APIの使い方 |
| Comfy MCP | Claude CodeやCodexなどのAIエージェント | 対話の中でエージェントに生成させる | Comfy MCPでローカルComfyUIをエージェントから使う |
CLIの強みは「コードを書かずに、既存のシェルの道具(ループ・リダイレクト・終了コード)で組める」ことです。逆に、アプリのUIに進捗を出す、利用者ごとに上限を設けるといった要件が出たらHTTP APIに移ります。
CLIをどう導入し接続するか
公式の導入はpipです。すでにComfyUIが動いている環境なら、CLIはそのインスタンスに接続するだけで使えます。
# 導入(Python 3.10+)
pip install comfy-cli
pip show comfy-cli # Version: 行でバージョンを記録する
# ComfyUIをまだ入れていない場合
comfy install # 対話で配置先を決める
comfy launch --background # バックグラウンド起動
comfy env # 使用中のworkspaceとpathを表示
comfy which # 対象workspaceのpath
comfy stop # バックグラウンド起動を止める
すでに別の方法でComfyUIを起動している場合は、comfy runに--hostと--portで接続先を指定します。既定は127.0.0.1:8188相当ですが、環境依存のため明示する方が安全です。バージョン確認の専用フラグが現行で用意されているかは確認できなかったため、pip showのVersion:行を記録に使います。
Workflowを1回実行するにはどうするか
実行対象は、GUIで動作を確認したworkflowをJSONに書き出したものです。現行のCLIは「API形式と、GUIから書き出したUI形式の両方を受け付け、UI形式はクライアント側でAPI形式に変換する」と説明しています。変換の結果を確認したいときは--print-promptで送信前のAPI形式を表示できます。
comfy validate --workflow workflow.json # 送信前の検査
comfy run --workflow workflow.json --wait --verbose \
--host 127.0.0.1 --port 8188 --timeout 120
echo "exit=$?"
成功条件は「終了コードが0」「出力ディレクトリに新しい画像がある」の二つで判定します。--timeoutは「サーバーが沈黙している時間」の上限で、workflow全体の所要時間ではありません。重いworkflowでは、進捗イベントが途切れなければタイムアウトしません。
出力は通常ComfyUIのoutputフォルダに保存されます。CLIにはcomfy download <prompt_id>で出力を取得するコマンドもありますが、ローカルで完結する場合はoutputフォルダを直接参照する方が単純です。
Batch処理はどう組むか
CLIにはBatch専用の機能はありません。その代わり、workflow JSONを複製して値を差し替え、シェルのループで逐次実行すれば足ります。並列にしないのは、ComfyUIのQueueが1件ずつ処理するためで、同時に投げても速くなりません。
#!/usr/bin/env bash
# prompts.txt の各行を positive prompt として逐次実行し、終了コードを記録する
set -u
BASE=workflow_api.json # API形式。ノード "6" の inputs.text を差し替える前提
LOG=batch_$(date +%Y%m%d_%H%M%S).tsv
printf "no\tprompt\texit\tstarted\tfinished\n" > "$LOG"
i=0
while IFS= read -r prompt; do
i=$((i+1))
jq --arg p "$prompt" '.["6"].inputs.text = $p' "$BASE" > "run_$i.json"
started=$(date +%T)
comfy run --workflow "run_$i.json" --wait --host 127.0.0.1 --port 8188 --timeout 180 \
> "run_$i.log" 2>&1
code=$?
printf "%s\t%s\t%s\t%s\t%s\n" "$i" "$prompt" "$code" "$started" "$(date +%T)" >> "$LOG"
done < prompts.txt
jqでJSONを書き換えているのは、文字列置換でJSONを壊さないためです。ノードID"6"は自分のworkflowに合わせてください。Presetを変えたい場合は、preset名ごとにAPI形式のJSONを別ファイルで用意し、ループの中でファイル名を切り替える方が、複数ノードを書き換えるより壊れにくいです。
3つのPromptを逐次実行してExit Codeを保存する
このスクリプトをそのまま、3行のprompts.txtで動かすのが最初の検証です。1行目は普通の描写、2行目は意図的に長すぎる文、3行目は存在しないノードIDを指すようBASEを壊した別JSONにすると、成功・失敗の両方の終了コードが採れます。終了コードの一覧は公式ドキュメントに見当たらなかったため、自分の環境での値を記録して運用の基準にします。
| No. | 条件 | 期待 | exit | 所要時間 | 出力ファイル | ログの末尾 |
|---|---|---|---|---|---|---|
| 1 | 正常なprompt | 0・画像あり | ||||
| 2 | 極端に長いprompt | 0または非0(環境で記録) | ||||
| 3 | 存在しないノードIDを参照 | 非0・画像なし |
見るべきは、失敗時に終了コードが非0になるか、ログのどの行に原因が出るかの二点です。ここが分かれば、CIでの失敗検知が「画像の有無」ではなく「終了コード」で組めます。
Shell/CIからどう呼ぶか
CIで回す場合、ComfyUIはGPU付きのセルフホストランナーか、常時起動しているサーバーに--hostで接続する形になります。気をつける点は三つです。
Secret
- Partner Node(有料の外部API連携ノード)を含むworkflowは
--api-keyが要る。値はCIのSecretに置き、コマンド履歴に残さない - 有料ノードの実行には
--allow-spendの明示が必要。CIで無自覚に課金されない設計になっている
Exit Code
set -eではなく、1件ごとに$?を記録して続行する- 全件終了後に非0の件数で最終的な成否を決める
Log
- 機械処理するなら
--jsonでNDJSON(1行1イベント)を標準出力に出す - 人が読むなら
--verbose。両方をファイルに残す
# GitHub Actions のジョブ例(セルフホストランナーでComfyUIが起動済みの前提)
jobs:
render:
runs-on: [self-hosted, gpu]
steps:
- uses: actions/checkout@v4
- run: pip install comfy-cli
- run: comfy tracking disable
- run: bash scripts/batch.sh
env:
COMFY_HOST: 127.0.0.1
COMFY_PORT: "8188"
- uses: actions/upload-artifact@v4
if: always()
with:
name: batch-logs
path: |
batch_*.tsv
run_*.log
comfy tracking disableはCLIの利用状況送信を止めるコマンドで、CI環境では最初に実行しておきます。アーティファクトにはログと記録表だけを上げ、生成画像の扱い(保存先・公開範囲)は別途決めてください。Custom Nodeを含むリポジトリのCI設計や、workflow JSONのGit管理は別記事で扱います。
仕様変更にどう備えるか
Comfy CLIは活発に更新されており、この記事の確認時点でも「--waitが旧既定」という注記が示すとおり、既定の挙動が変わった経緯があります。スクリプトが突然動かなくなったときに原因を切り分けられるよう、次を記録します。
pip show comfy-cliのVersionと、comfy envの出力をリポジトリに残す- スクリプト冒頭のコメントに「確認日」と「依存する引数名」を書く
comfy run --helpの出力をファイルに保存し、更新時にdiffを取る- CLIの更新は
pip install -U comfy-cliを明示したときだけ行い、CIでは版を固定する - 挙動が変わったらまず
--print-promptで送信内容が変わっていないか見る
記事冒頭の「確認時点のCLI状態」は、この記録の雛形です。自分のスクリプトにも同じ欄を置いてください。
よくある質問
GUIで保存したworkflow.jsonをそのままcomfy runに渡せますか?
現行のCLIはUI形式も受け付け、送信前にAPI形式へ変換すると説明しています。ただし変換結果が意図どおりかは--print-promptで確認してください。確実にしたいならGUIのExport (API)で書き出したJSONを使います。
並列で複数のcomfy runを起動すれば速くなりますか?
なりません。ComfyUIは1件ずつ処理するため、同時投入はQueueに並ぶだけです。逐次ループで十分で、むしろログと終了コードの対応が取りやすくなります。
Comfy Cloudにも同じコマンドで投げられますか?
--where cloudでCloudに向ける仕組みがあり、comfy cloud loginで認証します。ただしCloud側は課金と認証が絡むため、この記事のローカル前提のスクリプトをそのまま流用せず、公式ドキュメントでCloud向けの手順を確認してください。
まとめ
Comfy CLIは、固定workflowを対話なしで何度も回す用途に向く公式ツールで、基本形はcomfy run --workflow file.json --waitです。Batchはシェルのループとjqで組み、1件ごとに終了コードを記録します。
CIではSecretを履歴に残さず、--jsonか--verboseのログを必ず保存し、CLIの版を固定します。まず3件のpromptで終了コードの記録表を埋め、自分の環境での成功・失敗の形を確かめてから自動化に進んでください。