ND Pack Parameters
Twelve wires become one, and that's both the feature and the trap
- in_1
- in_2
- in_3
- in_4
- in_5
- in_6
- in_7
- in_8
- in_9
- in_10
- in_11
- in_12
- in_13
- in_14
- in_15
- in_16
- in_17
- in_18
- in_19
- in_20
- in_21
- in_22
- in_23
- in_24
- in_25
- in_26
- in_27
- in_28
- in_29
- in_30
- in_31
- in_32
- in_33
- in_34
- in_35
- in_36
- in_37
- in_38
- in_39
- in_40
- in_41
- in_42
- in_43
- in_44
- in_45
- in_46
- in_47
- in_48
- in_49
- in_50
- in_51
- in_52
- in_53
- in_54
- in_55
- in_56
- in_57
- in_58
- in_59
- in_60
- in_61
- in_62
- in_63
- in_64
- params
There's a reason every serious plumbing pack eventually ships a bundle node: past about thirty nodes, a ComfyUI graph stops being a diagram and becomes noodles. One wire carrying a dozen named values fixes the readability problem - and creates a subtler one. More on that below.
What it is
ND Pack Parameters collects values into a single wire of type ND_PARAMS. Under the hood that's an ordered {name: value} mapping - literally a dict subclass - so nothing is serialised or converted. Values are held and handed on.
The clever part is what a Pack looks like depending on where it's going. Wire its output into another node of this pack and the Pack reconfigures itself into exactly the inputs that node expects, typed, with the right names. Wire a Pack into ND Variant Preview Selector and you get images and an optional image pin, because that's what the selector wants. Into ND Character Builder and you get a seed pin. It's not a generic "one input, add more" box - it's a box that learns the contract of its consumer.
With no such consumer, it falls back to general mode: a new input appears as soon as you connect the last one, each field takes the name of the connected output, and renaming an input renames its field. Optional inputs are drawn as hollow circles.
The inputs and outputs
There's no required input at all, which is unusual and correct:
in_1…in_64(*, all optional) - the values. Up to 64 fields.names(STRING, default[]) - a machine-written list of{slot, name}pairs. You never type in this; the browser fills it as you rename pins. It's what lets the server name the fields without a browser.
Output: params (ND_PARAMS) - the bundle.
Two behaviours worth knowing. Duplicate names are tolerated rather than fatal: the pack logs a warning and the last one wins, which is why renaming a pin to something already in use quietly produces one field instead of two. And bundles nest - a field can itself be an ND_PARAMS, which is how ND Load Images hands you Image 1 Parameters as a sub-bundle you open with a second Unpack.
The honest downside
This is a pack-local bus. It doesn't talk to rgthree's Context, to Efficiency's Dependency pipe, or to Easy-Use's pipe dict - every one of those packs invented its own type, and none of them interoperate. Adopt this one and that part of your workflow is married to Neural Dreamer Nodes. For a workflow you share, that's a real cost: the recipient now needs this pack installed, and if they already use rgthree Context they'll have two bundle patterns in one graph.
The failure mode is imported wholesale from every bundle design: stale contents with an intact connection. With twelve wires you can see at a glance that your LoRA output isn't going to the sampler. With one wire, the connection is there and the content is wrong - you unpacked model from a bundle assembled before the patch node. Debugging that means unpacking the bundle and reading it, which is exactly what ND Show Any As Text is for.
So: reach for it when the wire count is the actual problem, not because it looks tidy. Keep explicit wires in the region you're actively iterating.
Install
Part of Neural Dreamer Nodes (v1.1.0, MIT). No Python dependencies - the pyproject.toml dependency list is empty, there's no requirements.txt, nothing to download.
cd ComfyUI/custom_nodes
git clone https://github.com/neural-dreamer/ComfyUI-NeuralDreamer-Nodes.git
Restart and refresh the tab. In ComfyUI Manager, search "Neural Dreamer Nodes".
Common issues
Pack shows one input and won't grow. Its output isn't connected yet. General mode only grows a new pin after the last one is used; connect the output first and it'll take a shape.
Pack shows inputs I can't fill. Those are the consumer's fields, drawn as hollow circles when optional. If a node in the pack wants images and image, you get both pins whether or not you intend to use image.
"Unpack gives me nothing." Unpack builds its outputs by tracing the wire back to whatever produced the bundle. If the source is a node it doesn't recognise - a different pack's bundle type, or a subgraph boundary it can't see through - it falls back to generic out_N names. Reroutes and subgraphs are followed; genuinely foreign bundle types aren't.
Searching for it is annoying. It's called "Pack" in the node list on purpose: drag a parameters wire into empty space and Pack / Unpack are the first suggestions. That's the intended gesture, not a hidden feature.
Order of fields changed. Fields come out in the order the browser wrote them into names, which follows the pins. Renaming reorders nothing; rewiring can.
Inputs (65)
| Name | Type | Default | Description |
|---|---|---|---|
| in_1opt | * | — | |
| in_2opt | * | — | |
| in_3opt | * | — | |
| in_4opt | * | — | |
| in_5opt | * | — | |
| in_6opt | * | — | |
| in_7opt | * | — | |
| in_8opt | * | — | |
| in_9opt | * | — | |
| in_10opt | * | — | |
| in_11opt | * | — | |
| in_12opt | * | — | |
| in_13opt | * | — | |
| in_14opt | * | — | |
| in_15opt | * | — | |
| in_16opt | * | — | |
| in_17opt | * | — | |
| in_18opt | * | — | |
| in_19opt | * | — | |
| in_20opt | * | — | |
| in_21opt | * | — | |
| in_22opt | * | — | |
| in_23opt | * | — | |
| in_24opt | * | — | |
| in_25opt | * | — | |
| in_26opt | * | — | |
| in_27opt | * | — | |
| in_28opt | * | — | |
| in_29opt | * | — | |
| in_30opt | * | — | |
| in_31opt | * | — | |
| in_32opt | * | — | |
| in_33opt | * | — | |
| in_34opt | * | — | |
| in_35opt | * | — | |
| in_36opt | * | — | |
| in_37opt | * | — | |
| in_38opt | * | — | |
| in_39opt | * | — | |
| in_40opt | * | — | |
| in_41opt | * | — | |
| in_42opt | * | — | |
| in_43opt | * | — | |
| in_44opt | * | — | |
| in_45opt | * | — | |
| in_46opt | * | — | |
| in_47opt | * | — | |
| in_48opt | * | — | |
| in_49opt | * | — | |
| in_50opt | * | — | |
| in_51opt | * | — | |
| in_52opt | * | — | |
| in_53opt | * | — | |
| in_54opt | * | — | |
| in_55opt | * | — | |
| in_56opt | * | — | |
| in_57opt | * | — | |
| in_58opt | * | — | |
| in_59opt | * | — | |
| in_60opt | * | — | |
| in_61opt | * | — | |
| in_62opt | * | — | |
| in_63opt | * | — | |
| in_64opt | * | — | |
| namesopt | STRING | [] | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| params | ND_PARAMS | — |