comfyui-node-packaging について
ComfyUIのカスタムノード開発者向けに、パッケージ構成、登録、公開方法をまとめたガイドです。依存関係、フロントエンド拡張、ローカライズ、レジストリ公開、comfy-cliによるひな形作成、デプロイ時の制約を扱います。
主な機能
- 01V1とV3のノード登録
- 02プロジェクト構成と依存関係
- 03フロントエンド拡張とヘルプページ
- 04ローカライズファイルの構成
- 05ComfyUI Registryへの公開
- 06comfy-cliによるプロジェクト作成
活用シーン
- 01カスタムノードの標準的な構成を用意
- 02フロントエンド拡張と翻訳の追加
- 03ノードパッケージの準備と公開
- 04依存関係とデプロイ制約の確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ jtydhr88/ comfyui-custom-node-skills --skill comfyui-node-packagingインストール後、Claude Code で/comfyui-node-packagingを入力して読み込まれたか確認します。
詳細
ComfyUI カスタムノードのパッケージ化
カスタムノードパッケージの構成、登録、公開方法です。
プロジェクト構成
ComfyUI/custom_nodes/
my_custom_nodes/
__init__.py # Entry point (required)
nodes.py # Node class definitions
requirements.txt # Python dependencies
pyproject.toml # Package metadata
README.md # Documentation
js/ # Frontend extensions (optional)
│ └── my_extension.js
docs/ # Help pages (optional)
│ └── MyNode.md
locales/ # i18n translations (optional)
└── zh/
└── main.json
エントリーポイント:init.py
V3 登録(推奨)
# __init__.py
from typing_extensions import override
from comfy_api.latest import ComfyExtension, io
from .nodes import MyNode1, MyNode2, MyNode3
WEB_DIRECTORY = "./js" # optional: frontend JS extensions
class MyNodesExtension(ComfyExtension):
@override
async def get_node_list(self) -> list[type[io.ComfyNode]]:
return [MyNode1, MyNode2, MyNode3]
@override
async def on_load(self):
# Optional: run initialization logic when extension loads
pass
async def comfy_entrypoint() -> MyNodesExtension:
return MyNodesExtension()
V1 登録(レガシー)
# __init__.py
from .nodes import MyNode1, MyNode2
NODE_CLASS_MAPPINGS = {
"MyNode1": MyNode1,
"MyNode2": MyNode2,
}
NODE_DISPLAY_NAME_MAPPINGS = {
"MyNode1": "My Node 1",
"MyNode2": "My Node 2",
}
WEB_DIRECTORY = "./js"
__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS", "WEB_DIRECTORY"]
ノード定義ファイル
# nodes.py
import torch
from comfy_api.latest import io
class MyNode1(io.ComfyNode):
@classmethod
def define_schema(cls):
return io.Schema(
node_id="MyNode1_UniqueID", # globally unique
display_name="My Node 1",
category="my_nodes",
description="Does something useful",
inputs=[
io.Image.Input("image"),
io.Float.Input("value", default=1.0, min=0.0, max=10.0),
],
outputs=[io.Image.Output("IMAGE")],
)
@classmethod
def execute(cls, image, value):
return io.NodeOutput(image * value)
依存関係:requirements.txt
# requirements.txt
opencv-python>=4.8.0
requests>=2.28.0
重要:ComfyUI にすでに含まれている依存関係は記載しないでください。ComfyUI の requirements.txt には、torch、torchvision、torchsde、numpy、einops、transformers、tokenizers、sentencepiece、safetensors、aiohttp、pyyaml、Pillow、scipy、tqdm、psutil、av(>=17)、requests、blake3 のほか、必須ではない kornia、spandrel、pydantic が含まれています。
torchaudioは ComfyUI の依存関係ではなくなりました(v0.38+)。インポートする場合は自分で記載するか、コアのcomfy.audio(resample、MelSpectrogram、bass_biquad、equalizer_biquad、treble_biquad)を使用してください。accelerateも含まれていません。- 公式にサポートされている PyTorch の最小バージョンは 2.7 です。Python 3.10 も引き続き動作しますが、EOL 警告がログに出力されます。
pyproject.toml
[project]
name = "comfyui-my-nodes"
version = "1.0.0"
description = "My custom nodes for ComfyUI"
license = "MIT"
requires-python = ">=3.10"
[project.urls]
Repository = "https://github.com/username/comfyui-my-nodes"
フロントエンド拡張機能(JavaScript)
.js ファイルを WEB_DIRECTORY に配置します。
my_custom_nodes/
js/
my_widgets.js # Custom widget implementations
my_extension.js # Extension hooks
# __init__.py
WEB_DIRECTORY = "./js"
このディレクトリ内のすべての .js ファイルは、フロントエンドによって自動的に読み込まれます。CSS などのリソースには extensions/my_custom_nodes/filename.css でアクセスできます。
ヘルプページ
ノードごとに Markdown ドキュメントを作成します。
my_custom_nodes/
docs/
MyNode1.md # filename matches node_id
# My Node 1
Processes images with adjustable value.
## Inputs
- **image**: The input image
- **value**: Processing strength (0.0 - 10.0)
## Outputs
- **IMAGE**: The processed image
国際化(i18n)
my_custom_nodes/
locales/
zh/
main.json
nodeDefs.json # node definition translations
// locales/zh/nodeDefs.json
{
"MyNode1_UniqueID": {
"display_name": "我的节点1",
"description": "处理图像",
"inputs": {
"image": { "display_name": "图像" },
"value": { "display_name": "数值", "tooltip": "处理强度" }
}
}
}
単一ファイルのノード
非常にシンプルなノードであれば、すべてを 1 つのファイルにまとめられます。
# ComfyUI/custom_nodes/my_simple_node.py
import torch
from comfy_api.latest import ComfyExtension, io
from typing_extensions import override
class InvertImage(io.ComfyNode):
@classmethod
def define_schema(cls):
return io.Schema(
node_id="SimpleInvert",
display_name="Simple Invert",
category="image",
inputs=[io.Image.Input("image")],
outputs=[io.Image.Output("IMAGE")],
)
@classmethod
def execute(cls, image):
return io.NodeOutput(1.0 - image)
class SimpleExtension(ComfyExtension):
@override
async def get_node_list(self):
return [InvertImage]
async def comfy_entrypoint():
return SimpleExtension()
主なインポート
# V3 API core
from comfy_api.latest import ComfyExtension, io, ui
from comfy_api.latest import ComfyAPI # async runtime API (use with await)
from comfy_api.latest import ComfyAPISync # sync runtime API (use in sync execute)
from comfy_api.latest import Input # Input.Image, Input.Audio, Input.Mask, Input.Latent, Input.Video
from comfy_api.latest import InputImpl # InputImpl.VideoFromFile, .VideoFromComponents, .VideoFromList
from comfy_api.latest import Types # Types.MESH, Types.VOXEL, Types.File3D, Types.VideoCodec
from typing_extensions import override
# Common utilities
import folder_paths # directory management
from server import PromptServer # server-to-client messaging
from comfy_execution.graph_utils import GraphBuilder # node expansion
folder_paths の使用
ComfyUI では、標準ディレクトリにアクセスするために folder_paths が用意されています。
import folder_paths
# Standard directories
input_dir = folder_paths.get_input_directory()
output_dir = folder_paths.get_output_directory()
temp_dir = folder_paths.get_temp_directory()
# Model directories
checkpoint_paths = folder_paths.get_folder_paths("checkpoints")
lora_paths = folder_paths.get_folder_paths("loras")
# Register custom model folder
folder_paths.add_model_folder_path("my_models", "/path/to/models")
# Get model file list
models = folder_paths.get_filename_list("checkpoints")
path = folder_paths.get_full_path_or_raise("checkpoints", name) # resolve a combo value safely
# Path containment check before reading/writing user-supplied paths
folder_paths.is_within_directory(base_dir, candidate_path)
# Dataset files live in the "datasets" folder type (v0.30+)
dataset_dirs = folder_paths.get_folder_paths("datasets")
ComfyUI Registry への公開
1. pyproject.toml を作成する
[project]
name = "comfyui-my-nodes"
version = "1.0.0"
description = "My custom nodes"
license = "MIT"
[tool.comfy]
PublisherId = "your-publisher-id"
2. 公開する
comfy node publish
GitHub Actions による CI/CD
# .github/workflows/publish.yml
name: Publish to ComfyUI Registry
on:
push:
tags:
- 'v*'
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- run: pip install comfy-cli
- run: comfy node publish
env:
COMFY_API_KEY: ${{ secrets.COMFY_API_KEY }}
comfy-cli によるスキャフォールディング
# Install comfy-cli
pip install comfy-cli
# Create new custom node project
cd ComfyUI/custom_nodes
comfy node scaffold
これにより、必要なファイルがすべて含まれたボイラープレート構成が生成されます。
ノード ID のベストプラクティス
- グローバルで一意なプレフィックスを使用します:"MyProject_NodeName" または "username.NodeName"
- コアノードと衝突する
node_idは完全に無視されます(クラス名と表示名、v0.35+)。 - リリース後に
node_idを変更しないでください(保存済みワークフローが壊れます)。 - ユーザー向けの名前を変更する場合は
display_nameを使用します。 - 見つけやすくするには
search_aliasesを使用します:search_aliases=["alias1", "alias2"]
よく使われるパターン
複数のノードファイルの整理
# __init__.py
from typing_extensions import override
from comfy_api.latest import ComfyExtension, io
from .image_nodes import BlurNode, SharpenNode, ResizeNode
from .text_nodes import ConcatNode, FormatNode
from .util_nodes import SwitchNode, DebugNode
class MyExtension(ComfyExtension):
@override
async def get_node_list(self):
return [
BlurNode, SharpenNode, ResizeNode,
ConcatNode, FormatNode,
SwitchNode, DebugNode,
]
async def comfy_entrypoint():
return MyExtension()
条件付きノード読み込み
class MyExtension(ComfyExtension):
@override
async def get_node_list(self):
nodes = [BasicNode]
try:
import cv2
from .opencv_nodes import OpenCVNode
nodes.append(OpenCVNode)
except ImportError:
pass
return nodes
デプロイ時の制約
- 無効化されたノード:ユーザーは
--disabled-nodes-config file.yaml(disabled_nodes: [ids])や、--disable-partner-nodes/--offline(旧--disable-api-nodesは--offlineの非推奨エイリアス)を使ってノード ID を除外できます。たとえばGraphBuilderの展開時に、別のパック(またはパートナー)のノードが存在することを前提にしないでください。 - ガバナンス対象ビルド(v0.40+、組織ポリシー対象ビルドのみ)では、
.py/.pyw/.pyd/.so/.dll/.dylib/.js/.mjsファイルの BLAKE3 ダイジェストによってパックが固定され、__pycache__/.pycファイルやシンボリックリンクを含むパックは拒否されます。ソースコードのみを同梱し、実行時に自分のコードファイルを書き換えたり、自動更新したりしないでください。
関連項目
comfyui-node-basics- ノードクラスの構成comfyui-node-frontend- JavaScript 拡張機能の詳細comfyui-node-migration- V1 から V3 への移行