https://github.com/mobcat40/comfyui-promptchain
A visual prompt engineering toolkit for ComfyUI. Chain prompts together, see what fires, lock what works.
https://github.com/mobcat40/comfyui-promptchain
ai-art comfy-ui comfyui comfyui-custom-nodes generative-ai prompt-engineering randomization stable-diffusion wildcards workflow-automation
Last synced: 6 months ago
JSON representation
A visual prompt engineering toolkit for ComfyUI. Chain prompts together, see what fires, lock what works.
- Host: GitHub
- URL: https://github.com/mobcat40/comfyui-promptchain
- Owner: mobcat40
- Created: 2025-11-25T00:10:01.000Z (7 months ago)
- Default Branch: master
- Last Pushed: 2025-12-04T19:14:47.000Z (6 months ago)
- Last Synced: 2025-12-08T02:55:04.788Z (6 months ago)
- Topics: ai-art, comfy-ui, comfyui, comfyui-custom-nodes, generative-ai, prompt-engineering, randomization, stable-diffusion, wildcards, workflow-automation
- Language: JavaScript
- Homepage:
- Size: 8.82 MB
- Stars: 1
- Watchers: 0
- Forks: 1
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# ComfyUI-PromptChain
A visual prompt engineering toolkit for ComfyUI. Chain prompts together, see what fires, lock what works.
## The Problem
Complex prompts with randomization become unreadable fast:
```
{warrior|mage|rogue}, {iron|steel|mythril} {sword|axe|staff},
{{fire|ice|lightning} enchantment|no enchantment}, {dragon|demon|undead} slayer
```
Now nest a few levels deeper. Add 20 options per group. Good luck debugging which path fired.
## The Solution
PromptChain makes the hierarchy *spatial*. Instead of parsing nested braces in your head, you see the decision tree as connected nodes:

