Nodes/ComfyUI-GeN13/Text Concatenate (GeN13)
ComfyUI Node

Text Concatenate (GeN13)

Build a prompt out of boxes you can switch off

By heigen13·Created 24 days ago·Updated 12 days ago· 1
Text Concatenate (GeN13)
    • STRING
    • #01
    • #02
    • #03
    • #04
    • #05
    • #06
    • #07
    • #08
    • #09
    • #10
    • #11
    • #12
    • #13
    • #14
    • #15
    • #16
    • #17
    • #18
    • #19
    • #20
    ◄count2►
    ◄soloOFF►
    ◄delimiter, ►
    ◄on_01true►
    ◄text_01►
    ◄on_02true►
    ◄text_02►
    ◄on_03true►
    ◄text_03►
    ◄on_04true►
    ◄text_04►
    ◄on_05true►
    ◄text_05►
    ◄on_06true►
    ◄text_06►
    ◄on_07true►
    ◄text_07►
    ◄on_08true►
    ◄text_08►
    ◄on_09true►
    ◄text_09►
    ◄on_10true►
    ◄text_10►
    ◄on_11true►
    ◄text_11►
    ◄on_12true►
    ◄text_12►
    ◄on_13true►
    ◄text_13►
    ◄on_14true►
    ◄text_14►
    ◄on_15true►
    ◄text_15►
    ◄on_16true►
    ◄text_16►
    ◄on_17true►
    ◄text_17►
    ◄on_18true►
    ◄text_18►
    ◄on_19true►
    ◄text_19►
    ◄on_20true►
    ◄text_20►

    Your prompt is not one thing. It's a subject, a lighting block, a camera or style clause, the character's hair, and four lines of quality boilerplate you keep pasting from a notes file. It all lives in one big CLIP Text Encode box, so the only way to try the shot without the style clause is to delete it - and then type it back. That's the itch Text Concatenate (GeN13) scratches: it turns the prompt into a stack of boxes you can switch on and off, and joins the survivors into one string.

    In the plumbing taxonomy this is a repetition node - one of the two problems utility nodes exist to fight. Other packs concatenate strings too, but they make you chain nodes and wire them. This one is a single node with numbered rows, which is the difference between "I'll just retype it" and "I'll actually test the variant."

    How it joins the boxes

    Open the node's Python and the mechanism is almost boringly literal. count decides how many text_NN boxes are visible and joined; anything past it is hidden and ignored. Each box is trimmed of leading and trailing whitespace, and empty boxes are skipped entirely - so you never get , , , from a row you left blank. delimiter is text inserted between the surviving boxes, and the two escapes you'll actually use are \n (line break) and \t, converted literally in the code. Default is , .

    Each row has an on_NN boolean, labelled #01…#20 on the node. Turn it off and that box drops out of the join but its text is kept - flip it back on and your style clause returns intact. solo is the blunt instrument for the same job: pick #03 and the node outputs only box 3, without disturbing any switches. A solo above count quietly falls back to OFF.

    The front end does real work here: boxes that won't be joined are dimmed, a grey line at the bottom previews the exact string you're about to send, and the node grows to fit its text. Only the first count #NN outputs are kept and trimmed from the end, so wiring #03 doesn't move to another box when you lower count - and a box with a wire in it won't let count drop below it.

    The inputs and outputs that matter

    • count - 1 to 20. Start at 2, raise it as you split your prompt up.
    • delimiter - leave it at , for tag prompts. Use \n for the two-block style prompts where structure matters.
    • on_NN / text_NN - the boxes. Each one can also be fed by a link instead of typed into, which is how you mix a hand-written style block with a prompt an LLM node generated upstream.
    • solo - the "just show me this one clause" switch while you're iterating.

    One STRING output is the joined text; wire it into your CLIP Text Encode positive. The #01–#20 outputs each hand back that box's raw text regardless of switches or solo, which is handy when one clause also needs to go somewhere else - a filename, a caption node, a Show Any for eyeballing.

    Install

    ComfyUI Manager: search GeN13 and install, then restart. Manually:

    cd ComfyUI/custom_nodes
    git clone https://github.com/heigen13/ComfyUI-GeN13
    pip install -r ComfyUI-GeN13/requirements.txt
    

    That requirements file is one line - nvidia-ml-py, which the pack's GPU monitor strip uses to read NVML. Nothing this node needs. Run the pip line with ComfyUI's own Python if you're on the portable build (python_embeded\python.exe -m pip), or you can skip it entirely unless you want the monitor.

    Fair warning about the pack's profile: ComfyUI-GeN13 is small and new (GPL-3.0, © GeN's Studio Inc., source comments in Traditional Chinese, locales for zh-TW / zh-CN / ja). It has essentially no Reddit footprint, so you won't find troubleshooting threads - you read the source or nothing. Every node ends in (GeN13); double-click the canvas and type GeN13 to see the lot.

    Where people trip

    The delimiter is a single-line field, so pressing Enter commits it instead of inserting a line break - type the two characters \n and the node converts them.

    Second: OFF is not delete. Toggle a box off and it drops out of the output; the text is still in the box, waiting.

    Third: an empty selected box is not an error - solo on a blank row gives you an empty string into your encoder and nothing turns red, the same silent-blank behaviour as any empty prompt box in ComfyUI.

    And if your boxes look cramped on the newest frontend, note the README's own framing: built and tested on ComfyUI 0.40 with the classic canvas, Nodes 2.0 support stated for image previews. These text rows are DOM widgets, the part a frontend rewrite actually disturbs.

    CategoryGeN13/text

    Inputs (43)

    NameTypeDefaultDescription
    countINT21–20Box count: number of text boxes shown and joined; hidden boxes are not output.
    soloCOMBOOFFSolo: outputs only the chosen box without changing the box switches. OFF follows each box's switch.
    delimiterSTRING, Delimiter: text inserted between boxes; \n is a line break.
    on_01BOOLEANtrueInclude: OFF leaves this box out of the joined text; its content is kept.
    text_01STRINGText: type here or connect an upstream string. Empty boxes are skipped.
    on_02BOOLEANtrueInclude: OFF leaves this box out of the joined text; its content is kept.
    text_02STRINGText: type here or connect an upstream string. Empty boxes are skipped.
    on_03BOOLEANtrueInclude: OFF leaves this box out of the joined text; its content is kept.
    text_03STRINGText: type here or connect an upstream string. Empty boxes are skipped.
    on_04BOOLEANtrueInclude: OFF leaves this box out of the joined text; its content is kept.
    text_04STRINGText: type here or connect an upstream string. Empty boxes are skipped.
    on_05BOOLEANtrueInclude: OFF leaves this box out of the joined text; its content is kept.
    text_05STRINGText: type here or connect an upstream string. Empty boxes are skipped.
    on_06BOOLEANtrueInclude: OFF leaves this box out of the joined text; its content is kept.
    text_06STRINGText: type here or connect an upstream string. Empty boxes are skipped.
    on_07BOOLEANtrueInclude: OFF leaves this box out of the joined text; its content is kept.
    text_07STRINGText: type here or connect an upstream string. Empty boxes are skipped.
    on_08BOOLEANtrueInclude: OFF leaves this box out of the joined text; its content is kept.
    text_08STRINGText: type here or connect an upstream string. Empty boxes are skipped.
    on_09BOOLEANtrueInclude: OFF leaves this box out of the joined text; its content is kept.
    text_09STRINGText: type here or connect an upstream string. Empty boxes are skipped.
    on_10BOOLEANtrueInclude: OFF leaves this box out of the joined text; its content is kept.
    text_10STRINGText: type here or connect an upstream string. Empty boxes are skipped.
    on_11BOOLEANtrueInclude: OFF leaves this box out of the joined text; its content is kept.
    text_11STRINGText: type here or connect an upstream string. Empty boxes are skipped.
    on_12BOOLEANtrueInclude: OFF leaves this box out of the joined text; its content is kept.
    text_12STRINGText: type here or connect an upstream string. Empty boxes are skipped.
    on_13BOOLEANtrueInclude: OFF leaves this box out of the joined text; its content is kept.
    text_13STRINGText: type here or connect an upstream string. Empty boxes are skipped.
    on_14BOOLEANtrueInclude: OFF leaves this box out of the joined text; its content is kept.
    text_14STRINGText: type here or connect an upstream string. Empty boxes are skipped.
    on_15BOOLEANtrueInclude: OFF leaves this box out of the joined text; its content is kept.
    text_15STRINGText: type here or connect an upstream string. Empty boxes are skipped.
    on_16BOOLEANtrueInclude: OFF leaves this box out of the joined text; its content is kept.
    text_16STRINGText: type here or connect an upstream string. Empty boxes are skipped.
    on_17BOOLEANtrueInclude: OFF leaves this box out of the joined text; its content is kept.
    text_17STRINGText: type here or connect an upstream string. Empty boxes are skipped.
    on_18BOOLEANtrueInclude: OFF leaves this box out of the joined text; its content is kept.
    text_18STRINGText: type here or connect an upstream string. Empty boxes are skipped.
    on_19BOOLEANtrueInclude: OFF leaves this box out of the joined text; its content is kept.
    text_19STRINGText: type here or connect an upstream string. Empty boxes are skipped.
    on_20BOOLEANtrueInclude: OFF leaves this box out of the joined text; its content is kept.
    text_20STRINGText: type here or connect an upstream string. Empty boxes are skipped.

    Outputs (21)

    NameTypeDescription
    STRINGSTRINGText: the enabled boxes joined in order with the delimiter.
    #01STRINGText: this box's content, regardless of its switch and solo.
    #02STRINGText: this box's content, regardless of its switch and solo.
    #03STRINGText: this box's content, regardless of its switch and solo.
    #04STRINGText: this box's content, regardless of its switch and solo.
    #05STRINGText: this box's content, regardless of its switch and solo.
    #06STRINGText: this box's content, regardless of its switch and solo.
    #07STRINGText: this box's content, regardless of its switch and solo.
    #08STRINGText: this box's content, regardless of its switch and solo.
    #09STRINGText: this box's content, regardless of its switch and solo.
    #10STRINGText: this box's content, regardless of its switch and solo.
    #11STRINGText: this box's content, regardless of its switch and solo.
    #12STRINGText: this box's content, regardless of its switch and solo.
    #13STRINGText: this box's content, regardless of its switch and solo.
    #14STRINGText: this box's content, regardless of its switch and solo.
    #15STRINGText: this box's content, regardless of its switch and solo.
    #16STRINGText: this box's content, regardless of its switch and solo.
    #17STRINGText: this box's content, regardless of its switch and solo.
    #18STRINGText: this box's content, regardless of its switch and solo.
    #19STRINGText: this box's content, regardless of its switch and solo.
    #20STRINGText: this box's content, regardless of its switch and solo.