StepReplace [m9]
Search-and-Replace for Prompts, With Dice in It
- text
Core ComfyUI has a Replace Text node and it's fine - one find, one swap. StepReplace [m9] is what you want when the prompt is a template: five chained replacements applied top to bottom, plus { rose | tulip | peony } choices that collapse to one option at random. Write [SUBJECT] wearing [OUTFIT], standing in [PLACE] once, then swap the placeholders per workflow, or let the node pick from short lists so every run in a batch comes out slightly different.
It's the pack's least glamorous node and the one I'd put in a randomizer workflow first, because it gives you control the wildcard packs don't: the substitution list is right there in the node, not in a text file you have to maintain.
How it works
Each step rewrites the result of the step before it, so a later search can match text an earlier replacement produced - flower → rose on step one, then rose → red rose on step two, and you get "a red rose in a vase". An empty search is skipped, so you use only as many of the five as you need, and an empty replace deletes the term.
Matching is literal and case-insensitive, with a subtlety that's actually useful. A word boundary is added only at an end whose character is a letter, digit or underscore - so cat does not find the cat inside category, but [FIND_THIS] or <lora:foo:0.8> matches wherever it appears, brackets and all. Every occurrence is replaced, not just the first.
Choices are the interesting part. { one | two | three } collapses to one option; options are trimmed, so {a|b} and { a | b } behave identically; an empty option ({ a | }) is a legal way to sometimes pick nothing; choices nest; and each occurrence draws its own option, so one replacement used three times can give you three different flowers. Braces without a | are left alone, and \{, \|, \} give you literal characters. Choices are resolved as the text is built, not at the end - which is why the second step in that flower example only fires on the runs where rose actually came up.
The fields
- text - an input socket. The text lives upstream in a PrimitiveString or another prompt node; this node only rewrites it.
- search_1 / replace_1 … search_5 / replace_5 - five pairs.
searchis a single line,replaceis multi-line, which is handy when a substitution is a paragraph. - print_output - prints what each step did (including
'x' not found, which is the fastest way to debug a step that isn't firing) and the final text. - seed_optional - and here the pack inverts its own convention, deliberately.
Output: text (STRING). Into a CLIP Text Encode, a preview node, or another text node.
Seeding, because it's the opposite of the rest of the pack
On the other m9 nodes, an unconnected seed means 0, which means deterministic and cached - you get one variation forever. StepReplace flips that: 0 here means no seed given, so it draws from entropy and re-executes on every queue instead of serving a cached result. That's what makes the example workflow in the repo work - it uses { ... } choices with an incrementing seed and gets a new pick each run out of the box.
So: default behaviour is "roll every time". Give it any non-zero seed and the run becomes fully reproducible, which is what you want the moment you get a keeper and need the same prompt again. The sensible habit is an incrementing seed primitive rather than a randomize one - same fresh variation, but the number in the box is the one that actually ran, so the log is enough to recover it.
A worked example
text: a flower in a vase
search_1 flower replace_1 { rose | tulip | dried lavender }
search_2 rose replace_2 red rose, { two | three } blooms
search_3 vase replace_3 cracked ceramic vase
Run it twice and you'll get a red-rose branch, a tulip branch, and occasionally a dried lavender branch where step 2 does nothing at all because rose never appeared. That last case is the one people don't anticipate: a step with zero matches is silent unless print_output is on.
Installing it
ComfyUI Manager → search m9-prompts-comfyui → install; or:
cd ComfyUI/custom_nodes
git clone https://github.com/MarcusNyne/m9-prompts-comfyui
Then restart ComfyUI. No requirements.txt, no downloads, nothing compiled - the pack is stdlib Python plus torch/numpy/Pillow, which you already have. StepReplace is filed under the text category, next to the stock Replace Text node. There's also an embedded workflow in the repo's examples folder (StepReplace_TextPreview_m9.png) you can drag straight in if you'd rather start from a working graph than a blank canvas.
Inputs (13)
| Name | Type | Default | Description |
|---|---|---|---|
| text | STRING | — | |
| search_1 | STRING | — | |
| replace_1 | STRING | — | |
| search_2 | STRING | — | |
| replace_2 | STRING | — | |
| search_3 | STRING | — | |
| replace_3 | STRING | — | |
| search_4 | STRING | — | |
| replace_4 | STRING | — | |
| search_5 | STRING | — | |
| replace_5 | STRING | — | |
| print_output | BOOLEAN | false | — |
| seed_optionalopt | INT | 00–18446744073709550000 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| text | STRING | — |