comfyui-node-advanced
ComfyUI advanced node patterns - MatchType, Autogrow, DynamicCombo, node expansion, MultiType, wildcard inputs. Use when building complex nodes with dynamic…
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.
$ npx -y skills add jtydhr88/comfyui-custom-node-skills --skill comfyui-node-lifecycle --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/comfyui-node-lifecycleContext preview
The summary Claude sees to decide when to auto-load this skill.
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.
name: comfyui-node-lifecycle description: 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.
Understanding the execution lifecycle helps build efficient, correct nodes.
1. Prompt received from frontend 2. Validation phase ├── Look up each node class ├── Call INPUT_TYPES() / define_schema() for input specs ├── Validate connections and types └── Call validate_inputs() for each node 3. Build execution order (topological sort from output nodes) 4. For each node in order: ├── Cache check (fingerprint_inputs) ├── Input resolution (get upstream values) ├── Lazy evaluation (check_lazy_status) ├── Execute function └── Store outputs in cache 5. Return results to frontend
ComfyUI executes from **output nodes backward**: 1. Identifies output nodes (`is_output_node=True`) 2. Builds dependency graph 3. Topological sort determines execution order 4. Only nodes connected to output nodes execute
Controls when a node re-executes vs uses cached results.
class RandomNode(io.ComfyNode):
@classmethod
def define_schema(cls):
return io.Schema(
node_id="RandomNode",
display_name="Random Value",
category="utils",
inputs=[
io.Float.Input("min_val", default=0.0),
io.Float.Input("max_val", default=1.0),
],
outputs=[io.Float.Output("FLOAT")],
)
@classmethod
def fingerprint_inputs(cls, min_val, max_val):
"""Return value compared to last run. Different value = re-execute."""
# Return unique value each time to always re-execute
import time
return time.time()
@classmethod
def execute(cls, min_val, max_val):
import random
return io.NodeOutput(random.uniform(min_val, max_val))**How caching works**:
**V1 equivalent** (`IS_CHANGED`):
@classmethod
def IS_CHANGED(s, min_val, max_val):
return time.time() # always re-executeFor nodes that should never be cached:
io.Schema(
node_id="AlwaysRunNode",
not_idempotent=True, # prevents cache sharing between instances of the same node
# ...
)> **Important:** `not_idempotent=True` does **not** prevent a node from reusing its own cached output on subsequent runs. It only prevents cache sharing between different instances of the same node type that have identical inputs. To force re-execution every run (e.g., for file-writing nodes), you must also implement `fingerprint_inputs` (V3) or `IS_CHANGED` (V1) returning a unique value each time.
For nodes with interactive UI that produce intermediate outputs (e.g., Image Crop, Painter). These behave like output nodes (UI results are cached and resent to the frontend on page refresh) but do NOT automatically get added to the execution list — they only execute if on the dependency path of a real output node.
io.Schema(
node_id="InteractiveCropNode",
has_intermediate_output=True,
# ...
)Share cached node outputs across ComfyUI instances (e.g. a shared network cache) by registering a `CacheProvider`:
from comfy_api.latest import Caching
class MyCacheProvider(Caching.CacheProvider):
async def on_lookup(self, context): # context: node_id, class_type, cache_key_hash
... # return Caching.CacheValue(outputs=[...], ui={...}) or None on miss
async def on_store(self, context, value):
... # store to external storage (dispatched as a background task)
def should_cache(self, context, value=None) -> bool:
return True # return False to skip external caching for a node
def on_prompt_start(self, prompt_id): ...
def on_prompt_end(self, prompt_id): ...
# Register in ComfyExtension.on_load():
api = ComfyAPI()
await api.caching.register_provider(MyCacheProvider())Providers are consulted on local cache miss, in registration order. Exceptions from providers never break execution.
Validates inputs before execution. Runs during the validation phase.
class ValidatedNode(io.ComfyNode):
@classmethod
def define_schema(cls):
return io.Schema(
node_id="ValidatedNode",
display_name="Validated Node",
category="utils",
inputs=[
io.Int.Input("width", default=512, min=1, max=8192),
io.Int.Input("height", default=512, min=1, max=8192),
],
outputs=[io.Image.Output("IMAGE")],
)
@classmethod
def validate_inputs(cls, width, height):
"""Return True if valid, or error string if invalid."""
if width % 8 != 0 or height % 8 != 0:
return "Width and height must be multiples of 8"
if width * height > 4096 * 4096:
return "Total pixels exceed maximum (4096x4096)"
return True
@classmethod
def execute(cls, width, height):
import torch
return io.NodeOutput(torch.zeros(1, height, width, 3))**V1 equivalent**:
@classmethod
def VALIDATE_INPUTS(s, width, height):
if width % 8 != 0:
return "Width must be a multiple of 8"
return TrueA 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
ComfyUI advanced node patterns - MatchType, Autogrow, DynamicCombo, node expansion, MultiType, wildcard inputs. Use when building complex nodes with dynamic…
ComfyUI custom node fundamentals - V3 node structure, Schema, inputs/outputs, registration. Use when creating new ComfyUI custom nodes, defining node classes,…
ComfyUI data types - IMAGE, LATENT, MASK, CONDITIONING, MODEL, CLIP, VAE, AUDIO, VIDEO, 3D types, widget types, and custom types. Use when working with ComfyUI…
ComfyUI frontend JavaScript extensions - hooks, widgets, sidebar tabs, commands, settings, toasts, dialogs. Use when adding UI features to custom nodes,…
ComfyUI node input types - INT, FLOAT, STRING, BOOLEAN, COMBO widgets, hidden inputs, optional inputs, lazy inputs, force_input. Use when configuring node…
ComfyUI V1 to V3 node migration - converting legacy nodes to the V3 API. Use when migrating existing custom nodes from V1 to V3, understanding differences…