Custom Nodes¶
nodes
¶
Custom nodes management — additive-only manifest system.
Provides a simple, reliable engine for managing ComfyUI custom nodes:
- Install missing bundled nodes (
git clone). - Update existing bundled nodes (
git pull --ff-only). - Never remove user-installed nodes.
Uses uv exclusively for package installs.
The manifest is defined in custom_nodes.json with the schema
described by :class:NodeManifest and :class:NodeEntry.
NodeEntry
¶
Bases: BaseModel
A single custom node definition in the manifest.
Attributes:
| Name | Type | Description |
|---|---|---|
name |
str
|
Directory name for the node (used as clone target). |
url |
str
|
Git repository URL. |
tier |
str
|
Bundle tier — |
requirements |
str | None
|
Relative path to a |
subfolder |
str | None
|
If set, the node lives inside another node's directory (e.g. Impact-Subpack inside Impact-Pack). |
note |
str | None
|
Human-readable comment (not used by the installer). |
NodeManifest
¶
Bases: BaseModel
The custom_nodes.json manifest.
filter_by_tier(manifest, tier)
¶
Return a new manifest containing only nodes for the given tier.
Each tier includes all nodes from lower tiers::
minimal ⊂ umeairt ⊂ full
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
manifest
|
NodeManifest
|
The full manifest. |
required |
tier
|
str
|
One of |
required |
Returns:
| Type | Description |
|---|---|
NodeManifest
|
A filtered NodeManifest. |
Source code in src/installer/nodes.py
load_manifest(path)
¶
Load and validate the custom_nodes.json manifest.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
Absolute path to the JSON manifest file. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
Validated |
NodeManifest
|
class: |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If path does not exist. |
Source code in src/installer/nodes.py
install_node(node, custom_nodes_dir, python_exe, log)
¶
Install a single custom node via git clone.
Clones the repository into custom_nodes_dir/node.name
(or node.subfolder if specified). On network failure,
retries up to 3 times with shallow clone.
After cloning, installs pip requirements if node.requirements
is set.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
node
|
NodeEntry
|
Node definition from the manifest. |
required |
custom_nodes_dir
|
Path
|
|
required |
python_exe
|
Path
|
Path to the venv Python executable. |
required |
log
|
InstallerLogger
|
Installer logger for user-facing messages. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
|
Source code in src/installer/nodes.py
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 | |
update_node(node, custom_nodes_dir, python_exe, log)
¶
Update an existing custom node via git pull --ff-only.
If the node is not installed, delegates to :func:install_node.
Re-installs pip requirements after pulling in case they changed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
node
|
NodeEntry
|
Node definition from the manifest. |
required |
custom_nodes_dir
|
Path
|
|
required |
python_exe
|
Path
|
Path to the venv Python executable. |
required |
log
|
InstallerLogger
|
Installer logger for user-facing messages. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
|
Source code in src/installer/nodes.py
install_all_nodes(manifest, custom_nodes_dir, python_exe, log)
¶
Install all nodes from the manifest (additive-only).
Only installs missing nodes — existing nodes and user-installed nodes are left untouched. Required nodes are processed first.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
manifest
|
NodeManifest
|
Validated node manifest. |
required |
custom_nodes_dir
|
Path
|
|
required |
python_exe
|
Path
|
Path to the venv Python executable. |
required |
log
|
InstallerLogger
|
Installer logger for user-facing messages. |
required |
Returns:
| Type | Description |
|---|---|
tuple[int, int]
|
Tuple of |
Source code in src/installer/nodes.py
update_all_nodes(manifest, custom_nodes_dir, python_exe, log)
¶
Update all bundled nodes. User-installed nodes are NEVER touched.
Identifies user-installed nodes (present on disk but not in
the manifest) and preserves them. Then updates each manifest
node via :func:update_node.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
manifest
|
NodeManifest
|
Validated node manifest. |
required |
custom_nodes_dir
|
Path
|
|
required |
python_exe
|
Path
|
Path to the venv Python executable. |
required |
log
|
InstallerLogger
|
Installer logger for user-facing messages. |
required |
Returns:
| Type | Description |
|---|---|
tuple[int, int]
|
Tuple of |
Source code in src/installer/nodes.py
reinstall_all_node_requirements(custom_nodes_dir, python_exe, log)
¶
Reinstall requirements for ALL installed custom nodes.
Scans every subdirectory in custom_nodes_dir for a
requirements.txt (or requirements-no-cupy.txt) and
installs it via uv. This is needed when the Python
environment has been recreated (migration, --reinstall).
Does NOT clone or update any node — only installs pip requirements for nodes already present on disk.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
custom_nodes_dir
|
Path
|
|
required |
python_exe
|
Path
|
Path to the venv Python executable. |
required |
log
|
InstallerLogger
|
Installer logger for user-facing messages. |
required |
Returns:
| Type | Description |
|---|---|
tuple[int, int]
|
Tuple of |