Nodes/jlc-comfyui-nodes/ JLC ControlNet Apply (Advanced)
ComfyUI Node

 JLC ControlNet Apply (Advanced)

A ControlNet Apply that loads its own model and chains cleanly

By Damkohler·Created 6 months ago·Updated 2 days ago· 24
 JLC ControlNet Apply (Advanced)
  • image
  • positive
  • negative
  • vae
  • control_net
  • positive
  • negative
  • vae
  • control_net
enabledtrue
strength1.00
start_percent0.000
end_percent1.000
control_net_name

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:

  1. 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.
  2. Otherwise the control_net_name dropdown selects a model from ComfyUI's registered ControlNet directory, loaded and reused through JLC's shared cache.
  3. If neither exists, conditioning passes through unchanged.

That's not the whole story, though. Two behaviors make it genuinely useful:

  • Hard bypass. If enabled is off or strength is 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 with set_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_net in 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.

Categoryconditioning/controlnet

Inputs (10)

NameTypeDefaultDescription
enabledBOOLEANtrueEnable or disable this ControlNet. Disabled = no model load.
imageIMAGEControl image used to generate ControlNet conditioning.
positiveCONDITIONING
negativeCONDITIONING
vaeVAE
strengthFLOAT1.000–10ControlNet influence strength. 0 = disabled behavior.
start_percentFLOAT0.0000–1When ControlNet starts influencing diffusion.
end_percentFLOAT1.0000–1When ControlNet stops influencing diffusion.
control_netoptCONTROL_NETOptional upstream ControlNet. Overrides dropdown selection.
control_net_nameoptCOMBOSelect ControlNet model. If the ControlNet input connector is used, this dropdown is ignored.

Outputs (4)

NameTypeDescription
positiveCONDITIONING
negativeCONDITIONING
vaeVAE
control_netCONTROL_NET