Nodes/DarkPrompts/Dark Prompt
ComfyUI Node

Dark Prompt

The prompt randomizer that re-reads your wildcard files without a restart

By darkpixel·Created 3 years ago·Updated about a year ago· 11
Dark Prompt
    • string
    strip_blank_linestrue
    strip_commentstrue
    randomly_disabletrue
    seed0
    filename
    prefix
    suffix
    text
    combine_with
    combine_with_delimiter

    DarkPrompt is the flagship of the DarkPrompts pack, and it does one thing that a surprising number of prompt-randomizer nodes get wrong: it re-reads its file on every generation. Edit your wildcard file, hit queue, and the new lines are live. No restart, no "clear cache" ritual. That single behavior is why people stick with it.

    The idea is older than ComfyUI. Prompt variety - batch 30 images where the clothing, location or camera changes each time - goes back to A1111's {a|b|c} syntax and Impact Pack's __wildcard__ files. DarkPrompt is the standalone version: it reads lines from a text file, a text box, or both, and picks one at random per generation, seeded so you can reproduce exactly what you got.

    How it works

    Give it a filename (a plain path string, more on that below), text, or both. It merges the lines, optionally strips # and // comments and blank lines, then seeds Python's random with the seed input and does a random.choice. The output is a STRING you wire into a CLIP Text Encode or into another DarkPrompt.

    Two behaviors are worth understanding before you use it:

    • randomly_disable defaults to ON. This is the trap. With it on, each generation has a coin flip on whether the node returns nothing at all. That's the intended use - an "optional section" of prompting you only sometimes want, like shoes on a character - but if you just want a reliable wildcard, flip it off or every other image silently lacks that part of the prompt. The source deliberately doesn't use your seed for this flip, so all your DarkPrompts don't disable in lockstep.
    • prefix and suffix wrap the chosen line. The README's example is the good one: a prefix of ( and a suffix of :1.2) turns the file line walking a dog into (walking a dog:1.2), which is exactly the weight syntax the CLIP encoder expects.

    Chaining them

    You don't need a separate combiner node. Feed one DarkPrompt's output into the next one's combine_with input, set combine_with_delimiter to \n, and each node adds its line to the growing prompt. Because each is seeded independently, you get a different combination on every queue - same architecture as the {a|b|c} trick, but each section lives in its own editable file. If a file ends up empty, the node falls back to returning whatever combine_with was holding, so one dead list doesn't nuke the whole chain.

    The inputs that matter

    • seed (INT, wireable) - reproducibility. Same seed, same file, same pick.
    • filename (STRING) - a plain text path, not a file picker. Give it an absolute path or a path relative to your ComfyUI working directory; relative paths silently fail to find the file otherwise.
    • text - inline lines as an alternative to (or in addition to) a file.
    • strip_comments, strip_blank_lines - keep both on; comment lines starting with # or // are your way to annotate a list without polluting the prompt.

    Install & troubleshooting

    ComfyUI Manager → search "DarkPrompts" → install, restart. Or clone it straight in:

    cd ComfyUI/custom_nodes
    git clone https://github.com/darkpixel/darkprompts.git
    

    Then restart ComfyUI. No models, no extra pip dependencies - it's pure Python on the ComfyUI API.

    The classic failure modes: "DarkPrompt text and filename can not both be blank" means you wired nothing in; a file that won't load is almost always a path problem, and it raises a clear FileNotFoundError telling you exactly what it tried to open. And if an output looks "wrong," check randomly_disable first - it's the node lying to you by design.

    CategoryDarkPrompt

    Inputs (10)

    NameTypeDefaultDescription
    strip_blank_linesBOOLEANtrue
    strip_commentsBOOLEANtrue
    randomly_disableBOOLEANtrue
    seedINT00–18446744073709550000
    filenameoptSTRING
    prefixoptSTRING
    suffixoptSTRING
    textoptSTRING
    combine_withoptSTRING
    combine_with_delimiteroptSTRING

    Outputs (1)

    NameTypeDescription
    stringSTRING