Nodes/kubakub nodes/kubakub versions
ComfyUI Node

kubakub versions

The numbered contact sheet workflow

By kubakubkub·Created about a month ago·Updated 2 days ago· 10
kubakub versions
  • model
  • clip
  • vae
  • plan
  • image
  • references
  • images
  • sheet
  • report
  • save_path
  • names
◄versions// 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 ►
◄moderotate►
◄qualitydraft►
◄pick►
◄max_versions12►
◄seed0►
◄draft_mp0.50►
◄final_denoise0.40►
◄draft_long_edge1600►
◄count0►
◄sheet_columns0►
◄steps0►
◄sampler_nameeuler►
◄schedulerauto►
◄picks_folder►
◄save_folderkubakub/versions►
◄unify0.00►
◄generateregions►
◄only►
◄cfg0.0►

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] is name : strength : words added to the prompt, and chains with + put several LoRAs on one version. A late and early = A : 1.1 + A : 0.65 line gives the sheet a readable label for a chain.
  • [reference] is style images - a file, a folder, or a folder with | 12 to 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.

Categorykubakub/2d/generate

Inputs (26)

NameTypeDefaultDescription
modelMODELThe image model (Flux 2 Klein or Qwen Image 2.1). LoRAs of the sheet are added to it per version.
clipCLIPThe text encoder that matches the model.
vaeVAEThe VAE that matches the model.
planKUBA_PLANFrom kubakub region plan: what every version has in common (the base prompt, denoise, order). Each version adds its rules.
imageIMAGEThe 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.
versionsSTRING// 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).
modeCOMBOrotaterotate: 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.
qualityCOMBOdraftdraft: small and fast, for the contact sheet. final: the same picture at the full canvas size with full-size detail, for the picked versions.
pickSTRINGVersion numbers to render (as on the contact sheet). Empty = all.
max_versionsINT121–200The sheet never gives more versions than this (combine grows fast).
seedINT00–18446744073709550000Added to the plan's seed; a [seed] list in the sheet adds to it per version.
draft_mpFLOAT0.500.1–2Work megapixels per region of the draft (small = fast).
final_denoiseFLOAT0.400–1final: 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_edgeINT1600256–8192The picture is made on the canvas scaled down to this long edge (draft and final); final scales it up again and adds the detail.
referencesoptIMAGEStyle reference images (a batch): each one is an option of the reference list, after those written in the sheet.
countoptINT00–200rotate: how many versions; 0 = as many as the longest list.
sheet_columnsoptINT00–16Columns of the contact sheet; 0 = automatic.
stepsoptINT00–2000 = the model's default (Klein 4, Qwen Image 2.1 25).
sampler_nameoptCOMBOeulerSampler for every region.
scheduleroptCOMBOautoauto: 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_folderoptSTRINGfinal: 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_folderoptSTRINGkubakub/versionsWhere 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.
unifyoptFLOAT0.000–1One 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.
generateoptCOMBOregionsregions: 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.
onlyoptSTRINGPaint 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.
cfgoptFLOAT0.00–30Used where the plan says cfg = 0. 0 = the model's default (1.0).

Outputs (5)

NameTypeDescription
imagesIMAGEOne image per rendered version, in number order.
sheetIMAGEThe contact sheet: every rendered version with its number and what it is made of.
reportSTRINGThe lists, every version with its number, and each rendered version's rules and time.
save_pathSTRINGThe folder the versions of this run were saved to (finals: the subfolder 'final'). Empty when nothing was saved.
namesSTRINGOne line per version, in the order of 'images': its number and label, as on the contact sheet.