AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Comfyui Node Registry

skill-artokun-comfyui-mcp-comfyui-node-registry · by artokun

Authoring & publishing ComfyUI custom nodes to the Comfy Registry — node structure, pyproject.toml spec, comfy-cli publishing, and CI

— No reviews yet
0 installs
44 views
0.0% view→install

Install

$ agentstack add skill-artokun-comfyui-mcp-comfyui-node-registry

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • ✓ Prompt-injection patterns
  • ✓ Secret / credential exfiltration
  • ✓ Dangerous shell & filesystem operations
  • ✓ Untrusted network calls
  • ✓ Known-malicious package signatures

What it can access

  • ✓ Network access No
  • ✓ Filesystem access No
  • ✓ Shell / process execution No
  • ✓ Environment & secrets No
  • ✓ Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-artokun-comfyui-mcp-comfyui-node-registry)

Reliability & compatibility

✓ Security review passed
0 installs to date
— no reviews yet
● 3mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Comfyui Node Registry? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Authoring & Publishing ComfyUI Custom Nodes

This skill covers writing a ComfyUI custom node pack and publishing it to the Comfy Registry (registry.comfy.org), the public catalog that powers ComfyUI-Manager. For using existing nodes in workflows, see the comfyui-core skill instead.

Minimal Node Pack Structure

A node pack is a Python package placed under ComfyUI/custom_nodes//. The package __init__.py must export NODE_CLASS_MAPPINGS and NODE_DISPLAY_NAME_MAPPINGS; WEB_DIRECTORY is optional (only if the pack ships frontend JS).

ComfyUI/custom_nodes/my-node-pack/
├── __init__.py          # exports the mappings ComfyUI scans for
├── nodes.py             # node class definitions
├── pyproject.toml       # registry metadata (required to publish)
├── requirements.txt     # optional Python deps
├── .comfyignore         # optional — exclude files from the published archive
├── LICENSE
├── README.md
└── web/js/              # optional frontend extension (see WEB_DIRECTORY)

__init__.py

from .nodes import NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS

# Optional: serve frontend JS/CSS from this folder (path relative to __init__.py)
WEB_DIRECTORY = "./web/js"

__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS", "WEB_DIRECTORY"]

A minimal node class (nodes.py)

class ImageSelector:
    CATEGORY = "example"          # menu path where the node appears

    @classmethod
    def INPUT_TYPES(cls):
        return {
            "required": {
                "images": ("IMAGE",),
                "mode": (["brightest", "reddest", "greenest", "bluest"],),
            },
            "optional": {
                "threshold": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.01}),
                "count": ("INT", {"default": 1, "min": 1, "max": 64}),
                "label": ("STRING", {"default": "", "multiline": False}),
            },
        }

    RETURN_TYPES = ("IMAGE",)        # tuple of output data types
    RETURN_NAMES = ("image",)        # optional friendly output names
    FUNCTION = "choose_image"        # name of the method ComfyUI calls
    OUTPUT_NODE = False              # True for terminal nodes (e.g. SaveImage)

    def choose_image(self, images, mode, threshold=0.5, count=1, label=""):
        import torch
        brightness = [torch.mean(img.flatten()).item() for img in images]
        best = brightness.index(max(brightness))
        return (images[best].unsqueeze(0),)   # MUST return a tuple

NODE_CLASS_MAPPINGS = {
    "ImageSelector": ImageSelector,        # globally unique class_type key
}

NODE_DISPLAY_NAME_MAPPINGS = {
    "ImageSelector": "Image Selector",     # label shown in the UI
}

Node class contract

| Member | Required | Purpose | |--------|----------|---------| | INPUT_TYPES | yes | @classmethod returning {"required": {...}, "optional": {...}}. Each input is (TYPE,) or (TYPE, {opts}). | | RETURN_TYPES | yes | Tuple of output type strings (e.g. ("IMAGE", "MASK")). Single output still needs a trailing comma. | | FUNCTION | yes | String name of the method to execute. | | CATEGORY | yes | Menu path string for the Add Node menu. | | RETURN_NAMES | no | Friendly names for outputs (defaults to lowercased types). | | OUTPUT_NODE | no | True marks a terminal node that produces a result (save/preview). |

Input type widgets — the options dict drives the UI widget:

  • ("INT", {"default": 0, "min": 0, "max": 100, "step": 1})
  • ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.1})
  • ("STRING", {"default": "", "multiline": True})
  • (["a", "b", "c"],) — a literal list becomes a dropdown
  • ("IMAGE",), ("LATENT",), ("MODEL",) etc. — typed connections (no widget)

The executing method must return a tuple matching RETURN_TYPES, even for a single output (return (result,)).

pyproject.toml — Registry Metadata

Required to publish. comfy node init scaffolds this file. See references/pyproject.toml for a fully-commented example.

