JLC ControlNet Apply (Advanced)
A ControlNet Apply that loads its own model and chains cleanly
- image
- positive
- negative
- vae
- control_net
- positive
- negative
- vae
- control_net
If you've built a multi-ControlNet workflow, you know the ritual: one ControlNetLoader, one Apply, repeat, then a chain of conditioning wires that looks like a bad cable drawer. JLC ControlNet Apply (Advanced) collapses the loader into the Apply node and, if you pair it with the pack's Composition node, gives you a modular route to multi-ControlNet that's much easier to reason about.
The core idea is simple: it's an Apply node that can also load its own ControlNet model from a dropdown, cache it, and build the standard native ControlNet chain - the same previous_controlnet linkage core ComfyUI uses - while passing the model, VAE, and conditioning through so you can keep wiring.
How it works
The node sources its ControlNet in priority order:
- A connected control_net input wins. You loaded the model somewhere else (a third-party loader, a custom location, a shared branch) and you're passing it in.
- Otherwise the control_net_name dropdown selects a model from ComfyUI's registered ControlNet directory, loaded and reused through JLC's shared cache.
- If neither exists, conditioning passes through unchanged.
That's not the whole story, though. Two behaviors make it genuinely useful:
- Hard bypass. If
enabledis off orstrengthis 0, the node returns before it touches model loading at all. Disabled stages cost you nothing, which matters when you're toggling experimental branches in a big graph. - Native chaining, copy discipline. For each distinct ControlNet already attached to your conditioning, it makes a per-run copy, applies your hint image/strength/range via
set_cond_hint(), and reconnects the chain withset_previous_controlnet(). Same native recursive execution ComfyUI would give you - just wrapped with caching and pass-throughs.
The name says "Advanced," and the advanced part is really this: each Apply is a chain-building stage, and you can line up several and let the pack's JLC ControlNet Composition node turn that chain into JLC's non-recursive weighted fusion (roughly A(x)+B(x)+C(x) instead of A(B(C(x)))). If you just want one Apply in a graph, you don't need the Composition half.
Inputs that matter
- enabled - the bypass switch. Off means no model load.
- image - your hint image (canny map, depth map, pose skeleton…). This is what gets encoded into conditioning.
- strength (0–10, default 1) - how hard the ControlNet pushes. 0 disables.
- start_percent / end_percent - the window of denoising where the ControlNet acts. For structure-heavy work, the standing advice is to let go once composition has formed - try start 0, end 0.5.
- positive / negative - your conditioning streams in and out.
- control_net vs control_net_name - the source-priority pair above.
Outputs are positive, negative, vae, and control_net - the last one is what makes daisy-chaining and reuse practical.
Installing it
This ships in jlc-comfyui-nodes, so it installs with the whole pack:
cd ComfyUI/custom_nodes
git clone https://github.com/Damkohler/jlc-comfyui-nodes.git
Restart ComfyUI, or install "jlc-comfyui-nodes" from ComfyUI Manager. No extra Python deps. The ControlNet model itself is a separate download - you still need a model file (e.g. a Flux union ControlNet) in your models/controlnet folder.
Where people get burned
- The dropdown is ignored when the input is connected. If you wire
control_netin and the node seems to use the wrong model, that's the priority order working as designed. - If it suddenly runs glacially slow, check your launch flags. The pack's author traced a catastrophic slowdown to launching ComfyUI with forced
--lowvram, which triggers destructive unload/reload cycles - not to the node's composition math. On a 16 GB GPU, normal VRAM mode with DynamicVRAM is the supported path. - A single ControlNet at weight 1.0 routes through the native path when Composition is involved. That's an optimization, not a lost feature.
Honest caveat: this is a small solo project, and its speed claims are the author's own benchmarks on a 16 GB RTX 4090 laptop. The node is sound and well-documented; just don't expect it to magically halve your sample time by itself. It's a tidy Apply node with good caching - and with Composition behind it, a genuinely different way to stack ControlNets.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| enabled | BOOLEAN | true | Enable or disable this ControlNet. Disabled = no model load. |
| image | IMAGE | Control image used to generate ControlNet conditioning. | |
| positive | CONDITIONING | — | |
| negative | CONDITIONING | — | |
| vae | VAE | — | |
| strength | FLOAT | 1.000–10 | ControlNet influence strength. 0 = disabled behavior. |
| start_percent | FLOAT | 0.0000–1 | When ControlNet starts influencing diffusion. |
| end_percent | FLOAT | 1.0000–1 | When ControlNet stops influencing diffusion. |
| control_netopt | CONTROL_NET | Optional upstream ControlNet. Overrides dropdown selection. | |
| control_net_nameopt | COMBO | Select ControlNet model. If the ControlNet input connector is used, this dropdown is ignored. |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| positive | CONDITIONING | — |
| negative | CONDITIONING | — |
| vae | VAE | — |
| control_net | CONTROL_NET | — |