CyclicCounter_AS
CyclicCounter_AS and the nested-batch grind
- value
- cycle
ComfyUI has no for-loop. It's a graph, not a script, so "do this 120 times, and make sure each subject eventually pairs with every scene" is a problem most people solve by hand - dragging loaders around, re-queuing manually, losing their place. CyclicCounter_AS (the display name for CyclicIntController) is one tiny node that fixes that. It's a stateful integer counter that gives you two synchronized outputs - the fast inner-loop index and the slow outer-loop count - so a nested "subject × scene" batch just works. For a tool this small, it punches absurdly above its weight.
What it actually does
The node holds a counter in memory and advances it every time ComfyUI executes it. Output value is the current step (0, 1, 2, 3… wrapping back to 0), and output cycle is how many full passes you've completed (0, 0, 0, 0, 1, 1…). Wire value into your inner loader's index and cycle into the outer loader's index, and the pair sweeps the Cartesian product of the two ranges - 20 subjects × 6 scenes, all 120 combinations, no dragging wires.
The mechanism is worth a peek, because the author got the math right. value is start + ((idx * step) % span), and cycle is idx // cycle_len, where cycle_len = span / gcd(span, step). That gcd matters: if your step doesn't divide your range cleanly, a naive counter would wrap at the wrong point and skip values. Here, stepping 2 across a 7-value range still hits all 7 values before the cycle ticks over. The state lives in a class-level dict keyed by the node's ID (or your group_key), and the node's IS_CHANGED always returns NaN, which forces ComfyUI to re-execute it on every queue run so the count persists across the whole batch. Clever and correct.
The inputs that matter
You'll set three of them 90% of the time:
start/end- the inclusive range ofvalue. Six images?0to5.step- how muchvaluejumps each run. Usually1.mode-incrementfor standard looping.decrementcounts down,fixedjust outputsstartforever, andrandomizegives you a random int in range.
Two more are there when you need them: reset forces the whole counter back to 0 (flip it on for one run, then off), and reset_cycle_only drops cycle back to 0 while leaving value's position alone - handy when you're starting a new outer pass mid-sequence. group_key is the interesting one: give the same string to two separate nodes and they share internal state, so you can sync a Load Image at the front of the workflow with a Save Image at the back without dragging a wire across the whole canvas.
Installing it
There are no dependencies, no model files, no requirements.txt - just one pure-Python file. Either install via ComfyUI Manager (search "AgaveLogicCounter"), or:
cd ComfyUI/custom_nodes
git clone https://github.com/agavesunset/AgaveLogicCounter.git
Then restart ComfyUI. You'll find it under Agave → Logic → Cyclic Int Controller. That's the entire install.
Where people get burned
Because the counter is stateful, it does not reset when you edit the workflow - if you forget it's mid-count, your next batch starts at 47, not 0. That's exactly why reset exists, but it's the classic trap with this class of node. Also remember this advances once per queue run, so it pairs with a repeat/loop wrapper or re-queuing - it won't batch a single run into 120 images by itself.
One honest caveat: group_key is the same trade the ecosystem keeps arguing about (the "Anything Anywhere" debate in r/comfyui). Silent, wire-less sync is convenient, but when a workflow misbehaves, an invisible string-keyed link is much harder to debug than a visible connection. It's great for a personal workflow; think twice before you bake it into one you share.
Inputs (7)
| Name | Type | Default | Description |
|---|---|---|---|
| mode | COMBO | increment | 4 options: fixed, increment, decrement, randomize |
| start | INT | 0-1000000–1000000 | — |
| end | INT | 6-1000000–1000000 | — |
| step | INT | 11–1000000 | — |
| group_key | STRING | — | |
| reset | BOOLEAN | false | — |
| reset_cycle_only | BOOLEAN | false | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| value | INT | — |
| cycle | INT | — |