Nodes/ControlFlowUtils/πŸ”ƒ Loop Open
ComfyUI Node

πŸ”ƒ Loop Open

The ComfyUI For-Loop That Clones Your Whole Subgraph

By VykosXΒ·Created 2 years agoΒ·Updated 2 years agoΒ· 147
πŸ”ƒ Loop Open
  • index_override
  • data
  • aux
  • aux2
  • aux3
  • aux4
  • aux5
  • LOOP
  • data
  • aux
  • aux2
  • aux3
  • aux4
  • aux5
β—„start1β–Ί
β—„step1β–Ί
β—„end10β–Ί
β—„conditionTrueβ–Ί

Stock ComfyUI has no loops. Want to iterate a prompt five times, upscale in stages, or zoom-animate frame after frame? You used to copy-paste a node block five times, or farm the repetition out to a script. LoopOpen (πŸ”ƒ Loop Open, from ControlFlowUtils) fixes that: it's the opening brace of a real for/while loop that repeats a chunk of your workflow, no copy-paste required.

It's the top half of a two-node pair. LoopOpen starts the loop; LoopClose (⏹️ Loop Close) ends it. Everything wired between them gets repeated.

How it works - the important part

This isn't a cosmetic trick. Under the hood it uses ComfyUI's Execution Model Inversion: when the loop needs another iteration, LoopClose asks ComfyUI's graph builder to clone every node between the two loop nodes, feed the new copies the current iteration's data, and run them. Each iteration is a fresh set of node copies. That's genuinely clever, and it's also why the author tags it "a bit of proof of concept."

You control the iteration with four numbers and one string:

  • start, step, end - the classic range. Default 1, 1, 10 gives you indices 1 through 9. Step 0 plus a condition turns it into a pure while-loop.
  • condition - a string evaluated like Python, default "True". The loop runs while it's true. Combine it with a step range and you get "run until the condition breaks OR the range runs out, whichever first."

Then the data slots. data and aux through aux5 carry values into each iteration, and here's the loop's whole secret: whatever you pass back into LoopClose's matching inputs on the other side becomes the next iteration's data. That round-trip is how state survives from iteration to iteration - a running seed, an accumulated batch, a growing prompt.

The LOOP output is a dict with the current index, start, step, end, finished status, and more. You can intercept it with this pack's DataMonitor to read what iteration you're on. index_override lets you force-jump the counter - useful for complex step math or early termination.

If the condition evaluates false at LoopOpen, execution blocks right there and everything after it is skipped.

Where people actually use it

The community's favorite real-world demo is img2img loops for endless animations - one widely-shared project ran a 1000-image Flux Klein zoom through a LoopOpen/LoopClose pair, changing the prompt periodically. That's the power: one block, repeated thousands of times, instead of a wall of pasted nodes.

The gotchas are real, though. Every iteration stays in memory - that same 1000-image project had to be batched because "Comfy keeps every iteration of the loop in memory," and RAM grows with each pass. Add a GarbageCollector inside the loop, and don't try to hold a thousand latents. Also, because it's the young execution-inversion machinery, it needs a recent ComfyUI - older builds throw "please update your ComfyUI" errors. And the README's known-issues section warns that Memory Storages persist a little too well across workflows; if a loop starts behaving like it has leftover state, restart ComfyUI.

Install

# ComfyUI Manager β†’ Install Custom Nodes β†’ search "ControlFlowUtils"
# or manually:
cd ComfyUI/custom_nodes
git clone https://github.com/VykosX/ControlFlowUtils

Restart, then find LoopOpen under 🐺 VykosX-ControlFlowUtils. No dependencies beyond a current ComfyUI. If loops are the reason you installed this pack, start from one of the included sample workflows - the repo ships several loop demos, and a working graph teaches more than ten paragraphs.

Category🐺 VykosX-ControlFlowUtils

Inputs (11)

NameTypeDefaultDescription
startINT1The initial value of the loop counter
stepINT1How much the loop counter gets increased or decreased by on each iteration
endINT10The value at which the loop should stop
conditionSTRINGTrueThe loop will be executed only if the specified condition evaluates to True
index_overrideopt*Manually override the current index of the Cycle. You can use this input to have complex Step calculations or to reset the loop manually
dataopt*Any data you wish to iterate on in the loop
auxopt*Any auxilliary data you wish to iterate on in the loop
aux2opt*Any auxilliary data you wish to iterate on in the loop
aux3opt*Any auxilliary data you wish to iterate on in the loop
aux4opt*Any auxilliary data you wish to iterate on in the loop
aux5opt*Any auxilliary data you wish to iterate on in the loop

Outputs (7)

NameTypeDescription
LOOP*Dictionary with information about the Loop. Connect to the LOOP input of a [Loop Close] node
data*Data to iterate on in the loop. Connect to the relevant Input of a [Loop Close] node to preserve any changes between iterations
aux*Data to iterate on in the loop. Connect to the relevant Input of a [Loop Close] node to preserve any changes between iterations
aux2*Data to iterate on in the loop. Connect to the relevant Input of a [Loop Close] node to preserve any changes between iterations
aux3*Data to iterate on in the loop. Connect to the relevant Input of a [Loop Close] node to preserve any changes between iterations
aux4*Data to iterate on in the loop. Connect to the relevant Input of a [Loop Close] node to preserve any changes between iterations
aux5*Data to iterate on in the loop. Connect to the relevant Input of a [Loop Close] node to preserve any changes between iterations