mcpField
C
comfyui-node-packaging

comfyui-node-packaging

github.com/jtydhr88開発308136 回インストール2 週間前に更新
リポジトリ

comfyui-node-packaging について

ComfyUIのカスタムノード開発者向けに、パッケージ構成、登録、公開方法をまとめたガイドです。依存関係、フロントエンド拡張、ローカライズ、レジストリ公開、comfy-cliによるひな形作成、デプロイ時の制約を扱います。

主な機能

  1. 01V1とV3のノード登録
  2. 02プロジェクト構成と依存関係
  3. 03フロントエンド拡張とヘルプページ
  4. 04ローカライズファイルの構成
  5. 05ComfyUI Registryへの公開
  6. 06comfy-cliによるプロジェクト作成

活用シーン

  1. 01カスタムノードの標準的な構成を用意
  2. 02フロントエンド拡張と翻訳の追加
  3. 03ノードパッケージの準備と公開
  4. 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 への移行

コメント