Runtime Toggle String Join (2)
Flip a prompt toggle mid-batch — Runtime Toggle String Join (2)
- text
The plain Toggle String Join nodes are queue snapshots: flip a toggle, queue, and the jobs already in line ignore you. Runtime Toggle String Join (2) is the same idea with the opposite philosophy - the toggle stays live, and each job reads the latest state at the moment it executes. Flip a switch while a queue is draining and the next image picks it up.
That's the one-sentence pitch, and it's worth sitting with for a second, because it's genuinely unusual. The pack's intended use is "long, pre-queued generation runs": queue a batch of jobs in advance, keep tweaking the prompt composition between jobs, and have the changes apply without re-queueing. This two-input version is the minimal way to test that workflow before you scale up to 10 sockets.
How the live state actually works
Under the hood there's a small state store on the ComfyUI server. When you click a toggle, the node's frontend sends the new mode and mask to a server route (/string_join_tools/runtime_state) keyed by a state_key. When the node executes, it reads that server-side state instead of trusting what was captured at queue time, then joins only the currently enabled non-empty strings. If live state isn't available - say, after a restart - it falls back to the saved queue-time values. The node even shows a subtle amber tint and a LIVE status so you know you're looking at a runtime node and not a snapshot one.
Two implementation details are worth knowing because they explain behavior you'll observe:
- It can't be cached. The node bakes a monotonically increasing revision number into its
IS_CHANGEDresult, so changing a toggle invalidates the cached join and forces downstream processing to redo. Toggle something, and the next execution reflects it. - Timing is "the next image onward." A change affects jobs whose Runtime Toggle Join hasn't executed yet. For normal image workflows, treat that as: the currently generating image finishes, then the change applies.
What you set
mode-multiple(each input independent) orsingle(zero or one enabled).- Per-row ON/OFF buttons - the actual control surface.
separator- default", ", with\n,\r\n,\t,\\escapes.state_key- normally auto-generated per node and best left alone. Set it manually only if you want two copies to control the same live state. The README's rule of thumb: use one active browser tab per workflow, since live state is shared by key.text_1,text_2- optionalSTRINGsockets. Output is onetextSTRING.
Installing it
ComfyUI Manager: search "String Join Tools" or "ComfyUI-StringJoinTools". Or:
cd ComfyUI/custom_nodes
git clone https://github.com/ruminar/ComfyUI-StringJoinTools
Restart and refresh. No Python dependencies, no models. Under String Join Tools.
The honest caveats
Live state lives in server memory and dies on a ComfyUI restart - a restart means the fallback saved values take over until you touch a toggle again. And if you're not running a queue, the live vs snapshot distinction barely matters: you'll get the same result either way, so this node's complexity only pays for itself on long runs. Keep that in mind before you reach for it; the snapshot variants are simpler and are the right call for most one-shot work.
Inputs (7)
| Name | Type | Default | Description |
|---|---|---|---|
| separator | STRING | , | Supports \n, \r\n, \t, and \\. |
| mode | COMBO | multiple | 2 options: multiple, single |
| enabled_mask | INT | 30–3 | — |
| selected_index | INT | 0-1–1 | — |
| state_key | STRING | — | |
| text_1opt | STRING | Optional queued STRING input. Its generated value is accepted or rejected at execution time by the live toggle. | |
| text_2opt | STRING | Optional queued STRING input. Its generated value is accepted or rejected at execution time by the live toggle. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| text | STRING | — |