CLIP Positive-Negative XL (WLSH)
One box for both your SDXL prompts
- clip
- positive
- negative
If you've ever built a real SDXL graph by hand, you know the annoyance this node exists to fix. Core ComfyUI wants two CLIPTextEncodeSDXL nodes - one for positive, one for negative - and each one drags along six numeric fields (width, height, crop_w, crop_h, target_width, target_height) on top of the actual text boxes. That's two sprawling nodes and a dozen-plus widgets to say "here's what I want, here's what I don't." This node folds both prompts and all the SDXL conditioning knobs into a single box. It's exactly what the pack's README calls it: a space saver.
What it's doing under the hood. SDXL wasn't trained on just a caption - it was trained with extra "micro-conditioning" numbers baked in alongside the text: the size the source image actually was, where it was cropped from, and what size it was ultimately resized to. At inference time you get to set those numbers yourself, and doing so nudges the output. width/height tell the model what resolution to condition on (normally your real generation size). crop_w/crop_h simulate a crop offset - leave these at 0 unless you know why you'd want otherwise, since (0,0) means "uncropped," which is what you almost always want. target_width/target_height describe the size the model should aim its quality at - usually the same as width/height, though some people deliberately set it higher to nudge SDXL toward sharper detail (that's a documented side effect of how the conditioning was trained, not a rumor). This node keeps the two SDXL text encoders separate too - positive_g/positive_l and negative_g/negative_l - because SDXL actually runs two CLIP models (OpenCLIP-G and CLIP-L) under the hood, not one. Most people just paste the same text into both G and L slots and move on; you only need to split them if you're doing something deliberate like weighting concepts differently per encoder.
The inputs that actually matter for a first pass: clip from your SDXL checkpoint loader, positive_g/positive_l (your prompt, usually identical text in both), negative_g/negative_l (same idea), and width/height set to your real generation resolution. Leave crop_w/crop_h at 0 and target_width/target_height matching width/height unless you're specifically chasing the detail trick above.
Outputs are positive and negative CONDITIONING - wire those straight into your KSampler exactly like you would from any text encoder.
Installing it
Easiest path: open ComfyUI Manager, search "wlsh_nodes" (or "WLSH Nodes"), install, restart. Manual route: cd ComfyUI/custom_nodes && git clone https://github.com/wallish77/wlsh_nodes, then restart ComfyUI. No models to download, no unusual Python dependencies called out in the README - it's a lightweight utility pack, and the whole install is done in under a minute.
Where people trip up
The most common mistake isn't a crash, it's silence - you mix up width/height with target_width/target_height, or leave crop_w/crop_h non-zero from a copy-pasted template, and nothing errors. You just get subtly worse output than you'd expect, which is the most annoying kind of bug because there's no traceback pointing you at the fix. If your SDXL generations look a little off in ways you can't quite name, check these six numbers before you start reaching for sampler or CFG changes.
The other one: this node needs CLIP from an actual SDXL checkpoint. Feed it CLIP from an SD1.5 model and you'll get errors or garbage, because SD1.5's CLIP has no G/L split for this node to plug into - the two architectures aren't interchangeable at the conditioning level. If you need something that works across both SD1.5 and SDXL without swapping nodes, the pack's CLIP +/- w/Text Unified (WLSH) sibling node does that (at the cost of some of the flexibility this node gives you).
Inputs (11)
| Name | Type | Default | Description |
|---|---|---|---|
| width | INT | 10240–8192 | — |
| height | INT | 10240–8192 | — |
| crop_w | INT | 00–8192 | — |
| crop_h | INT | 00–8192 | — |
| target_width | INT | 10240–8192 | — |
| target_height | INT | 10240–8192 | — |
| positive_g | STRING | POS_G | — |
| positive_l | STRING | POS_L | — |
| negative_g | STRING | NEG_G | — |
| negative_l | STRING | NEG_L | — |
| clip | CLIP | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| positive | CONDITIONING | — |
| negative | CONDITIONING | — |