Skip to main content

ComfyUI Types

This is a small helper project to make it easier to write custom nodes for ComfyUI. Usually, types in ComfyUI are represented as string constants for parameter and return types, which can cause errors during development, as it is easy to mistype. With such string constants, your IDE cannot recognize the types and offer suggestions or alarm you about errors. Such an error will only be found, when ComfyUI is restarted and the custom node is executed.

This project provides a small set of shallow Python classes that provide typing, so an IDE can pick up correct types and show errors before the node is imported, making development much faster and reducing debugging.

Installation

Install from PyPI:

pip install comfyui-types

Or via conda:

conda install tkreuziger::comfyui_types

Alternatively, you can install the package locally from source:

git clone https://github.com/tkreuziger/comfyui-types.git ./comfyui_types
pip install ./comfyui_types

Requirements

  • Python 3.10+
  • No runtime dependencies

Defining a custom node

Base node

Your custom node must derive from ComfyUINode:

from comfyui_types import ComfyUINode

class MyCustomNode(ComfyUINode):
    """Your custom node."""

This does most of the heavy lifting and ensures that ComfyUI can import your node correctly.

Meta parameters

Next you can define some meta parameters:

from comfyui_types import ComfyUINode

class MyCustomNode(ComfyUINode):
    function = 'execute'
    category = 'mycategory/mynodes'
    display_name = 'My Custom Node'
    deprecated = False
    experimental = False
  • function works the same as the traditional FUNCTION member, but has a default value of execute. This means that you can save yourself writing one line of code, if you simply name the method of your node that you want to be executed execute.
  • The category member is equivalent to the CATEGORY member, it is simply written in lower case letters for consistency.
  • display_name defines the name that will be exported and used for showing your name in the ComfyUI frontend. If you do not define this member, it will simply use the name of the class, i.e. MyCustomNode in this example, automatically. This is only relevant, if you use the exporter function, described below, otherwise it can safely be ignored.
  • deprecated and experimental are simply aliases for DEPRECATED and EXPERIMENTAL respectively

Defining input parameters

You define your input parameters as fields of the node class. All available input types are described in the documentation.

By default, the name of the field will be used as the name that is shown in the UI. You can override this behavior, by passing the optional parameter display_name, when defining your inputs. Any other options are defined as parameters of the input field:

from comfyui_types import ComfyUINode, StringInput, FloatInput

class MyCustomNode(ComfyUINode):
    pos_prompt_text = StringInput(default='masterpiece', multiline=True)
    neg_prompt_text = StringInput(required=False, default='b&w', multiline=True)
    custom_weight = FloatInput(default=1.0, min=0.0, max=1.0, step=0.1)
    secret_parameter = FloatInput(hidden=True, display_name='super secret')

Input parameters can be required, optional, or hidden (see Input type for more information). Usually, most parameters are required, so the default value for required is True. If you need an optional parameter, pass in required=False. If you want a hidden parameter, pass in hidden=True. Due to the assumption of required being the default state, hidden=True will overwrite the required state.

The definition above will lead to the following inputs for our custom node:

>> print(MyCustomNode.INPUT_TYPES())

{
    'required': {
        'pos_prompt_text': ('STRING', {'multiline': True, 'default': 'masterpiece'}),
        'custom_weight': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0,
                                    'step': 0.1}),
    },
    'optional': {
        'neg_prompt_text': ('STRING', {'multiline': True, 'default': 'b&w'})
    },
    'hidden': {
        'super secret': ('FLOAT', {'lazy': False})
    }
}

Defining output parameters

Output parameters are defined analogously to input parameters as fields. Check the list of available output types in the documentation.

Example:

from comfyui_types import ComfyUINode, StringOutput, FloatOutput

class MyCustomNode(ComfyUINode):
    # Definitions so far...

    combined_prompt = StringOutput()
    calculated_score = FloatOutput(display_name='Final Score')

Outputs are very straightforward to define, as they do not need any configuration. The name for the RETURN_NAMES list is taken from the variable name that you are assigning, i.e., combined_prompt in this example. Alternatively, you can override this in the same way as with input parameters by passing the optional display_name parameter to the definition. The example above would result in the following outputs:

RETURN_TYPES = ('STRING', 'FLOAT')
RETURN_NAMES = ('combined_prompt', 'Final Score')

Examples

We are providing some examples here to help you better understand, how to write your own custom nodes.

