ComfyUI/docs/custom_nodes.md
2025-12-26 15:36:44 -08:00

350 lines
11 KiB
Markdown

# Custom Nodes
Custom Nodes can be added to ComfyUI by copying and pasting Python files into your `./custom_nodes` directory.
## Installing Custom Nodes
There are two kinds of custom nodes: vanilla custom nodes, which generally expect to be dropped into the `custom_nodes` directory and managed by a tool called the ComfyUI Extension manager ("vanilla" custom nodes) and this repository's opinionated, installable custom nodes ("installable").
### Installing ComfyUI Manager
ComfyUI-Manager is a popular extension to help you install and manage other custom nodes. To install it, you will need `git` on your system.
#### Manual Install
The installation process for ComfyUI-Manager requires two steps: installing its Python dependencies, and then cloning its code into the `custom_nodes` directory.
1. **Install dependencies.**
First, ensure you have installed `comfyui` from this repository as described in the Installing section. Then, run the following command from your ComfyUI workspace directory (the one containing your `.venv` folder) to install the extra dependencies for ComfyUI-Manager:
```shell
uv pip install --torch-backend=auto --upgrade "comfyui[comfyui_manager]@git+https://github.com/hiddenswitch/ComfyUI.git"
```
2. **Clone the repository.**
Next, you need to clone the ComfyUI-Manager repository into the `custom_nodes` directory within your ComfyUI workspace. Your workspace is the directory you created during the initial setup where you ran `uv venv` (e.g., `~/Documents/ComfyUI_Workspace`).
If the `custom_nodes` directory does not exist in your workspace, create it first (e.g., `mkdir custom_nodes`). Then, from your workspace directory, run the following command:
```shell
git clone https://github.com/Comfy-Org/ComfyUI-Manager.git ./custom_nodes/ComfyUI-Manager
```
This command will place the manager's code into `custom_nodes/ComfyUI-Manager/`.
3. **Restart ComfyUI.**
After the cloning is complete, restart ComfyUI. You should now see a "Manager" button in the menu.
### PyPi Install
[ComfyUI-Manager](https://github.com/Comfy-Org/ComfyUI-Manager/tree/manager-v4)
**ComfyUI-Manager** is an extension that allows you to easily install, update, and manage custom nodes for ComfyUI.
### Setup
1. Install the manager dependencies:
```bash
pip install -r manager_requirements.txt
```
2. Enable the manager with the `--enable-manager` flag when running ComfyUI:
```bash
python main.py --enable-manager
```
### Command Line Options
| Flag | Description |
|------|-------------|
| `--enable-manager` | Enable ComfyUI-Manager |
| `--enable-manager-legacy-ui` | Use the legacy manager UI instead of the new UI (requires `--enable-manager`) |
| `--disable-manager-ui` | Disable the manager UI and endpoints while keeping background features like security checks and scheduled installation completion (requires `--enable-manager`) |
### Vanilla Custom Nodes
Clone the repository containing the custom nodes into `custom_nodes/` in your working directory and install its requirements, or use the manager.
### Custom Nodes Authored for this Fork
Run `uv pip install "git+https://github.com/owner/repository"`, replacing the `git` repository with the installable custom nodes URL. This is just the GitHub URL.
## Authoring Custom Nodes
These instructions will allow you to quickly author installable custom nodes.
#### Using `pyproject.toml` for projects with existing `requirements.txt`
Suppose your custom nodes called `my_comfyui_nodes` has a folder layout that looks like this:
```
__init__.py
some_python_file.py
requirements.txt
LICENSE.txt
some_directory/some_code.py
```
First, add an `__init__.py` to `some_directory`, so that it is a Python package:
```
__init__.py
some_python_file.py
requirements.txt
LICENSE.txt
some_directory/__init__.py
some_directory/some_code.py
```
Then, if your `NODE_CLASS_MAPPINGS` are declared in `__init__.py`, use the following as a `pyproject.toml`, substituting your actual project name:
**pyproject.toml**
```toml
[project]
name = "my_comfyui_nodes"
description = "My nodes description."
version = "1.0.0"
license = { file = "LICENSE.txt" }
dynamic = ["dependencies"]
[project.urls]
Repository = "https://github.com/your-github-username/my-comfyui-nodes"
# Used by Comfy Registry https://comfyregistry.org
[tool.comfy]
PublisherId = "your-github-username"
DisplayName = "my_comfyui_nodes"
Icon = ""
[build-system]
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"
[tool.setuptools]
packages = ["my_comfyui_nodes", "my_comfyui_nodes.some_directory"]
package-dir = { "my_comfyui_nodes" = ".", "my_comfyui_nodes.some_directory" = "some_directory" }
[tool.setuptools.dynamic]
dependencies = { file = ["requirements.txt"] }
[project.entry-points."comfyui.custom_nodes"]
my_comfyui_nodes = "my_comfyui_nodes"
```
Observe that the directory should now be listed as a package in the `packages` and `package-dir` statement.
#### Using `setup.py`
Create a `requirements.txt`:
```
comfyui
```
Observe `comfyui` is now a requirement for using your custom nodes. This will ensure you will be able to access `comfyui` as a library. For example, your code will now be able to import the folder paths using `from comfyui.cmd import folder_paths`. Because you will be using my fork, use this:
```
comfyui @ git+https://github.com/hiddenswitch/ComfyUI.git
```
Additionally, create a `pyproject.toml`:
```
[build-system]
requires = ["setuptools", "wheel", "pip"]
build-backend = "setuptools.build_meta"
```
This ensures you will be compatible with later versions of Python.
Finally, move your nodes to a directory with an empty `__init__.py`, i.e., a package. You should have a file structure like this:
```
# the root of your git repository
/.git
/pyproject.toml
/requirements.txt
/mypackage_custom_nodes/__init__.py
/mypackage_custom_nodes/some_nodes.py
```
Finally, create a `setup.py` at the root of your custom nodes package / repository. Here is an example:
**setup.py**
```python
from setuptools import setup, find_packages
import os.path
setup(
name="mypackage",
version="0.0.1",
packages=find_packages(),
install_requires=open(os.path.join(os.path.dirname(__file__), "requirements.txt")).readlines(),
author='',
author_email='',
description='',
entry_points={
'comfyui.custom_nodes': [
'mypackage = mypackage_custom_nodes',
],
},
)
```
All `.py` files located in the package specified by the entrypoint with your package's name will be scanned for node class mappings declared like this:
**some_nodes.py**:
```py
from comfy.nodes.package_typing import CustomNode
class Binary_Preprocessor(CustomNode):
...
NODE_CLASS_MAPPINGS = {
"BinaryPreprocessor": Binary_Preprocessor
}
NODE_DISPLAY_NAME_MAPPINGS = {
"BinaryPreprocessor": "Binary Lines"
}
```
These packages will be scanned recursively.
Extending the `comfy.nodes.package_typing.CustomNode` provides type hints for authoring nodes.
## Adding Custom Configuration
Declare an entry point for configuration hooks in your **setup.py** that defines a function that takes and returns an
`configargparser.ArgParser` object:
**setup.py**
```python
setup(
name="mypackage",
...
entry_points = {
'comfyui.custom_nodes': [
'mypackage = mypackage_custom_nodes',
],
'comfyui.custom_config': [
'mypackage = mypackage_custom_config:add_configuration',
]
},
)
```
**mypackage_custom_config.py**:
```python
import configargparse
def add_configuration(parser: configargparse.ArgParser) -> configargparse.ArgParser:
parser.add_argument("--openai-api-key",
required=False,
type=str,
help="Configures the OpenAI API Key for the OpenAI nodes", env_var="OPENAI_API_KEY")
return parser
```
You can now see your configuration option at the bottom of the `--help` command along with hints for how to use it:
```shell
$ comfyui --help
usage: comfyui.exe [-h] [-c CONFIG_FILE] [--write-out-config-file CONFIG_OUTPUT_PATH] [-w CWD] [-H [IP]] [--port PORT]
[--enable-cors-header [ORIGIN]] [--max-upload-size MAX_UPLOAD_SIZE] [--extra-model-paths-config PATH [PATH ...]]
...
[--openai-api-key OPENAI_API_KEY]
options:
-h, --help show this help message and exit
-c CONFIG_FILE, --config CONFIG_FILE
config file path
--write-out-config-file CONFIG_OUTPUT_PATH
takes the current command line args and writes them out to a config file at the given path, then exits
-w CWD, --cwd CWD Specify the working directory. If not set, this is the current working directory. models/, input/, output/ and other
directories will be located here by default. [env var: COMFYUI_CWD]
-H [IP], --listen [IP]
Specify the IP address to listen on (default: 127.0.0.1). If --listen is provided without an argument, it defaults to
0.0.0.0. (listens on all) [env var: COMFYUI_LISTEN]
--port PORT Set the listen port. [env var: COMFYUI_PORT]
...
--distributed-queue-name DISTRIBUTED_QUEUE_NAME
This name will be used by the frontends and workers to exchange prompt requests and replies. Progress updates will be
prefixed by the queue name, followed by a '.', then the user ID [env var: COMFYUI_DISTRIBUTED_QUEUE_NAME]
--external-address EXTERNAL_ADDRESS
Specifies a base URL for external addresses reported by the API, such as for image paths. [env var:
COMFYUI_EXTERNAL_ADDRESS]
--openai-api-key OPENAI_API_KEY
Configures the OpenAI API Key for the OpenAI nodes [env var: OPENAI_API_KEY]
```
You can now start `comfyui` with:
```shell
uv run comfyui --openai-api-key=abcdefg12345
```
or set the environment variable you specified:
```shell
export OPENAI_API_KEY=abcdefg12345
uv run comfyui
```
or add it to your config file:
**config.yaml**:
```txt
openapi-api-key: abcdefg12345
```
```shell
comfyui --config config.yaml
```
Since `comfyui` looks for a `config.yaml` in your current working directory by default, you can omit the argument if
`config.yaml` is located in your current working directory:
```shell
uv run comfyui
```
Your entry point for adding configuration options should **not** import your nodes. This gives you the opportunity to
use the configuration you added in your nodes; otherwise, if you imported your nodes in your configuration entry point,
the nodes will potentially be initialized without any configuration.
Access your configuration from `cli_args`:
```python
from comfy.cli_args import args
from comfy.cli_args_types import Configuration
from typing import Optional
# Add type hints when accessing args
class CustomConfiguration(Configuration):
def __init__(self):
super().__init__()
self.openai_api_key: Optional[str] = None
args: CustomConfiguration
class OpenAINode(CustomNode):
...
def execute(self):
openai_api_key = args.open_api_key
```