Flux Klein RefGrid
The Klein reference node that made face LoRAs optional
- conditioning
- vae
- conditioning
- grid_image
Flux Klein 9B is the reference-image model: give it a few photos and it will happily swap heads, place a character into a scene, or hold a face across a generation - no LoRA, no training, just conditioning. The problem is how you feed it. The native ComfyUI path is one ReferenceLatent encode per image, chained together, and it's fiddly - multiple separate latents leak backgrounds into each other and bleed characters together. FluxKleinRefGrid sidesteps the whole mess by doing what the author figured out after weeks of fighting it: stitch up to 4 references into a single 2×2 grid, encode that one image, and hand Klein one clean reference latent.
It works, and it works noticeably better than the chain. This node is the distilled version of xb1n0ry's r/comfyui workflow that hit +300 with "from now on there's no need for face loras" in the comments. One node, no noodles.
How it works
The mechanism is right there in the source, and it's refreshingly honest. Each image you drop in gets letterbox-fit (aspect preserved, black bars added) onto a fixed 1000×1000 tile. Tiles fill a 2×2 grid, missing slots becoming plain black, so you always get exactly a 2000×2000 image - 4MP, matching what Flux 2 natively speaks. That grid is VAE-encoded once, multiplied by strength, and appended to the conditioning's reference_latents list via conditioning_set_values with append=True, so it composes with any reference latents already in the stream.
The second half is the UI. The node ships a built-in gallery - an Add Images button, 2×2 thumbnails, per-image × removal, a Clear button - and that gallery state is serialized into the hidden image_list widget, so your references travel with the saved workflow. Images are uploaded to ComfyUI's input folder and thumbnailed in the browser; nothing runs until you hit Queue. Because the node is marked OUTPUT_NODE, it also shows a live preview of the stitched grid after each run, same mechanism as PreviewImage.
The inputs that matter
Four inputs, and honestly you only touch two of them.
conditioning- your positive/edited-conditioning, straight from your CLIP or Qwen text encoder.vae- the Flux Klein VAE. This one's non-negotiable: the grid is encoded in latent space, so a wrong VAE means garbage reference.strength- default 1.0. The schema lets it swing from −10 to +10, but in practice you live between about 0.5 and 1.5: too high and the references start smearing into the result, too low and Klein ignores them. Negative values subtract the reference instead of adding it, which is more of a party trick than a tool.image_list- hidden serialized state, populated by the gallery. You'll never type in it. If it's empty when you run, the node refuses with a "add at least one image" error.
Outputs are conditioning (wire this into your sampler stack instead of the original) and grid_image, which is handy if you want to save or inspect the stitched reference.
Installing it
ComfyUI Manager, search ComfyUI-KleinRefGrid, install, restart. Or the manual route:
cd ComfyUI/custom_nodes
git clone https://github.com/xb1n0ry/ComfyUI-KleinRefGrid
Then restart ComfyUI. There are no extra Python dependencies - it's PIL, numpy, and torch, all already bundled with ComfyUI. What you do need is the model itself: the Flux Klein 9B checkpoint (plus its VAE), which is the actual cost of admission. Klein 9B runs in roughly 13GB of VRAM, so this is a real but not absurd hardware ask.
Where people get burned
The most common failure isn't the node at all - it's Klein not finding a face to work on. If your target image has a face that's tiny, heavily cropped, or partially cut off, Klein may decide there's nothing to replace and silently generate a new image from your references instead of editing. The author's fixes, straight from the thread: use a cleaner face crop, load the BFS face-swap LoRA to push the model to scan harder, or start the prompt with "find the face in the image and…". And keep in mind the reference pipeline doesn't have to be four images - one solid reference beats four mediocre ones every time. If your result looks off, tune strength before you blame the node; it's the only real knob, and it's a good one.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| conditioning | CONDITIONING | — | |
| vae | VAE | — | |
| strength | FLOAT | 1.00-10–10 | — |
| image_list | STRING | [] | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| conditioning | CONDITIONING | — |
| grid_image | IMAGE | — |