Nodes/ControlFlowUtils/πŸ”„ Cycle
ComfyUI Node

πŸ”„ Cycle

The ComfyUI Loop That Survives Multiple Queue Runs

By VykosXΒ·Created 2 years agoΒ·Updated 2 years agoΒ· 147
πŸ”„ Cycle
    • CYCLE
    • RESET?
    β—„start0β–Ί
    β—„step1β–Ί
    β—„end10β–Ί
    β—„manual_resetβ€”β–Ί
    β—„auto_resettrueβ–Ί

    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.

    Category🐺 VykosX-ControlFlowUtils

    Inputs (5)

    NameTypeDefaultDescription
    startINT0The 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 is considered to be finished
    manual_resetoptBOOLEANEnable to force a 'DRY RUN' and reset the Cycle to its first iteration
    auto_resetoptBOOLEANtrueEnable to have the loop counter automatically reset to Start once it reaches End

    Outputs (2)

    NameTypeDescription
    CYCLECYCLEConnect to the CYCLE input of a [CycleContinue] node to establish a loop
    RESET?BOOLEANSpecifies whether the Cycle is executing its 'DRY RUN' iteration