CSVWildcardNode
The wildcard node that keeps a monster's color, size and texture in sync
- STRING
Most wildcard setups in ComfyUI treat every prompt slot as independent. That's the whole point of the {a|b|c} bracket trick and Impact Pack's __wildcard__ syntax - you batch 32 runs and get 32 different combinations. But independent is exactly the problem when your prompt has relationships. "A {color} monster with {size} feet" will happily hand you a red monster with tiny feet on one run and a blue one with giant feet on the next. CSVWildcardNode exists to fix that one thing: it pulls related terms from the same CSV row, so your monsters stay coherent.
It's the star of the tiny comfyui-csvwildcards pack, and honestly it's the only reason most people install the pack at all.
How it works
You write a prompt template with two kinds of placeholders:
{animal}- grabs a random non-empty line fromdata/animal.txt{csv:monster:color}- grabs a random row fromdata/monster.csvand uses thecolorcolumn
Here's the trick: every {csv:monster:...} reference in the same prompt run pulls from the same randomly-chosen row. So "The {csv:monster:color} creature was {csv:monster:size}" gives you red + large, blue + small, and never a mix. The code groups all CSV placeholders by file, picks one row per file, caches it, and substitutes. Regular text wildcards still pick independently, so you get variety where variety is fine and consistency where it matters.
Mechanically it's pure Python stdlib - random, csv, re. No models, no pip dependencies, no magic. A name can be a .txt, a .csv, and a directory all at once: {name} uses the txt, {csv:name:column} uses the csv, {name/file} digs into the directory.
The inputs that matter
- prompt_template - the multiline template. It's the whole point; everything else is gravy.
- seed (optional) - an integer that seeds Python's RNG. Same seed, same substitutions, guaranteed.
One gotcha that isn't obvious: the seed ships with a default of 0. The README promises random picks when it's unconnected, but the code seeds random.Random(seed) with whatever it receives, so in practice you'll get the same selection on repeat runs until you change the value. If you came here for shuffle, feed it a varying seed.
The single output is a STRING - wire it straight into a CLIP Text Encode node's prompt input, or anywhere else that eats text.
Installing it
Two ways, both standard:
cd ComfyUI/custom_nodes
git clone https://github.com/illuminatianon/comfyui-csvwildcards.git
…then restart ComfyUI. Or skip the terminal and search "CSV Wildcard Node for ComfyUI" in ComfyUI Manager. There's no requirements.txt and nothing to download - for once, no dependency hell to report.
The data folder
Your files live in ComfyUI/custom_nodes/comfyui-csvwildcards/data/. Subdirectories of any depth work, but use forward slashes in placeholders even on Windows: {pokemon/gen1/types}. CSV files need a header row; column names are case-insensitive and get lowercased with spaces stripped. Missing files are skipped silently.
Where people get burned
The big one: an unresolved placeholder is left in the prompt literally. {monster} that doesn't resolve to a file gets encoded into your actual prompt as the text {monster}, and CLIP Text Encode won't complain. No error, just silently worse results. That silent-keep behavior is the author's debugging feature, but it means you should verify what the node actually output - wire it into a text display node for a run and look.
Also manage expectations: this is a small, quiet pack with a tiny footprint in the community. For plain independent randomization, the better-known packs cover you. CSVWildcardNode earns its spot precisely when row-level consistency is the whole ask - character reference libraries, creature rosters, anything where a batch should stay internally coherent.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| prompt_template | STRING | The {csv:monster:color} {animal}-like monster has {csv:monster:size} {appendage} with a {csv:monster:texture} texture. | — |
| seedopt | INT | 00–18446744073709550000 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| STRING | STRING | — |