Loop Manager
The loop counter that keeps Cyclist workflows from overwriting themselves
- STRING
ComfyUI can't actually loop. The graph is a DAG - a node can't feed itself, and the engine flat-out refuses to run a workflow with a cycle in it. So how does a pack called Cyclist do loops? It cheats the queue. Each time you press Queue Prompt is one iteration; you save a result at the end of the run and load it back at the start of the next one. Loop Manager is the little node that makes that bookkeeping bearable.
At heart it just hands you a string - the loop_id - that everything else in the pack keys off. Memorize/Recall use it as a variable name; the Override/Reload save nodes use it as a filename. Point five nodes at the same loop_id and they're all reading and writing the same slot. That's the whole idea, and on its own it sounds trivial. The reason the node exists is the increment behaviour.
Why you'd reach for it
Here's the problem it solves. You run a loop, it converges, you interrupt it. Now you want to start a fresh loop - but all your saved state (the memorized values, the ForLoop_1.png on disk) is still sitting there from the last run. If you just queue again, iteration one of your new loop reads the old loop's leftovers. Cyclist ships a "New Cycle" button for exactly this: it bumps every loop_id and filename widget so the next run starts clean. Loop Manager automates pressing that button.
The two inputs that matter
loop_id(STRING, defaultForLoop_1) - the name of this loop. If you run more than one loop in a graph, give each its own id so they don't stomp on each other.increment(enum) - the actual brain of the node. Three settings:never- the id never changes on its own; behaves like a plain string constant.by_interrupt_node- when an Interrupt node fires (your stop condition was met), the id auto-advances so your finished result doesn't get clobbered by the next queued run.on_any_interrupt- same as above, plus it advances when you manually cancel the queue. Handy for "skip the failures" workflows where you bail on a bad gen and want the next attempt to start fresh.
The single output is a STRING - wire it into the loop_id/filename inputs of your Memorize, Recall, Override and Reload nodes.
How to install it
Two ways, same as the rest of Cyclist:
- ComfyUI Manager - open the Manager, search comfyui-cyclist, install, restart.
- Manually -
cd ComfyUI/custom_nodes && git clone https://github.com/Pos13/comfyui-cyclist, then restart ComfyUI.
No models, no pip wheels, no CUDA anything - it's pure Python glue.
Things that'll trip you up
Worth saying plainly: this pack is archived. The author put a note right at the top of the README that they're not maintaining it anymore, and it barely registers on the community radar - it's a clever niche tool, not a staple like rgthree or Impact Pack. It still works, but you're on your own if a ComfyUI update breaks something.
Two gotchas specific to the increment feature. First, the "New Cycle" logic that Loop Manager rides on only rewrites loop_id and filename widgets, plus Primitive nodes wired into them - it will not touch a string coming out of a "String Const," "String Op," or "Recall String" node. If you're feeding your loop id through one of those, the auto-increment silently does nothing. Second, if you're using Auto Queue to run the loop hands-free, note that ComfyUI unchecks that box automatically whenever an interrupt fires, so a converged loop stops instead of instantly restarting the next one - you re-check it by hand each cycle. Slightly annoying, but it's a deliberate guard against runaway short-circuits.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| loop_id | STRING | ForLoop_1 | — |
| increment | COMBO | by_interrupt_node | 3 options: never, by_interrupt_node, on_any_interrupt |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| STRING | STRING | — |