Recall String
Read a string back from the last run
- STRING
Recall String is one half of a memory cell. It pulls a string that a previous run stashed away and hands it to the current run, so your workflow can remember something from one queue to the next instead of starting cold every time. That's the whole trick behind Cyclist: ComfyUI can already repeat a workflow forever, but each pass normally forgets everything. Recall String (plus its partner, Memorize String) gives one loop a tiny bit of persistent state.
You'd reach for it whenever a decision this run depends on something the last run computed - a caption you want to compare against, a running label, the name of the best result so far, a seed you jotted down as text. Iterative loops are exactly the thing ComfyUI is awkward at, because the graph is a DAG and can't legally contain a cycle. Cyclist sidesteps that by breaking the loop across separate queue presses: you save at the end, recall at the start, and the "wire" that closes the loop is memory, not a link the scheduler would reject.
How it works
Memorize String writes a string into an in-memory slot keyed by a loop ID. Recall String reads that same slot back. Two things worth burning in early. First, it's RAM, not disk - restart ComfyUI and the value is gone. This is the "Recall" family (memory); the "Reload" nodes in the same pack are the ones that persist to your output folder. Second, each loop ID holds exactly one string. Storage is one Int, one Float, one String and one Conditioning per ID, so if you want two separate strings alive at once, give them two different loop IDs.
On the very first pass there's nothing in memory yet, and that's what the fallback is for.
Inputs and outputs
Only three things exist here, and you'll touch two of them:
- loop_id (string, default
ForLoop_1) - the name of the memory slot. It has to match theloop_idon the Memorize String node that saved the value, or you'll read the wrong slot (or an empty one). If you're running a Loop Manager, feed itsloop_idoutput into both nodes so they always agree. - fallback (string, optional) - what to hand downstream when the slot is empty, i.e. the first iteration before anything's been memorized. Leave it unset and you'll get an empty string on that first pass, which is often fine, but wire it up if downstream nodes choke on empty input.
The single output is a STRING, which goes wherever a string goes - a CLIP text encode, a filename, a comparison node, a switch.
Installing it
The pack is on ComfyUI Manager. Open Manager, search comfyui-cyclist, install, restart ComfyUI. If you'd rather do it by hand:
cd ComfyUI/custom_nodes
git clone https://github.com/Pos13/comfyui-cyclist
then restart. No models to download, no heavy Python dependencies - it's pure graph plumbing, which is a nice change from the usual custom-node dependency hell where every install drags in a requirements.txt that fights with something you already have.
One thing to know before you commit: the repo is archived. The author (Postpos on Civitai) has said outright they're not going to support it anymore. It still works - people run it on current ComfyUI - but nobody's patching it if a future release breaks something. For a node this simple that's a low risk, just go in with eyes open.
Common issues
The gotcha that trips people isn't the node, it's the New Cycle button. When you press New Cycle to start a fresh loop, Cyclist walks the graph and bumps every filename and loop_id widget it can find - but it deliberately leaves Recall String's output value alone. So if you were relying on New Cycle to also reset the string flowing out of a Recall node, it won't. Reset that path yourself.
The other classic is a loop_id mismatch. Save under ForLoop_1, recall under ForLoop_2, and you'll silently read an empty slot and quietly fall back forever, wondering why nothing persists. Keep the IDs identical, and use Loop Manager to drive both ends from one source if you're tired of hand-syncing them.
And remember the volatility: restart ComfyUI mid-project and memory is wiped, so your next run starts from the fallback. That's by design - if you need the value to survive restarts, use a disk-backed node, not this one. Community reports on Postpos's Cyclist workflows note the score-and-compare loops can be finicky to tune (a comparison that reads "always right" or "always wrong"), so when a loop won't converge, check the comparison logic feeding your interrupt before blaming the memory cell - Recall String just hands back exactly what got saved.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| loop_id | STRING | ForLoop_1 | — |
| fallbackopt | STRING | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| STRING | STRING | — |