Each node shows exactly what it can output. Chain them together, see the whole prompt path at a glance.
## Installation
```bash
cd ComfyUI/custom_nodes
git clone https://github.com/mobcat40/ComfyUI-PromptChain.git
```
Restart ComfyUI. No external dependencies required.
## Features at a Glance
- **Dual prompt support** — Handle both positive and negative prompts in a single chain
- **Inline wildcards** — Write `red | blue | green` directly in nodes. No external files required.
- **Comments** — Use `//` or `/* */` to annotate your prompts without affecting output
- **Syntax highlighting** — Operators and comments are color-coded for easy reading
- **Visual chaining** — Connect nodes to build rich, meaningful structures
- **Dynamic inputs** — Inputs auto-expand as you connect more nodes
- **Live preview** — See what fired, when it fired, in real-time
- **Lock system** — Freeze outputs with upstream propagation
- **Disable system** — Mute entire branches with one click
- **Import/Export** — Convert to/from Dynamic Prompt syntax
- **Tag deduplication** — Automatic duplicate removal
- **Three modes:**
- `🎲 Roll` — Pick one random path from connected inputs
- `➕ Combine` — Merge all paths with intelligent interleaving
- `🟢 Switch` — Manually select which input to pass through (shows selected option name)
---
## Nodes
### PromptChain (Main Node)
The core node for all prompt processing, combining, and randomization.
#### Outputs
| Output | UI Label | Description |
|--------|----------|-------------|
| `chain` | `out` | Bundle containing both positive and negative prompts (for chaining to other PromptChain nodes) |
| `positive` | `positive` | Plain positive prompt text (connect to CLIP positive) |
| `negative` | `negative` | Plain negative prompt text (connect to CLIP negative) |
#### Menubar Controls
The menubar at the top of each node provides quick access to all controls:
| Control | Description |
|---------|-------------|
| 🔒/🔓 Lock | Freeze output (orange when active). Label shows when node is wide enough. |
| ⛔ Disable | Mute node (red when active). Label shows when node is wide enough. |
| ℹ️ Preview | Show live output preview. Label shows when node is wide enough. |
| `+` checkbox | Show/hide positive prompt text field (blue) |
| `-` checkbox | Show/hide negative prompt text field (red) |
#### Mode Selector
Below the menubar is a mode dropdown that controls how inputs are processed:
| Mode | Description |
|------|-------------|
| 🎲 Roll | Pick one random input (shows winning input name after execution) |
| ➕ Combine | Merge all inputs with breadth-first interleaving |
| 🟢 [name] | Switch mode — manually select which input to use (shows selected input's name) |
The dropdown shows "No Inputs" when no inputs are connected.
---
### PromptChain Debug (Utility Node)
Inspector node for debugging text flowing through your prompt chain.
**Purpose:** Logs the text reaching your CLIP/KSampler nodes to help debug complex chains.
**Inputs:**
- `text` — Text to inspect
- `label` — Optional label for the debug output (default: "positive")
**Output:**
- `text` — Passes through input unchanged
**Usage:** Insert between any connection to see what's actually being passed. Check `debug.log` in the extension folder (`custom_nodes/ComfyUI-PromptChain/debug.log`) for output.
---
## Dual Prompt Support
PromptChain handles both **positive and negative prompts** in a single unified chain.
### How It Works
Each PromptChain node has two text fields:
- **Positive prompt** (dark background) — Your main prompt content
- **Negative prompt** (subtle red-tinted background) — Things to avoid
Both prompts flow through the chain together via the `chain` output. At the end of your chain, use the separate `positive` and `negative` outputs to connect to your CLIP nodes.
### Visibility Toggles
Use the `+` and `-` checkboxes in the menubar to show/hide each prompt field:
- `+` — Toggle positive prompt visibility
- `-` — Toggle negative prompt visibility
This helps reduce clutter when you only need one prompt type in a particular node.
### Example Setup
```
[Style Node] [Subject Node] [Final Node]
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ + cinematic | │ │ + warrior | mage │ │ │──→ positive → CLIP
│ dramatic │──chain──→ │ │──chain──→ │ │
│ - blurry | ugly │ │ - deformed │ │ │──→ negative → CLIP
└──────────────────┘ └──────────────────┘ └──────────────────┘
```
---
## Modes
### 🎲 Roll (Randomize)
Picks **ONE random input** from all connected inputs.
- The node's text field is prepended to the selected input
- Use for branching logic where you want one path chosen randomly
- Each execution may select a different input
### ➕ Combine
Merges **ALL inputs** using breadth-first interleaving.
Tags round-robin across branches so no single branch dominates the token budget:
```
Input branches: ["a, b, c, d", "X, Y"]
Output: "a, X, b, Y, c, d"
```
Not `"a, b, c, d, X, Y"` — the interleaving ensures balanced representation.
### 🟢 Switch
**Manually select** which connected input to pass through.
- A dropdown appears showing all connected inputs by their source node names
- Click the dropdown or use arrow keys to cycle through inputs
- The node's text field is prepended to the selected input
- Perfect for A/B testing or debugging specific paths
---
## Wildcard Syntax
Write wildcards directly in text fields — no external files needed.
| Symbol | Meaning | Example | Result |
|--------|---------|---------|--------|
| `\|` | OR (pick one) | `red \| blue \| green` | `blue` |
| `,` | AND (include both groups) | `red \| blue, dress \| skirt` | `blue, dress` |
### Multiline Wildcards
Lines ending with `|` continue the OR group:
```
warrior |
mage |
rogue
```
Equivalent to `warrior | mage | rogue` — picks one randomly.
### Multiple Groups
Comma separates independent wildcard groups:
```
red | blue | green, large | small, fluffy | smooth
```
This picks one from each group and combines them: `"blue, small, fluffy"`
---
## Comments
Add notes to your prompts without affecting the output. Great for documenting complex prompts or temporarily disabling tags.
### Single-Line Comments
Use `//` to comment until end of line:
```
photorealistic, // main style
1girl, // character
detailed background // setting
```
Output: `photorealistic, 1girl, detailed background`
### Block Comments
Use `/* */` for multi-line comments:
```
cinematic lighting,
/* TODO: experiment with these later
golden hour,
rim lighting,
*/
soft shadows
```
Output: `cinematic lighting, soft shadows`
### Use Cases
- **Documentation** — Explain why certain tags are included
- **Quick disable** — Comment out tags instead of deleting them
- **Notes to self** — Leave reminders for future editing
- **Version history** — Keep old variations as comments
---
## Syntax Highlighting
All text fields feature live syntax highlighting with a Monokai-inspired color scheme:
| Element | Color | Example |
|---------|-------|---------|
| Operators (`\|`, `,`) | Pink, bold | `red \| blue` |
| Comments (`//`, `/* */`) | Gray, italic | `// note` |
| Regular text | Light gray | `portrait of a warrior` |
The highlighting updates in real-time as you type, making it easy to:
- **Spot structure** — Instantly see where your wildcards and groups are
- **Find comments** — Gray italic text stands out from active prompts
- **Identify operators** — Bold pink pipes and commas show decision points
The preview panel also uses syntax highlighting, with the "Prompt result:" label displayed in gray bold to distinguish metadata from actual prompt content.
---
## Lock System
Click the **lock icon** (🔒/🔓) to freeze the current output. (For when you need to lock in that sweet Mythril Ice Enchanted Sword!)

### When Locked
- Node returns cached output instead of re-processing
- Randomization results preserved across executions
- Perfect for keeping a roll you like
### Visual Indicators
| State | Appearance |
|-------|------------|
| Locked | 🔒 Orange icon + **bold yellow "Lock" text** + gold background with diagonal stripes |
| Unlocked | 🔓 Dim gray icon and text |
### Upstream Propagation
**Locking a node also locks all its input nodes** (the entire upstream chain). This ensures your complete prompt path stays frozen — from source nodes all the way to the locked node.
### Persistence
Lock state and cached output save with your workflow.
---
## Disable System
Click **⛔ Disable** in the menubar to temporarily exclude a node from the prompt chain.

### When Disabled
- Node outputs an empty string
- Downstream nodes ignore this input entirely
- The node and its upstream chain are visually marked
### Visual Indicators
| State | Appearance |
|-------|------------|
| Disabled | ⛔ Red icon + **bold red "Disable" text** + dark red background with diagonal stripes |
| Enabled | ⛔ Dim gray icon and text |
### Upstream Propagation
**Disabling a node also disables all its input nodes** (the entire upstream chain). This lets you mute an entire branch with one click.
### Use Cases
- A/B testing different branches without rewiring
- Temporarily muting parts of complex prompt trees
- Quick toggling of optional modifiers
### Persistence
Disabled state saves with your workflow.
---
## Live Preview
Toggle the **Preview** button (ℹ️) in the menubar to see real-time output.
### Preview Shows
- **Last run timestamp** — Shows elapsed time since execution (e.g., "20 mins ago"), updates in real-time
- **Execution time** — Shows how long the workflow took to execute (in milliseconds)
- **Word count** — Shows word count for positive and negative prompts (e.g., "15 words / 8 neg")
- **Selected wildcards** — See exactly which options fired
- **Full output** — The complete processed result for both positive and negative prompts
- **"Awaiting first run..."** — Shown until node executes for the first time
---
## Import & Export
Right-click any PromptChain node → **Import** or **Export**
### Import
Paste existing prompts and auto-generate clean node structures:
| Format | Example | Result |
|--------|---------|--------|
| Plain tags | `red, blue, green` | Converts to `red \| blue \| green` |
| Dynamic Prompts | `{warrior\|mage}, {sword\|staff}` | Creates connected node tree |
| Nested braces | `{a\|{b\|c}}` | Recursively expanded into node hierarchy |
| Top-level OR | `option A \| option B` | Creates separate input nodes |
### Export
Convert your node tree back to Dynamic Prompt format:
- Traverses all connected upstream nodes
- Converts wildcards to brace syntax
- Respects modes: Randomize → `{a|b}`, Combine → comma-joined
- Opens dialog with exportable string ready to copy
---
## Tag Deduplication
Duplicates are automatically removed. **First occurrence wins:**
```
Input: "red, blue, RED, green, Blue"
Output: "red, blue, green"
```
- Case-insensitive matching
- Special tags like `[BREAK]` are always preserved
- Early nodes = intentional placement; later duplicates from merges get removed
---
## Dynamic Inputs
Input slots automatically expand as you connect more nodes:
- Connect a node → new empty slot appears
- Disconnect → empty slots are cleaned up (keeps at least one)
- Input labels show connected node titles for easy identification
- No manual slot management needed
---
## Example Workflows
### RPG Character Generator
```
Node 1 (Randomize): Node 2 (Randomize): Node 3 (Combine):
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ warrior | │ │ steel | mythril │ │ fire enchant, │
│ mage | rogue │──────────→│ sword | staff │──────────→│ dragon slayer │
└─────────────────┘ └─────────────────┘ └─────────────────┘
Possible output: "warrior, mythril staff, fire enchant, dragon slayer"
```
### Style + Subject with Negative Prompts
```
[Style] [Subject] [Output]
┌────────────────┐ ┌────────────────┐ ┌────────────────┐
│ + cinematic | │ │ + portrait of │ │ │→ positive
│ moody | soft │──chain────→│ a warrior │──chain────→│ │
│ - cartoon │ │ - bad anatomy │ │ │→ negative
└────────────────┘ └────────────────┘ └────────────────┘
positive: "cinematic, portrait of a warrior"
negative: "cartoon, bad anatomy"
```
### A/B Testing with Switch Mode
```
[Option A]─────┐
│
[Option B]─────┼──→ [Switch Node] ──→ Output
│ (manually select)
[Option C]─────┘
```
Use the dropdown to instantly swap between options without rewiring.
---
## Trait Mixing Networks
Wire Randomize nodes in a **mesh** instead of a tree for combinatorial trait mixing:
```
[Fur Type]──┐ ┌──[Randomize]──┐
├────→┤ ├────→[Combine]──→ Final
[Fur Color]─┤ └──[Randomize]──┤
│ │
[Creature]──┴─────[Randomize]─────┘
```
Each Randomize node acts as selection pressure. Cross-wire your trait pools and every run produces a unique combination — like breeding.
Example pools:
- `Shiny Fur | Matted Fur`
- `Silver | Black | Red`
- `Werewolf | Bear`
Natural output: "Red, Shiny Fur, Werewolf" — emergent behavior from simple primitives.
---
## Prompt Palette
Use Switch mode to build a reusable prompt control panel:

**How it works:**
1. Create a Switch node for each category (Style, Pose, Character, Outfit, etc.)
2. Connect pre-built prompt options to each Switch
3. Use the dropdown or arrow keys to flip between presets
4. All Switches feed into a final Combine node
**Why this pattern is powerful:**
- **Instant iteration** — Change any category without rewiring
- **Saved presets** — Your options persist with the workflow
- **Mix and match** — Combine any style with any pose with any character
- **Quick comparison** — Flip through options to find what works
Build your prompt palette once, reuse it forever. Each workflow becomes a custom prompt mixer tailored to your subject.
---
## Prompt Library Mode
Disconnected PromptChain nodes act as prompt storage:
- Drop a node, paste your prompt, leave it unwired
- Sits on your canvas as a visual "sticky note"
- Saves with your workflow
- Connect when you want to use it, disconnect to deactivate
Build a library of prompt fragments right in your workflow. Zero config, just nodes.
---
## Why PromptChain?
| Pain Point | Dynamic Prompts | PromptChain |
|------------|-----------------|-------------|
| Nested syntax | `{a\|{b\|{c\|d}}}` | Visual node tree |
| Debugging | Read the string | See what lit up |
| Positive + negative | Separate handling | Unified chain |
| External files | Required | None |
| Migration | — | One-click import |
---
## Tips & Tricks
1. **Use Lock for iteration** — Find a random combination you like? Lock it before further experiments.
2. **Disable for comparison** — Instead of deleting nodes, disable them to quickly compare with/without.
3. **Hide unused prompts** — Use `+`/`-` toggles to hide prompt fields you're not using in a node.
4. **Preview everything** — Enable preview on your final node to see the complete output.
5. **Chain outputs** — Use `chain` output when connecting to other PromptChain nodes; use `positive`/`negative` only at the end for CLIP.
6. **Debug complex chains** — Insert a PromptChain Debug node to log what's actually flowing through a connection.
7. **Comment out experiments** — Use `//` to disable tags without deleting them: `// golden hour, soft lighting`
---
## License
MIT License — free to use forever!