π Cycle
The ComfyUI Loop That Survives Multiple Queue Runs
- CYCLE
- RESET?
Here's a ComfyUI problem most node packs don't even try to solve: loops that span multiple queues. The LoopOpen/LoopClose pair repeats a block inside a single prompt execution. But what if you want iteration N+1 to start only after you've had a chance to look at iteration N - or after a completely separate prompt run finishes? That's what the Cycle family does, and Cycle (π Cycle) is its starting gate.
A Cycle is a loop whose state lives in memory between prompt executions. Hit Queue, the cycle advances one step, data gets cached; hit Queue again, it advances another. It's less "for loop" and more "each queue run is one tick of a state machine" - which is exactly the right tool for progressive workflows, multi-pass refinement, or anything where you want to inspect intermediate results.
The three-node family
The README's diagram is a circle: Cycle β Cycle Continue β Cycle End β back to Cycle.
- Cycle opens the loop and owns the counter.
- Cycle Continue (β©) carries your data forward through processing.
- Cycle End (βͺ) caches the processed data back into the loop state for the next prompt run.
Cycle itself is simple: start, step, end define the range. Two optional toggles matter:
- auto_reset - on by default. When the counter hits end, it wraps back to start and keeps cycling. Off, it stops and waits for a manual reset.
- manual_reset - force the cycle back to its very first iteration (the "DRY RUN").
And it has two outputs: CYCLE (the loop handle you wire to Cycle Continue) and RESET? (a boolean that's true only during the first run).
The DRY RUN - read this twice
The first iteration of any cycle is special: the author calls it a DRY RUN. On that pass, the index and all data are None, and the RESET? output is True. Why? Because cycles carry state from previous runs, so the first run needs a chance to initialize everything before any real data exists.
The pattern is: check RESET? with an IfConditionSelector and, on the dry run, set up your starting values - an initial seed, an empty batch, a base prompt. On every later run, RESET? is false and you work with the carried-over data. Miss this and your first real iteration will be working with None and erroring in confusing ways.
Because the state lives in the node instance inside the running Python process, a few practical rules follow:
- The cycle state persists as long as ComfyUI keeps running - restarting ComfyUI resets it.
- Changing the workflow and running again keeps old state, which is either a feature (resume where you left off) or a trap (stale data from a previous experiment). If a cycle misbehaves after you've edited it, restart ComfyUI.
- This is the same persistence family that the README warns about for Memory Storage nodes: state outliving the workflow that created it is a known quirk of this pack.
Install
Cycle ships in VykosX/ControlFlowUtils:
# ComfyUI Manager β Install Custom Nodes β search "ControlFlowUtils"
# or manually:
cd ComfyUI/custom_nodes
git clone https://github.com/VykosX/ControlFlowUtils
Restart, find it under πΊ VykosX-ControlFlowUtils, and try the "Simple Cycle Workflow" from the repo's sample files. A caveat before you fall in love: cycles require you to actually queue prompts repeatedly (or use Auto-Queue/Instant mode) and to halt the cycle when done - this pack's Halt Execution node is the standard way to stop a finished cycle from re-queuing forever. Powerful, but you are the loop's break condition.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| start | INT | 0 | The initial value of the loop counter |
| step | INT | 1 | How much the loop counter gets increased or decreased by on each iteration |
| end | INT | 10 | The value at which the loop is considered to be finished |
| manual_resetopt | BOOLEAN | Enable to force a 'DRY RUN' and reset the Cycle to its first iteration | |
| auto_resetopt | BOOLEAN | true | Enable to have the loop counter automatically reset to Start once it reaches End |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| CYCLE | CYCLE | Connect to the CYCLE input of a [CycleContinue] node to establish a loop |
| RESET? | BOOLEAN | Specifies whether the Cycle is executing its 'DRY RUN' iteration |