/comfyui-node-packaging
ComfyUI custom node project structure - directory layout, __init__.py, registration, requirements.txt, publishing, WEB_DIRECTORY. Use when setting up a new custom node project, packaging nodes, or publishing to the registry.
$ npx -y skills add jtydhr88/comfyui-custom-node-skills --skill comfyui-node-packaging --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/comfyui-node-packaging
Context preview
The summary Claude sees to decide when to auto-load this skill.
ComfyUI custom node project structure - directory layout, __init__.py, registration, requirements.txt, publishing, WEB_DIRECTORY. Use when setting up a new custom node project, packaging nodes, or publishing to the registry.
SKILL.md
comfyui-node-packaging.SKILL.mdname: comfyui-node-packaging
description: ComfyUI custom node project structure - directory layout, __init__.py, registration, requirements.txt, publishing, WEB_DIRECTORY. Use when setting up a new custom node project, packaging nodes, or publishing to the registry.
ComfyUI Custom Node Packaging
How to structure, register, and publish a custom node package.
Project Structure
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.jsonEntry Point: __init__.py
V3 Registration (Recommended)
# __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 Registration (Legacy)
# __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"]Node Definitions File
# 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)Dependencies: requirements.txt
# requirements.txt
opencv-python>=4.8.0
requests>=2.28.0
**Important**: Only list dependencies not already included with ComfyUI. ComfyUI ships with: `torch`, `torchvision`, `torchaudio`, `numpy`, `PIL/Pillow`, `scipy`, `safetensors`, `transformers`, `accelerate`.
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"
Frontend Extensions (JavaScript)
Place `.js` files in the `WEB_DIRECTORY`:
my_custom_nodes/
js/
my_widgets.js # Custom widget implementations
my_extension.js # Extension hooks# __init__.py
WEB_DIRECTORY = "./js"
All `.js` files in this directory are loaded by the frontend automatically. CSS and other resources can be accessed at `extensions/my_custom_nodes/filename.css`.
Help Pages
Create markdown documentation per node:
my_custom_nodes/
docs/
MyNode1.md # filename matches node_id<!-- docs/MyNode1.md -->
# 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
Internationalization (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": "处理强度" }
}
}
}Single-File Node
For very simple nodes, everything can be in one file:
# 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()Key Imports
# 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, InputImpl.VideoFromComponents
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
Read more
name: comfyui-node-packaging description: ComfyUI custom node project structure - directory layout, __init__.py, registration, requirements.txt, publishing, WEB_DIRECTORY. Use when setting up a new custom node project, packaging nodes, or publishing to the registry.
ComfyUI Custom Node Packaging
How to structure, register, and publish a custom node package.
Project Structure
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.jsonEntry Point: __init__.py
V3 Registration (Recommended)
# __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 Registration (Legacy)
# __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"]Node Definitions File
# 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)Dependencies: requirements.txt
# requirements.txt opencv-python>=4.8.0 requests>=2.28.0
**Important**: Only list dependencies not already included with ComfyUI. ComfyUI ships with: `torch`, `torchvision`, `torchaudio`, `numpy`, `PIL/Pillow`, `scipy`, `safetensors`, `transformers`, `accelerate`.
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"
Frontend Extensions (JavaScript)
Place `.js` files in the `WEB_DIRECTORY`:
my_custom_nodes/
js/
my_widgets.js # Custom widget implementations
my_extension.js # Extension hooks# __init__.py WEB_DIRECTORY = "./js"
All `.js` files in this directory are loaded by the frontend automatically. CSS and other resources can be accessed at `extensions/my_custom_nodes/filename.css`.
Help Pages
Create markdown documentation per node:
my_custom_nodes/
docs/
MyNode1.md # filename matches node_id<!-- docs/MyNode1.md --> # 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
Internationalization (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": "处理强度" }
}
}
}Single-File Node
For very simple nodes, everything can be in one file:
# 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()Key Imports
# 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, InputImpl.VideoFromComponents 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
A curated collection of agent skills (for Claude Code and OpenAI Codex) for developing ComfyUI custom nodes. These skills give the agent comprehensive knowledge of the ComfyUI node system, covering both the V3 (recommended) and V1 (legacy) APIs.
Repo: jtydhr88/comfyui-custom-node-skills
Other skills on comfyui-custom-node-skills.
- /comfyui-node-advanced
ComfyUI advanced node patterns - MatchType, Autogrow, DynamicCombo, node expansion, MultiType, wildcard inputs. Use when building complex nodes with dynamic inputs, type matching, or node expansion.
Open skill - /comfyui-node-basics
ComfyUI custom node fundamentals - V3 node structure, Schema, inputs/outputs, registration. Use when creating new ComfyUI custom nodes, defining node classes, or setting up a custom node project.
Open skill - /comfyui-node-datatypes
ComfyUI data types - IMAGE, LATENT, MASK, CONDITIONING, MODEL, CLIP, VAE, AUDIO, VIDEO, 3D types, widget types, and custom types. Use when working with ComfyUI tensors, model types, or defining input/output data types.
Open skill - /comfyui-node-frontend
ComfyUI frontend JavaScript extensions - hooks, widgets, sidebar tabs, commands, settings, toasts, dialogs. Use when adding UI features to custom nodes, creating custom widgets, or extending the ComfyUI frontend.
Open skill - /comfyui-node-inputs
ComfyUI node input types - INT, FLOAT, STRING, BOOLEAN, COMBO widgets, hidden inputs, optional inputs, lazy inputs, force_input. Use when configuring node inputs, adding widgets, or customizing input behavior.
Open skill - /comfyui-node-lifecycle
ComfyUI node execution lifecycle - caching, fingerprint_inputs/IS_CHANGED, validate_inputs/VALIDATE_INPUTS, check_lazy_status, execution order. Use when debugging execution, implementing caching control, input validation, or understanding execution flow.
Open skill

