kubakub versions
The numbered contact sheet workflow
- model
- clip
- vae
- plan
- image
- references
- images
- sheet
- report
- save_path
- names
The worst way to explore a design is to change one thing, queue, wait, look, change another thing, queue. kubakub versions is the opposite: you write a list of what should vary, queue once, get a numbered contact sheet of drafts, then type the numbers you like into a second field and get only those at full size. It's the best-designed node in this pack, and it's the one most likely to change how you work.
The versions sheet
The versions input is a small text language, one option per line, grouped into lists:
[look]
copper = oxidised copper plates, verdigris, rivets
paper = folded white paper, soft daylight
[region windows]
warm rooms, people moving inside
aquariums, fish, blue light
[rotate windows | wall | roof]
molten glass
woven textile
[lora]
none
My_Style_v1 : 0.8 : my style
My_Style_v1 : 1.2 + Detail_v2 : 0.5
[look]adds to every region's prompt - whole-facade looks.[region windows]adds to some regions, using the plan's selector syntax (names,group:,tag:,region:).[rotate a | b | c]is the clever one: each idea moves on by one region per version, so version 3 applies idea 3 to the first selected region, idea 1 to the second, and so on. No two versions have the same idea in the same place.[lora]isname : strength : words added to the prompt, and chains with+put several LoRAs on one version. Alate and early = A : 1.1 + A : 0.65line gives the sheet a readable label for a chain.[reference]is style images - a file, a folder, or a folder with| 12to spread 12 images over a big folder.[image]rotates the picture each version starts from: the clay render, a wireframe over it, a canny map, a cryptomatte.[set denoise](and[set denoise windows]for some regions) changes any plan setting.[seed]adds to the plan's seed per version.
A short name before the = is optional and only exists so the contact sheet and names output read nicely.
mode decides how the lists combine: rotate (version n takes option n of every list, short lists start over), combine (every combination - grows fast, which is what max_versions, default 12, is defending against), and one by one (everything at its first option, then one change at a time - the mode for isolating a variable). count overrides how many versions rotate produces.
Draft, then final
quality is the whole trick. draft renders small and fast - draft_mp (default 0.5) megapixels per region, on the canvas scaled down to draft_long_edge (1600) - and gives you a sheet with every version numbered and labelled with what it's made of. You look at it, you write numbers into pick (2, 5, 9-11), you switch quality to final, queue again. Finals are the draft scaled back up to the full canvas and resampled tile by tile at final_denoise (default 0.4). The author's framing is the right one: a final is its draft, sharper. Low final_denoise stays close to the draft; higher adds detail and changes more.
If you'd rather pull images from disk than type numbers, picks_folder takes a folder of drafts you copied out of save_folder - every image in it gets scaled up with the look, LoRAs and style image it was made with. save_folder (default kubakub/versions inside ComfyUI's output) writes drafts as r<run>_v<number>_<what>.png with finals in a final subfolder, and the filenames carry enough to go straight back into a picks folder.
Two modes, and one honest option
generate = regions repaints every region inside its own mask: the facade keeps its windows, a window stays a window. whole picture throws the masks away and does one free sample, with the starting image only as reference image 1 and the style image as image 2 - forms can grow across the facade and out of it. That's how you get large sculptural interventions, and it comes with a caveat the author states: a free sample comes back a few pixels moved or scaled, so the node puts it back onto the starting image by itself (the same thing kubakub align to source does) and leaves it alone when the fit isn't certain.
unify is the fix for a specific failure. If your plan deals a random idea per region (prompt += {tiles|folded cloth|porous stone|mesh} chooses one per region by seed), regions sampled with different ideas can fall apart into patches. unify at 0.3 runs one more pass over the whole picture and ties them into one structure; 0.5 and up lets them grow into each other. It costs about one more sample per version - cheap next to re-queuing.
only limits which regions get painted, in plan-selector syntax; the rest stay as they were.
Models and installation
model, clip, vae and the plan from kubakub region plan are required, plus the image every version starts from. The example workflows use Flux 2 Klein or Qwen Image 2.1; the lightest path by far is Klein 4B, which is Apache 2.0, distilled to 4 steps at CFG 1, and small enough to run on modest cards. If steps and cfg are 0, the model's own default applies (Klein 4, Qwen Image 2.1 25, CFG 1.0) - and if you're running one of the Qwen turbo LoRAs, set scheduler to qwen21_turbo_5 or pruna_qwen21_8 so the schedule matches the trained step count instead of the full 25.
cd ComfyUI/custom_nodes && git clone https://github.com/kubakubkub/ComfyUI_KubaNodes
python -m pip install -r ComfyUI_KubaNodes/requirements.txt
Outputs: images (one per rendered version, in number order), sheet (the numbered contact sheet - this is the deliverable you send to the client), report (the lists, every version, each rendered version's rules and time), save_path, and names (one line per version, matching the order of images).
Where people get burned
Versions that didn't change come from the region cache, so this is cheaper than it looks - but combine mode with four lists is 60 versions before you notice. And max_versions is a hard ceiling, not a budget: the sheet never shows more versions than the number you set, so read the report's list rather than assuming you got everything you asked for.
And the honest limit: the sheet gives you options, not judgement. A list of twelve looks where three are essentially the same image at different seeds is a wasted queue - curate the sheet the way you'd curate anything else, one variable at a time.
Inputs (26)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | The image model (Flux 2 Klein or Qwen Image 2.1). LoRAs of the sheet are added to it per version. | |
| clip | CLIP | The text encoder that matches the model. | |
| vae | VAE | The VAE that matches the model. | |
| plan | KUBA_PLAN | From kubakub region plan: what every version has in common (the base prompt, denoise, order). Each version adds its rules. | |
| image | IMAGE | The canvas every version starts from, e.g. the clay render, exactly the size of the regions. A batch of several images (clay, wireframe, canny ...): each one is an option of the image list, like [image] in the sheet. | |
| versions | STRING | // one option per line; 'short name = text' gives it a label [look] copper = oxidised copper plates, verdigris, rivets paper = folded white paper, soft daylight moss = overgrown with moss and ivy, wet stone [region windows] warm rooms, people moving inside aquariums, fish, blue light [lora] none | The versions sheet: lists of options, one per line. See docs/generate.md (kubakub versions). |
| mode | COMBO | rotate | rotate: version n takes option n of every list (short lists start over). combine: every combination. one by one: the first option of everything, then one change at a time. |
| quality | COMBO | draft | draft: small and fast, for the contact sheet. final: the same picture at the full canvas size with full-size detail, for the picked versions. |
| pick | STRING | Version numbers to render (as on the contact sheet). Empty = all. | |
| max_versions | INT | 121–200 | The sheet never gives more versions than this (combine grows fast). |
| seed | INT | 00–18446744073709550000 | Added to the plan's seed; a [seed] list in the sheet adds to it per version. |
| draft_mp | FLOAT | 0.500.1–2 | Work megapixels per region of the draft (small = fast). |
| final_denoise | FLOAT | 0.400–1 | final: the draft is scaled up to the full canvas and resampled tile by tile at this denoise. Low stays close to the draft, higher adds more detail and changes more; 0 = the scaled-up draft. |
| draft_long_edge | INT | 1600256–8192 | The picture is made on the canvas scaled down to this long edge (draft and final); final scales it up again and adds the detail. |
| referencesopt | IMAGE | Style reference images (a batch): each one is an option of the reference list, after those written in the sheet. | |
| countopt | INT | 00–200 | rotate: how many versions; 0 = as many as the longest list. |
| sheet_columnsopt | INT | 00–16 | Columns of the contact sheet; 0 = automatic. |
| stepsopt | INT | 00–200 | 0 = the model's default (Klein 4, Qwen Image 2.1 25). |
| sampler_nameopt | COMBO | euler | Sampler for every region. |
| scheduleropt | COMBO | auto | auto: the model's own schedule (Flux 2: core's Flux2Scheduler for the crop size; Qwen Image 2.1: simple). simple, beta, sgm_uniform ...: that core scheduler, as in KSampler. qwen21_turbo_5 / pruna_qwen21_8: the trained steps of the Qwen turbo LoRAs. |
| picks_folderopt | STRING | final: a folder with the drafts you like (copy them there from the save folder). Every image in it is scaled up to the full canvas and gets its full-size detail, with the look, LoRAs and style image it was made with; the sheet and pick are not used. Empty = the numbers in pick. | |
| save_folderopt | STRING | kubakub/versions | Where the versions are saved (inside ComfyUI's output folder, or a full path): drafts as r<run>_v<number>_<what it is made of>.png, finals in the subfolder 'final'. Each file knows its version, so it can go into a picks folder. Empty = nothing is saved. |
| unifyopt | FLOAT | 0.000–1 | One more pass over the whole picture after the regions, at this denoise: it ties regions with different prompts into one structure. 0 = off; 0.3 keeps every region's idea, 0.5 and more lets them grow into each other. Costs about one more sample per version. |
| generateopt | COMBO | regions | regions: every region is repainted inside its own mask (the facade keeps its elements). whole picture: one free sample of the whole picture from nothing, with the image only as reference image 1 and the style image as image 2, no masks: forms may grow across the facade and out of it. Per-region rules then only add their words to the one prompt. |
| onlyopt | STRING | Paint only these regions (Written as in kubakub region plan: names with wildcards ('W_F1_*'), 'group:Windows', 'tag:front', 'region:3-7'; comma or Enter = or, space = and, '!' = not.); the others stay as they are. Empty = all. A whole picture is still made in one piece; only its full-size detail follows this. | |
| cfgopt | FLOAT | 0.00–30 | Used where the plan says cfg = 0. 0 = the model's default (1.0). |
Outputs (5)
| Name | Type | Description |
|---|---|---|
| images | IMAGE | One image per rendered version, in number order. |
| sheet | IMAGE | The contact sheet: every rendered version with its number and what it is made of. |
| report | STRING | The lists, every version with its number, and each rendered version's rules and time. |
| save_path | STRING | The folder the versions of this run were saved to (finals: the subfolder 'final'). Empty when nothing was saved. |
| names | STRING | One line per version, in the order of 'images': its number and label, as on the contact sheet. |