comfyui-node-advanced
ComfyUI advanced node patterns - MatchType, Autogrow, DynamicCombo, node expansion, MultiType, wildcard inputs, loops. Use when…
ComfyUI node output types - NodeOutput, UI outputs, PreviewImage, PreviewMask, SavedImages, PreviewAudio, PreviewText, PreviewVideo, Saved3DModels. Use when returning results from nodes, displaying previews, or saving output files.
Claude Code
$ npx -y skills add jtydhr88/comfyui-custom-node-skills --skill comfyui-node-outputs --agent claude-code
Codex
$ npx skills add jtydhr88/comfyui-custom-node-skills --skill comfyui-node-outputs -a codex -y
Cursor
$ npx skills add jtydhr88/comfyui-custom-node-skills --skill comfyui-node-outputs -a cursor -y
Gemini CLI
$ npx skills add jtydhr88/comfyui-custom-node-skills --skill comfyui-node-outputs -a gemini-cli -y
GitHub Copilot
$ npx skills add jtydhr88/comfyui-custom-node-skills --skill comfyui-node-outputs -a github-copilot -y
OpenCode
$ npx skills add jtydhr88/comfyui-custom-node-skills --skill comfyui-node-outputs -a opencode -y
Windsurf
$ npx skills add jtydhr88/comfyui-custom-node-skills --skill comfyui-node-outputs -a windsurf -y
name: comfyui-node-outputs description: ComfyUI node output types - NodeOutput, UI outputs, PreviewImage, PreviewMask, SavedImages, PreviewAudio, PreviewText, PreviewVideo, Saved3DModels. Use when returning results from nodes, displaying previews, or saving output files.
Nodes return data through `io.NodeOutput`. V3 provides built-in UI helpers for previews and file saving.
class SimpleNode(io.ComfyNode):
@classmethod
def define_schema(cls):
return io.Schema(
node_id="SimpleNode",
display_name="Simple Node",
category="example",
inputs=[io.Float.Input("a"), io.Float.Input("b")],
outputs=[
io.Float.Output("SUM"),
io.Float.Output("PRODUCT"),
],
)
@classmethod
def execute(cls, a, b):
# Values must match output order
return io.NodeOutput(a + b, a * b)io.Schema(
outputs=[
io.Image.Output("IMAGE"), # basic output
io.Int.Output("COUNT"), # integer output
io.Float.Output("VALUE", display_name="Result"), # custom display name
io.String.Output("TEXT", tooltip="The processed text"),
io.Image.Output("FRAMES", is_output_list=True), # outputs a list
],
)# Data only return io.NodeOutput(image_tensor, mask_tensor) # UI only (output node with no data outputs) return io.NodeOutput(ui=ui.PreviewImage(images, cls=cls)) # Data + UI return io.NodeOutput(image_tensor, ui=ui.PreviewImage(images, cls=cls)) # No output return io.NodeOutput() # Block execution return io.NodeOutput(block_execution="Reason for blocking") # Node expansion (positional args are outputs, not result= keyword) return io.NodeOutput(output_ref, expand=graph.finalize())
Import `ui` from `comfy_api.latest`:
from comfy_api.latest import io, ui
Display image previews on the node. Saves to temp directory automatically.
# Constructor: PreviewImage(image, animated=False, cls=None)
class PreviewNode(io.ComfyNode):
@classmethod
def define_schema(cls):
return io.Schema(
node_id="PreviewNode",
display_name="Preview Image",
category="image",
is_output_node=True,
inputs=[io.Image.Input("images")],
outputs=[],
hidden=[io.Hidden.prompt, io.Hidden.extra_pnginfo],
)
@classmethod
def execute(cls, images):
return io.NodeOutput(ui=ui.PreviewImage(images, cls=cls))# Constructor: PreviewMask(mask, animated=False, cls=None) # Auto-converts mask to 3-channel grayscale for display return io.NodeOutput(ui=ui.PreviewMask(masks, cls=cls))
# Constructor: PreviewAudio(audio, cls=None) # Saves as FLAC to temp directory return io.NodeOutput(ui=ui.PreviewAudio(audio, cls=cls))
# Constructor: PreviewVideo(values: list[SavedResult | dict]) return io.NodeOutput(ui=ui.PreviewVideo(saved_video_results))
Display text output:
return io.NodeOutput(ui=ui.PreviewText(value))
Display 3D model preview:
return io.NodeOutput(ui=ui.PreviewUI3D(
model_file=saved_result, # SavedResult for the 3D file
camera_info=camera_dict, # camera position/target/zoom
bg_image=image_tensor, # optional background image (via **kwargs)
))All core 3D save/preview nodes now report models as standard `"3d"` output items (shown in queue/assets like images):
# Constructor: Saved3DModels(results: list[SavedResult], camera_info=None, model_3d_info=None)
# -> {"3d": results, "camera_info": [camera_info], "model_3d_info": [...]}
return io.NodeOutput(ui=ui.Saved3DModels(
[ui.SavedResult("model.glb", "", io.FolderType.output)], # or FolderType.temp for previews
camera_info=camera_dict, # extended CameraInfo (quaternion/fov/near/far/frustum)
model_3d_info=transforms, # list[Model3DTransform]: position/quaternion/scale per model
))`ui.PreviewUI3DAdvanced(model_file, camera_info, model_3d_info, folder_type=None)` still exists as a subclass, but `model_file` is now a relative path **string** (`"subfolder/model.glb"`, default folder `output`) and it emits the `"3d"` format above, not `{"result": [...]}`.
The `ui.ImageSaveHelper` class provides static methods for various image formats:
# Save as PNG (returns list[SavedResult])
results = ui.ImageSaveHelper.save_images(
images, # tensor [B,H,W,C]
filename_prefix="ComfyUI",
folder_type=io.FolderType.output, # output, temp, or input
cls=cls, # node class (for metadata)
compress_level=4,
)
# Save and get UI object directly (saves to output folder)
saved_ui = ui.ImageSaveHelper.get_save_images_ui(images, "ComfyUI", cls=cls)
return io.NodeOutput(ui=saved_ui)
# Save animated PNG
result = ui.ImageSaveHelper.save_animated_png(
images, "anim", io.FolderType.output, cls=cls, fps=12.0, compress_level=4
)
# Save animated PNG and get UI
saved_ui = ui.ImageSaveHelper.get_save_animated_png_ui(images, "anim", cls=cls, fps=12.0, compress_level=4)
# Save animated WebP
result = ui.ImageSaveHelper.save_animated_webp(
images, "anim", io.FolderType.output, cls=cls,
fps=12.0, lossless=False, quality=80, method=4
)
# Save animated WebP and get UI
saved_ui = ui.ImageSaveHelper.get_save_animated_webp_ui(
images, "anim", cls=cls, fps=12.0, lossless=False, quality=80, method=4
)**Simple save node example:**
class SaveImageNode(io.ComfyNode):
@classmethod
def define_schemaA 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.
ComfyUI advanced node patterns - MatchType, Autogrow, DynamicCombo, node expansion, MultiType, wildcard inputs, loops. Use when…
ComfyUI custom node fundamentals - V3 node structure, Schema, inputs/outputs, registration. Use when creating new ComfyUI custom…
ComfyUI data types - IMAGE, LATENT, MASK, CONDITIONING, MODEL, CLIP, VAE, AUDIO, VIDEO, 3D types, widget types, and custom types.…
ComfyUI frontend JavaScript extensions - hooks, widgets, sidebar tabs, commands, settings, toasts, dialogs. Use when adding UI…
ComfyUI node input types - INT, FLOAT, STRING, BOOLEAN, COMBO widgets, hidden inputs, optional inputs, lazy inputs, force_input.…
ComfyUI node execution lifecycle - caching, fingerprint_inputs/IS_CHANGED, validate_inputs/VALIDATE_INPUTS, check_lazy_status,…
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
Ask which skill or flow fits your situation. A router over the skills in this repo.