Node Controller [BETA]
One node to bypass or mute a dozen — a master switchboard for your graph
There's a moment in every serious ComfyUI workflow where the graph gets too big to reason about and you start wanting a cockpit instead of a canvas. DA_NodeController is that cockpit for node-level on/off. It's a single node that lets you bypass or mute specific nodes - or batches of them - from a row of labeled toggles, live, with zero re-queueing. The group version of this same idea lives in DA_GroupController; this one targets individual nodes.
It ships in DemonAlone-JS_Addon-ComfyUI, the JS-focused companion pack to the author's main DemonAlone-nodes repo, and it's explicitly based on the AUNMultiUniversal node from AUN-ComfyUI-Nodes. It's one of those "I got tired of right-clicking 14 nodes" tools - the pack is mostly that philosophy: responsive UI work in the browser, not in Python.
How it works
Like its group sibling, the Python half is a thin layer. It reads your slots, splits the targets strings on commas and semicolons, and passes two lists to the frontend: IDs/titles that should be active and ones that shouldn't. The JS then walks the actual graph and flips each matched node's mode to ALWAYS, BYPASS, or NEVER.
Two targeting modes, set per slot via target_type_N:
- ID - matches the node's numeric ID exactly. Stable per workflow, precise, but you have to know the numbers (hover or check the workflow JSON).
- Title - matches the node's display title with a case-insensitive substring match.
denoisewill hit a node titled "KSampler denoise pass". Fuzzier, easier to remember.
Because IS_CHANGED is always false, flipping a switch doesn't mark the graph dirty and doesn't fire a run. You're just editing state, which is what makes it feel like a hardware panel rather than an edit operation.
The inputs that matter
The top-level trio is shared with the group controller: mode (Bypass or Mute - how "off" behaves), slot_count (1–20 rows, 3 default), and toggle_restriction (default, max one for radio-button A/B, always one to guarantee at least one slot stays on). AllSwitch turns everything on at once; show_AllSwitch keeps that toggle visible in compact mode.
Each slot gets four fields, and the only one you genuinely need to fill is targets_N - node IDs or titles, comma or semicolon separated, with target_type_N choosing how they're interpreted. label_N is just a caption for the row. switch_N is the actual toggle. There are no outputs; it's a OUTPUT_NODE control panel, not a data node.
Installing it
Same as any pack in this repo:
cd ComfyUI/custom_nodes
git clone https://github.com/DemonAlone/DemonAlone-JS_Addon-ComfyUI
Or search "DemonAlone-JS_Addon-ComfyUI" in ComfyUI Manager and hit install. Restart, and it appears under Node Control. No models, no pip dependencies.
Where people get burned
The Title substring match is both the feature and the trap: a title that contains another title's text will catch both. If you have "denoise" and "denoise final", one slot targeting denoise grabs both. Be more specific, or switch that slot to ID targeting.
Also remember it only controls nodes present in the graph when you toggle. Nodes you add later with matching titles won't be affected until you toggle again - and since toggling is a live event rather than an execution, the change applies to what's on the canvas at that moment. It's a workflow-organizing tool, not a save-file validator. Name things deliberately, and this thing genuinely feels like magic the first time you A/B two upscale paths with a single click.
Inputs (85)
| Name | Type | Default | Description |
|---|---|---|---|
| modeopt | COMBO | Bypass | Choose how to disable nodes: Bypass (🔴) or Mute (🔇). |
| slot_countopt | INT | 31–20 | Number of control slots to show (1-20). |
| toggle_restrictionopt | COMBO | default | Logic for toggles: 'max one' allows only one active, 'always one' ensures at least one is active. |
| AllSwitchopt | BOOLEAN | false | ON = all groups active (🟢). OFF = use individual group switches. |
| show_AllSwitchopt | BOOLEAN | false | Show the AllSwitch toggle even in compact mode. |
| label_1opt | STRING | Descriptive label for slot 1 (other slots follow the same layout). | |
| targets_1opt | STRING | 0 | Target node IDs or Titles for slot 1 (comma or semicolon separated). Example: '123, 456' or 'upscale; denoise'. |
| switch_1opt | BOOLEAN | false | Toggle state for slot 1. 🟢 = active, 🔴 = controlled by mode. |
| target_type_1opt | COMBO | ID | Targeting method for slot 1: ID (numeric) or Title (display name). |
| label_2opt | STRING | — | |
| targets_2opt | STRING | 0 | — |
| switch_2opt | BOOLEAN | false | — |
| target_type_2opt | COMBO | ID | 2 options: ID, Title |
| label_3opt | STRING | — | |
| targets_3opt | STRING | 0 | — |
| switch_3opt | BOOLEAN | false | — |
| target_type_3opt | COMBO | ID | 2 options: ID, Title |
| label_4opt | STRING | — | |
| targets_4opt | STRING | 0 | — |
| switch_4opt | BOOLEAN | false | — |
| target_type_4opt | COMBO | ID | 2 options: ID, Title |
| label_5opt | STRING | — | |
| targets_5opt | STRING | 0 | — |
| switch_5opt | BOOLEAN | false | — |
| target_type_5opt | COMBO | ID | 2 options: ID, Title |
| label_6opt | STRING | — | |
| targets_6opt | STRING | 0 | — |
| switch_6opt | BOOLEAN | false | — |
| target_type_6opt | COMBO | ID | 2 options: ID, Title |
| label_7opt | STRING | — | |
| targets_7opt | STRING | 0 | — |
| switch_7opt | BOOLEAN | false | — |
| target_type_7opt | COMBO | ID | 2 options: ID, Title |
| label_8opt | STRING | — | |
| targets_8opt | STRING | 0 | — |
| switch_8opt | BOOLEAN | false | — |
| target_type_8opt | COMBO | ID | 2 options: ID, Title |
| label_9opt | STRING | — | |
| targets_9opt | STRING | 0 | — |
| switch_9opt | BOOLEAN | false | — |
| target_type_9opt | COMBO | ID | 2 options: ID, Title |
| label_10opt | STRING | — | |
| targets_10opt | STRING | 0 | — |
| switch_10opt | BOOLEAN | false | — |
| target_type_10opt | COMBO | ID | 2 options: ID, Title |
| label_11opt | STRING | — | |
| targets_11opt | STRING | 0 | — |
| switch_11opt | BOOLEAN | false | — |
| target_type_11opt | COMBO | ID | 2 options: ID, Title |
| label_12opt | STRING | — | |
| targets_12opt | STRING | 0 | — |
| switch_12opt | BOOLEAN | false | — |
| target_type_12opt | COMBO | ID | 2 options: ID, Title |
| label_13opt | STRING | — | |
| targets_13opt | STRING | 0 | — |
| switch_13opt | BOOLEAN | false | — |
| target_type_13opt | COMBO | ID | 2 options: ID, Title |
| label_14opt | STRING | — | |
| targets_14opt | STRING | 0 | — |
| switch_14opt | BOOLEAN | false | — |
| target_type_14opt | COMBO | ID | 2 options: ID, Title |
| label_15opt | STRING | — | |
| targets_15opt | STRING | 0 | — |
| switch_15opt | BOOLEAN | false | — |
| target_type_15opt | COMBO | ID | 2 options: ID, Title |
| label_16opt | STRING | — | |
| targets_16opt | STRING | 0 | — |
| switch_16opt | BOOLEAN | false | — |
| target_type_16opt | COMBO | ID | 2 options: ID, Title |
| label_17opt | STRING | — | |
| targets_17opt | STRING | 0 | — |
| switch_17opt | BOOLEAN | false | — |
| target_type_17opt | COMBO | ID | 2 options: ID, Title |
| label_18opt | STRING | — | |
| targets_18opt | STRING | 0 | — |
| switch_18opt | BOOLEAN | false | — |
| target_type_18opt | COMBO | ID | 2 options: ID, Title |
| label_19opt | STRING | — | |
| targets_19opt | STRING | 0 | — |
| switch_19opt | BOOLEAN | false | — |
| target_type_19opt | COMBO | ID | 2 options: ID, Title |
| label_20opt | STRING | — | |
| targets_20opt | STRING | 0 | — |
| switch_20opt | BOOLEAN | false | — |
| target_type_20opt | COMBO | ID | 2 options: ID, Title |
Outputs (0)
No outputs