Text Concatenate (Dynamic)
A Text Joiner That Grows Its Own Inputs
- text
Stock ComfyUI's text-join story has always been a bit clumsy: a fixed handful of inputs, and when you need a sixth slot you're mutating the node. Text Concatenate (Dynamic) fixes the annoying part - it starts with two slots, and the moment you type into the last one, another slot appears. Up to 64 of them. Remove the text and the unused slots tidy themselves up. It's a small quality-of-life win, but it's the exact kind of thing that keeps a big prompt-building graph from turning into node surgery every five minutes.
How it works
The inputs you actually interact with: text_1, text_2, and so on - up to text_64. Type into the last visible slot and a new one grows; clear the trailing slots and they drop off. Behind the scenes the node collects every non-empty text slot, sorts them in order, and joins them with your separator.
The three controls:
separator- what goes between pieces, default", ". Change it to a newline or" + "if you're building something that isn't a comma-prompt.strip_inputs(default on) - trims leading/trailing whitespace off each piece before joining.skip_empty(default on) - drops empty slots from the result entirely, so a half-filled chain doesn't leave, ,artifacts.
With separator = ", ", strip_inputs and skip_empty on, and text_1 = masterpiece, text_2 = 1girl, text_3 = blue hair, you get masterpiece, 1girl, blue hair - no trailing comma, no double separators.
There's also a text STRING output (the joined result), which is what you wire into a text encoder or into the pack's sibling Normalize Comma Prompt if you want a final formatting pass.
Install
It ships in Ye0l/ComfyUI-KSTR-Nodes:
cd ComfyUI/custom_nodes
git clone https://github.com/Ye0l/ComfyUI-KSTR-Nodes
or search "ComfyUI-KSTR-Nodes" in ComfyUI Manager, then restart. The auto-growing slots need the pack's small JavaScript file (web/text_concatenate.js), which loads automatically because the pack declares a web directory - so as long as you restarted after installing, you get the dynamic behavior for free. No Python dependencies.
Where people get burned
Two small things. First, the dynamic-slot trick is a UI feature - the node itself exposes all 64 text inputs regardless, so if you're driving ComfyUI through its API you can still pass any of them; only the visual auto-grow needs the frontend. Second, this node is part of a very young pack (one commit, essentially no community footprint yet), so if a slot ever behaves oddly, check that the web directory actually loaded - a missing WEB_DIRECTORY shows up as slots that never appear. For day-to-day prompt assembly it's otherwise exactly what it says: concatenate, strip, skip, done.
Inputs (67)
| Name | Type | Default | Description |
|---|---|---|---|
| separator | STRING | , | — |
| strip_inputs | BOOLEAN | true | — |
| skip_empty | BOOLEAN | true | — |
| text_1opt | STRING | — | |
| text_2opt | STRING | — | |
| text_3opt | STRING | — | |
| text_4opt | STRING | — | |
| text_5opt | STRING | — | |
| text_6opt | STRING | — | |
| text_7opt | STRING | — | |
| text_8opt | STRING | — | |
| text_9opt | STRING | — | |
| text_10opt | STRING | — | |
| text_11opt | STRING | — | |
| text_12opt | STRING | — | |
| text_13opt | STRING | — | |
| text_14opt | STRING | — | |
| text_15opt | STRING | — | |
| text_16opt | STRING | — | |
| text_17opt | STRING | — | |
| text_18opt | STRING | — | |
| text_19opt | STRING | — | |
| text_20opt | STRING | — | |
| text_21opt | STRING | — | |
| text_22opt | STRING | — | |
| text_23opt | STRING | — | |
| text_24opt | STRING | — | |
| text_25opt | STRING | — | |
| text_26opt | STRING | — | |
| text_27opt | STRING | — | |
| text_28opt | STRING | — | |
| text_29opt | STRING | — | |
| text_30opt | STRING | — | |
| text_31opt | STRING | — | |
| text_32opt | STRING | — | |
| text_33opt | STRING | — | |
| text_34opt | STRING | — | |
| text_35opt | STRING | — | |
| text_36opt | STRING | — | |
| text_37opt | STRING | — | |
| text_38opt | STRING | — | |
| text_39opt | STRING | — | |
| text_40opt | STRING | — | |
| text_41opt | STRING | — | |
| text_42opt | STRING | — | |
| text_43opt | STRING | — | |
| text_44opt | STRING | — | |
| text_45opt | STRING | — | |
| text_46opt | STRING | — | |
| text_47opt | STRING | — | |
| text_48opt | STRING | — | |
| text_49opt | STRING | — | |
| text_50opt | STRING | — | |
| text_51opt | STRING | — | |
| text_52opt | STRING | — | |
| text_53opt | STRING | — | |
| text_54opt | STRING | — | |
| text_55opt | STRING | — | |
| text_56opt | STRING | — | |
| text_57opt | STRING | — | |
| text_58opt | STRING | — | |
| text_59opt | STRING | — | |
| text_60opt | STRING | — | |
| text_61opt | STRING | — | |
| text_62opt | STRING | — | |
| text_63opt | STRING | — | |
| text_64opt | STRING | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| text | STRING | — |