Files
ComfyUI-UTFCN/README.md
T
Ethanfel cc728eb50b Support uninstalled / missing nodes
Previously the index was built only from the live registry, so a custom node
that wasn't installed (a red "missing" node in a downloaded workflow) was
invisible — the main point of the tool. Now:

- Backend: utfcn_core split into build_context / build_index / match. build_index
  also emits curated candidates for uninstalled source types (curated-only), and
  a new POST /utfcn/match matches missing nodes by their serialized signature
  against installed core/other-pack nodes.
- Frontend: nodeType() reads a missing placeholder's last_serialization.type;
  matchMissing() feeds serialized slots to /utfcn/match and merges the results;
  the right-click item moved to a canvas-level getNodeMenuOptions patch so it
  reaches missing placeholders too. Bulk dialog labels them "not installed".

Replace a missing node with core without installing its pack. Links are rewired
losslessly; widget values can't be carried for a node whose def is absent.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 10:43:13 +02:00

122 lines
4.8 KiB
Markdown

<p align="center">
<img src="assets/social-preview.png" alt="UTFCN — Use The Core Nodes" width="100%">
</p>
# UTFCN — Use The F***ing Core Nodes
A ComfyUI companion that nudges your workflows back toward **core nodes**. Over
time a graph accumulates custom nodes that just re-implement things ComfyUI now
ships itself. UTFCN spots those and helps you swap them out — fewer dependencies,
more portable workflows.
It does three things:
1. **On add** — drop a custom node that has a core (or otherwise installed)
equivalent and, depending on the mode, UTFCN either shows a quiet tip or
(in **Force mode**) auto-replaces it with the equivalent on the spot.
2. **Replace across a workflow** — `Extensions ▸ UTFCN ▸ Replace custom nodes
with core / available…` (also in the command palette). It scans the open
graph and shows a **preview** of every swap before anything changes.
3. **Replace one node** — right-click any custom node ▸ **Replace with core /
available**.
Nothing is ever swapped without your say-so, and the engine only rewires slots
it can move *losslessly* — anything it can't map is reported, not guessed.
### Works on uninstalled ("missing") nodes
The headline case: open a downloaded workflow full of red **missing** nodes and
replace them with core equivalents **without installing the packs at all**.
ComfyUI keeps each missing node as a placeholder that remembers its original
type and wiring, so UTFCN can still match and swap it — via a curated rule (by
name) or by matching the node's *serialized* signature against your core nodes.
Both "Replace…" and the right-click item work on them; the bulk dialog labels
them `⚠ not installed`. (Widget values aren't carried for a node whose
definition you don't have — links are.)
## How it decides what's equivalent
The backend reads the live node registry (real `INPUT_TYPES` / `RETURN_TYPES`
and each node's source module) and ranks candidates in three tiers:
| Tier | Meaning | Auto-applied? |
|------|---------|---------------|
| **curated** | a hand-written rule in `mappings.json` / `user_mappings.json` | yes (verified) |
| **exact** | identical input names+types and output types to a core/other-pack node | yes (verified) |
| **partial** | can structurally stand in (accepts all inputs, provides all outputs) but names/slots differ | suggestion only |
"Available" means core is preferred, and if there's no core match it will offer
an equivalent from a **different installed pack** as a fallback.
For an **uninstalled** node only *curated* (by name) and *partial* (by its
serialized link signature) can apply — the exact tier needs the widget-level
signature, which a node you haven't installed can't provide.
## Shipped equivalences
`mappings.json` ships a small, hand-verified set (each checked lossless against
the real core signatures):
- `GetImageSize+` (essentials) → core `GetImageSize`
- `MaskPreview+` (essentials) → core `MaskPreview`
- `BOOLConstant` / `INTConstant` / `FloatConstant` (KJNodes) → core
`PrimitiveBoolean` / `PrimitiveInt` / `PrimitiveFloat`
- `Convert Masks to Images` / `Mask Invert` (WAS) → core `MaskToImage` /
`InvertMask`
Rules for nodes you don't have installed are simply ignored. Everything else is
found live: exact-signature matches auto-apply, looser ones are suggested.
## Adding your own equivalences
To bless a partial match as safe, or to fix up slots whose names differ, add a
rule to **`user_mappings.json`** (merged over the shipped `mappings.json`,
survives updates):
```json
{
"rules": {
"SomeCustomNode": [
{
"to": "CoreNode",
"note": "why they're equivalent (shown in the preview)",
"inputs": { "old_input": "new_input" },
"widgets": { "old_widget": "new_widget" },
"outputs": { "old_output": "new_output" }
}
]
}
}
```
List targets in preference order (put the core node first). Any slot you don't
list is matched by identical name, then by type + order. After editing, run
`Extensions ▸ UTFCN ▸ Refresh equivalence index` (no restart needed).
## Settings
**UTFCN ▸ On add ▸ When adding a custom node that has a core / available
equivalent:**
- **Off** — do nothing.
- **Suggest** (default) — show a tip pointing at the equivalent.
- **Force (auto-replace with core)** — immediately swap it for the equivalent.
Force only ever applies **verified** matches (curated or exact-signature); it
never auto-applies a heuristic guess, and it never fires while you're opening
or importing a workflow — only on nodes *you* add. Undo with Ctrl+Z.
## Install
Clone into `ComfyUI/custom_nodes/` and restart ComfyUI:
```
git clone https://github.com/ethanfel/ComfyUI-UTFCN
```
No Python dependencies. The node adds a single read-only server route
(`/utfcn/scan`) and a frontend extension.
## License
GPL-3.0-or-later. See [LICENSE](LICENSE).