π€ Text Concatenate
Build a filename (or a prompt) out of 99 sockets
- texts
- Output
ComfyUI's core has no join node. You can concatenate two strings with a Text Concatenate-ish node from a couple of packs, but they all stop at two or three inputs, which is useless the moment you want a filename made of a model, a sampler, a step count and a seed. This one gives you up to 99 sockets that grow as you connect them, plus the separator and whitespace handling that filenames need.
How it works
The Texts input is an autogrow socket group: one socket to start, and connecting it spawns the next, up to 99 (Text Input 01 through Text Input 99). Connect in order, because the order of the sockets is the order of the join - there's no sorting, no naming, just slot order.
Then it assembles: the Global Prefix first (if non-empty), then each connected value, then the Global Suffix - all joined with the Separator. A connected channel that's completely empty is dropped when Skip Empty Inputs is on (the default), so a missing value doesn't leave a double separator in the middle of your nice filename. Channels you never connected are always ignored, regardless of that toggle.
The part that surprises everyone is Replace With, which defaults to _ and performs a whitespace substitution on every channel: re.sub(r'\s+', '_', value). So the prompt a photo of a cat becomes a_photo_of_a_cat. For filenames that's exactly right. For building a prompt out of parts - which is the other obvious use - it's wrong, and the fix is counterintuitive: type a single space into the field. The code special-cases that (if replace_whitespaces_with != " "), and with a space it leaves your text alone; combined with Trim Whitespaces on, it collapses runs of spaces to one.
Case Mode is applied to the final joined string, prefix and suffix included: Keep Original, UPPERCASE, lowercase, or Capitalize Each Word. Four options, and yes, UPPERCASE will shout your prefix too.
The inputs and outputs that matter
Set these five and ignore the rest: Separator (_ default - good for names, use , for prompts), Replace With as discussed, Global Prefix / Global Suffix for a run tag or file extension, Skip Empty Inputs on, Case Mode as needed.
One output: Output, a STRING. Its two natural destinations are Save Image's filename (base name; the counter is appended for you) and Path Join, if you want the full path assembled rather than just the leaf.
The filename pattern this node was clearly built for:
Text: "sdxl_base" ββ
Text: "dpmpp_2m" ββ€
Primitive: steps 30 ββΌβ Text Concatenate β Save Image.filename
Text: "cfg7" ββ€
seed from the sampler ββ
with separator _, prefix empty, suffix empty. You get sdxl_base_dpmpp_2m_30_cfg7_1234567890_00001.png and every part of it is data, so the name is true by construction. Get the order wrong and you'll still get a valid filename, just a less useful one - which is the worst case of a naming scheme, honestly.
For prompts, switch separator to , and Replace With to a single space, and it becomes a legible prompt assembler that respects your commas.
How to install it
Part of Avaray/honda-nodes - ComfyUI Manager β Node Pack β search Honda Nodes β Install β restart. Manual:
cd ComfyUI/custom_nodes
git clone --depth 1 https://github.com/Avaray/honda-nodes.git
cd honda-nodes
python install.py
Nothing in the installer is needed for this node; it exists to fetch jq and ime for the pack's JSON and metadata nodes. Requires ComfyUI 0.38.0 or newer, because the autogrow input type is part of the V3 schema API - on an older build the node won't load at all.
Common issues
Underscores everywhere in my prompt. The _ default on Replace With. Change it to a single space character.
Extra separators in the middle. A connected channel that's empty and Skip Empty Inputs turned off - the node faithfully joins the empty string. Leave the toggle on.
The sockets won't multiply. The autogrow widget adds the next socket when the last one is connected; it needs the frontend to be current (this pack pins a recent ComfyUI frontend package). Hard-reload the browser after updating.
Only the first channel shows up in the output. The others aren't connected - the widget renders but an unwired slot contributes nothing, silently.
Capitalize Each Word mangles your text. It's str.title(), which uppercases the letter after every non-letter. don't becomes Don'T. Use Keep Original and capitalise by hand where it matters.
A value with a newline in it. Multi-line text is passed through and the newline stays, so a pasted multi-line prompt becomes a multi-line filename. Turn on Trim Whitespaces and use Text Replace to strip newlines first.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| case_mode | COMBO | Keep Original | Changes the capitalization of the entire final output. 'Capitalize Each Word' will make the first letter of every word uppercase. |
| separator | STRING | _ | Text inserted between each connected text channel (and also before the suffix and after the prefix). |
| replace_whitespaces_with | STRING | _ | Symbol to replace whitespaces with. By default it uses an underscore. To disable this and keep spaces, type a single space here. |
| global_prefix | STRING | Text added to the very beginning of the final string. The separator will be placed between this prefix and the first text channel. | |
| global_suffix | STRING | Text added to the very end of the final string. The separator will be placed between the last text channel and this suffix. | |
| skip_empty | BOOLEAN | true | If enabled, ignores any connected text channels that are completely empty so they don't produce extra separators. |
| trim_whitespaces | BOOLEAN | false | If enabled, automatically removes extra spaces from the beginning and end of each text channel, and collapses multiple spaces into a single space before joining them. |
| texts | COMFY_AUTOGROW_V3 | Connect text outputs to these slots. They will be combined in order. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| Output | STRING | β |