Exporting custom nodes

Custom nodes can be manually exported as always like this:

NODE_CLASS_MAPPINGS = {
    'MyCustomNode': MyCustomNode,
}
NODE_DISPLAY_NAME_MAPPINGS = {
    'MyCustomNode': 'My Cool Custom Node',
}

__all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS']

However, there is a convenience function to help with this:

NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS = export_nodes([
    MyCustomNode,
])

__all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS']

(The __all__ is not strictly needed, but good practice.)

This will automatically create the mapping tables according to the class name and optionally the display_name property. If no display_name is set, the class name is used.

Under the hood

Internally, the ComfyUINode simply exports the parameters that you have defined with proper classes and types in such a way that ComfyUI can load them. That means for example that all your input parameters are collected and used to automatically create the INPUT_TYPES dictionary that ComfyUI will try to find in your node. For example, the input parameter

pos_prompt_text = StringInput(default='masterpiece', multiline=True)

will automatically create the following entry in INPUT_TYPES:

('STRING', {'default': 'masterpiece', 'multiline': True})

Compatibility with ComfyUI

The way the ComfyUINode is defined is fully compatible with existing nodes and practices. It simply creates the fields that are expected from a class that ComfyUI imports as a custom node, like INPUT_TYPES. If at any point, you do not like the conventions or they do not work with your use case, you can fall back to the regular way of defining custom nodes in ComfyUI, i.e.:

  • use CATEGORY instead of category
  • use FUNCTION instead of function
  • define your INPUT_TYPES or RETURN_TYPES as always

Only the parts that you choose to use will actually be active, you can mix and match to suit your preferences.

Projects using ComfyUI-Types

The following list of projects are using this project. This is not relevant to end-consumers, but if you are developing your own nodes, head over there and get some inspiration and real-world exposure:

  • ComfyUI Claude: A set of custom nodes that are using Anthropic's Claude models for describing images and transforming texts.

If you want to add a project to this list, please open a PR!

Development

The project uses tox for development. You can get started like this:

git clone https://github.com/tkreuziger/comfyui-types.git ./comfyui_types
cd comfyui_types
uv sync --group dev

Then you can run different parts of the pipeline:

# Format code with Ruff
tox -e format

# Run linters Ruff and MyPy
tox -e lint

# Run tests with pytest
tox -e test

# Build the package
tox -e build

Dependency Groups

This project uses PEP 735 dependency groups for development dependencies. The following groups are available:

  • lint: ruff, mypy
  • test: pytest
  • build: build, twine
  • dev: all of the above plus tox

Install with uv:

uv sync --group dev      # all dev dependencies
uv sync --group lint     # only lint tools
uv sync --group test     # only test tools

License

This code is provided under the terms of the GPL-3.0 license.

Contributions

Contributions of any kind (bug fixes, extensions, documentation etc.) are always welcome, simply open a PR!

Metadata

Release files for comfyui-types 1.4.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for comfyui-types 1.4.1
File Size Uploaded Provenance Actions
comfyui_types-1.4.1.tar.gz 162.9 kB Without provenance Details for comfyui_types-1.4.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for comfyui-types 1.4.1
File Interpreter ABI Platform Actions
comfyui_types-1.4.1-py3-none-any.whl Python 3 none any Details for comfyui_types-1.4.1-py3-none-any.whl

Total release size: 189.6 kB

Release files / comfyui_types-1.4.1.tar.gz

Download URL comfyui_types-1.4.1.tar.gz
Size 162.9 kB
Tags Source
SHA-256 checksum
How to use checksums
eddcd590db232bdcd1423243771ae9b9a91abf90c74b94fbe99c5428c14b19fc
BLAKE2b-256 checksum
How to use checksums
ca4edbb7c7e4cfef879d0b2004fcf916fab679fd00cfcdeca5afbce0aee6919f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/5.1.1 CPython/3.10.12

Release files / comfyui_types-1.4.1-py3-none-any.whl

Download URL comfyui_types-1.4.1-py3-none-any.whl
Size 26.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
38dd7adab9658d43717f6f46ced31e80da59882a1012306ca4546cd4baf8ba34
BLAKE2b-256 checksum
How to use checksums
5420bf33c9bf021c1e9a7294d6a81bd744c475787d2106e7c6711d87a4fa46e1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/5.1.1 CPython/3.10.12

Security for comfyui-types 1.4.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page