[project]
name = "my-node-pack"                          # unique & IMMUTABLE; lowercase, =3.10"
dependencies = [
    "comfyui-frontend-package=1.0.0"                   # optional ComfyUI version constraint

Field rules (verified against the live spec)

| Field | Section | Notes | |-------|---------|-------| | name | [project] | Unique and immutable once published. =3.10" (recommended). | | dependencies | [project] | PEP 508 requirement strings; can pin comfyui-frontend-package. | | Repository | [project.urls] | **Required** — valid GitHub repo URL. | | PublisherId | [tool.comfy] | **Required** — your publisher id (after the @ on your profile). | | DisplayName | [tool.comfy] | Friendly registry name (optional). | | Icon | [tool.comfy] | URL to a **square** image, **max 400×400px**; SVG/PNG/JPG/GIF. | | Banner | [tool.comfy] | URL to a **21:9** banner image; SVG/PNG/JPG/GIF (optional). | | requires-comfyui | [tool.comfy] | ComfyUI version range using = ~= != (optional). | | includes | [tool.comfy]` | Array forcing extra folders into the published archive. |

Controlling the published archive

  • .comfyignore — uses .gitignore syntax; files listed are excluded from the published archive. Use it to drop tests, examples, large assets, and dev files.
  • [tool.comfy].includes — the inverse: force-includes folders that would otherwise be skipped (e.g. a bundled web/dist).

Registry Setup (one-time)

  1. Go to registry.comfy.org and create a publisher.
  2. Your Publisher ID is the value after the @ on your profile page. It is globally unique and cannot be changed — use it for PublisherId in pyproject.toml.
  3. In the publisher's section, create an API key. Name it and save it somewhere safe — if you lose it you must create a new one (it is not recoverable).

CLI Publishing Flow

Install comfy-cli (requires Python 3.10+; a virtualenv is recommended):

pip install comfy-cli

| Command | What it does | |---------|--------------| | comfy node init | Scaffolds pyproject.toml with registry metadata in the current node pack folder. Fill in the required fields (esp. PublisherId and Repository). | | comfy node publish | Validates and uploads the current version to the registry. Prompts for your API key. Prints the registry URL on success. |

Version immutability: once a version is published it cannot be modified or overwritten. To ship changes, bump version and publish again. To pull a bad version, deprecate it on the website (More Actions > Deprecate), which prompts users to upgrade rather than deleting it.

CI Publishing (GitHub Actions)

Automate publishing on every version bump. Add the API key as a repo secret named REGISTRY_ACCESS_TOKEN (Settings > Secrets and variables > Actions), then create .github/workflows/publish_action.yml:

name: Publish to Comfy registry
on:
  workflow_dispatch:
  push:
    branches:
      - main
    paths:
      - "pyproject.toml"

jobs:
  publish-node:
    name: Publish Custom Node to registry
    runs-on: ubuntu-latest
    steps:
      - name: Check out code
        uses: actions/checkout@v4
      - name: Publish Custom Node
        uses: Comfy-Org/publish-node-action@main
        with:
          personal_access_token: ${{ secrets.REGISTRY_ACCESS_TOKEN }}
  • Triggers on push to main but only when pyproject.toml changes (i.e. when you bump version). workflow_dispatch allows manual runs.
  • If your default branch isn't main, update the branches: list.
  • The action reads the version from pyproject.toml and publishes it — so the typical flow is: bump version, commit, push to main, done.

Optional Frontend Extension

If your pack adds custom UI (widgets, sidebar tabs, menu items), set WEB_DIRECTORY in __init__.py and ship JS there. New frontend extensions should target the modern @comfyorg/extension-api rather than poking at legacy globals; pull in @comfyorg/comfyui-frontend-types for TypeScript types (npm install -D @comfyorg/comfyui-frontend-types). For the full frontend authoring workflow (defineExtension/defineNode/defineWidget and the defineSidebarTab/defineCommand/defineSetting shell APIs), see the sibling comfyui-frontend-extensions skill.

Common Mistakes

  1. Forgetting the return tuple — the FUNCTION method must return (value,), not return value, even for one output.
  2. Single-element RETURN_TYPES without a comma — ("IMAGE") is a string, not a tuple. Write ("IMAGE",).
  3. INPUT_TYPES not a @classmethod — ComfyUI calls it on the class; missing the decorator breaks node loading.
  4. Trying to overwrite a published version — versions are immutable. Bump version instead; deprecate bad ones on the website.
  5. Renaming name after publishing — it's immutable and globally unique. Pick a good name (no "ComfyUI" prefix) up front.
  6. Missing [project.urls].Repository — it's required; publishing fails without a valid repo URL.
  7. Wrong PublisherId — use the id after the @ on your profile, not your display name.
  8. Oversized icon — must be square and ≤ 400×400px; larger images are rejected.
  9. Renaming class keys in NODE_CLASS_MAPPINGS — the key is the class_type stored in workflow JSON. Changing it breaks every saved workflow that used the node.
  10. Committing the API key — store it as the REGISTRY_ACCESS_TOKEN secret; never in pyproject.toml or the repo.

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.