BRKN Lifestyle Prompt Composer
Roll a whole photoshoot from one seed — the BRKN Lifestyle Prompt Composer
- metadata_in
- pack_selection
- positive_prompt
- negative_prompt
- metadata
- metadata_json
- summary
- character_prompt
- fashion_prompt
- scene_prompt
- presentation_prompt
- warnings
- used_seed
This is the engine half of the BRKN pack. Give it a seed and it builds a complete lifestyle prompt - character, outfit, location, action, pose, camera, lighting - by rolling from pools of curated prompt fragments, then resolves conflicts so the outfit doesn't fight the environment and the camera doesn't fight the pose. It's the successor to the author's WAN-2.2-era BRKN prompt generator, reborn as a ComfyUI node, and the whole point is that you stop rebuilding prompts from scratch: one seed gives you one coherent scene, the next seed gives you a different coherent scene, and you never write a sentence.
Where people get burned: treating it like a tag blender and leaving everything on random. The real power is the locks and filters.
How it works
Every section of the scene - character, body, skin, hair, fashion, footwear, location, atmosphere, pose, expression, camera, lighting, dozens of them - is a dropdown with three states: random (roll it), none (leave it out entirely), or a specific ID (lock it). Behind the scenes the resolver runs a three-stage pipeline per section: filter (your exclusions, then hard rules, then parent allowlists), score (soft rules that push compatible picks together and apart), then a deterministic weighted choice on that section's sub-seed.
The determinism is the interesting part. Each sub-seed is a SHA-256 hash of global_seed | section | revision, designed to be byte-stable across machines and pack load order - Python's salted hash() is never used. That means the same seed on the same packs always produces the same scene, which is what makes the _reroll counters work: bump fashion_reroll by 1 and only the outfit changes, because only that section's revision moved. It's a genuinely well-thought-out system, and it shows.
The inputs that matter
Of the five required, set seed with control_after_generate on randomize if you want a fresh scene every run - every section derives its own sub-seed from it. compatibility_mode (strict/balanced/loose) controls how aggressively the pack's generic fallback entries are allowed in; strict is the pickiest, loose lets the pool spill over when nothing exact matches. target_model (generic, qwen_image, flux_klein, krea) picks the rendering template - krea maps to generic for now, which is fine because these are long descriptive prompts, exactly what LLM-encoded models like Krea 2 read best.
Then the switches that save you: the four master toggles (use_character, use_wardrobe, use_scene, use_presentation) turn a whole block off - turn use_character OFF when a character LoRA owns the person, or your rolled hairstyle will fight the LoRA's weights instead of helping them. excluded_terms is your comma-separated blocklist ("garage, sleepwear"). And descent filters the character pool, with unspecified as the option that names no ethnicity and lets skin, hair and eyes carry the look.
Outputs
positive_prompt and negative_prompt wire straight into your CLIP Text Encode nodes. The middle outputs (character_prompt, fashion_prompt, scene_prompt, presentation_prompt) are the rendered fragments, handy when you want to inspect or splice just one block. metadata / metadata_json are the reuse trick: paste metadata_json back into the metadata_json input with reuse_from_metadata set to lock_content and you can re-roll presentation without touching the scene. warnings tells you when a conflict was resolved; used_seed confirms what actually ran.
Install and gotchas
Manager (search "Modular Prompt Composer" or "BRKN"), or git clone https://github.com/NUVoize/ComfyUI-BRKN-Prompt-Randomizer into custom_nodes/, then restart and hard-refresh. The only dependency is jsonschema - the pack degrades gracefully without it, showing a "Prompt Composer (failed to load)" placeholder node instead of crashing your whole scan; run pip install -r requirements.txt and restart if you see it.
Two real-world notes from the field. First, the beta shipped a "short stature" character option that leaked into prompts and stuck - the author pulled it, and it's the kind of thing to watch for: if a rolled entry won't leave, check the locks and excluded_terms, not the sampler. Second, the prompt pools lean descriptive (the pack description is literally "maximum spread by design - consistency is what the LoRA is for"), so on 2026 LLM-encoded models keep prompt_length at standard rather than detailed and let the blocks do the work; essays don't help the attention cap. It's one of the few randomizers built around locks, seeds and filters instead of pure chaos - worth the install.
Inputs (90)
| Name | Type | Default | Description |
|---|---|---|---|
| seed | INT | 00–9223372036854776000 | Every section derives its own sub-seed from this. Set control_after_generate to randomize for a fresh scene each run. |
| compatibility_mode | COMBO | strict | 3 options: strict, balanced, loose |
| target_model | COMBO | generic | 4 options: generic, qwen_image, flux_klein, krea |
| prompt_length | COMBO | standard | 3 options: compact, standard, detailed |
| visual_category | COMBO | any | 7 options: any, cinematic, commercial, editorial, hyper_realistic, photographic, +1 |
| use_characteropt | BOOLEAN | true | Face, body, hair, expression. Turn OFF when a character LoRA owns the person. |
| use_wardrobeopt | BOOLEAN | true | Outfit, footwear, outerwear, accessories. |
| use_sceneopt | BOOLEAN | true | Environment, location, pose, props. (The action always stays.) |
| use_presentationopt | BOOLEAN | true | Visual style, camera, lighting. Turn OFF when a style LoRA owns the look. |
| descentopt | COMBO | any | Filter the character pool by descent. 'any' keeps the full spread; 'unspecified' names no ethnicity at all and lets skin, hair and eyes carry the look. |
| styleopt | COMBO | random | 25 options: random, none, brkn_base.visual_style.anamorphic_cinema, brkn_base.visual_style.candid_iphone, brkn_base.visual_style.cinematic_photo, brkn_base.visual_style.clean_lifestyle, +19 |
| characteropt | COMBO | random | 29 options: random, none, brkn_base.character.black_early20s, brkn_base.character.black_early30s, brkn_base.character.black_late20s, brkn_base.character.black_mid20s, +23 |
| bodyopt | COMBO | random | 26 options: random, none, brkn_base.body.athletic_toned, brkn_base.body.athletic_toned_thighs, brkn_base.body.compact_strong, brkn_base.body.curvy_thick_hips, +20 |
| skinopt | COMBO | random | 21 options: random, none, brkn_base.skin.caramel_complexion, brkn_base.skin.clear_glowing, brkn_base.skin.dark_complexion, brkn_base.skin.deep_dark_glow, +15 |
| eyesopt | COMBO | random | 21 options: random, none, brkn_base.eyes.almost_black, brkn_base.eyes.amber, brkn_base.eyes.blue, brkn_base.eyes.brown, +15 |
| face_shapeopt | COMBO | random | 9 options: random, none, brkn_base.face_shape.diamond, brkn_base.face_shape.heart, brkn_base.face_shape.long, brkn_base.face_shape.oval, +3 |
| featuresopt | COMBO | random | 17 options: random, none, brkn_base.features.button_nose, brkn_base.features.dimpled_chin, brkn_base.features.geometric_features, brkn_base.features.high_cheekbones, +11 |
| browsopt | COMBO | random | 9 options: random, none, brkn_base.brows.arched, brkn_base.brows.dark, brkn_base.brows.pale, brkn_base.brows.straight_bold, +3 |
| lipsopt | COMBO | random | 9 options: random, none, brkn_base.lips.defined_cupids_bow, brkn_base.lips.full, brkn_base.lips.heart_shaped, brkn_base.lips.plump, +3 |
| hair_coloropt | COMBO | random | 25 options: random, none, brkn_base.hair_color.ash_blonde, brkn_base.hair_color.ash_brown, brkn_base.hair_color.auburn, brkn_base.hair_color.black_with_bleached_streak, +19 |
| face_paintopt | COMBO | random | 2 options: random, none |
| environmentopt | COMBO | random | 85 options: random, none, brkn_base.environment.back_alley, brkn_base.environment.bakery_cafe, brkn_base.environment.beach_house, brkn_base.environment.bookshop_cafe, +79 |
| figureopt | COMBO | random | 18 options: random, none, brkn_base.figure.athletic_flat, brkn_base.figure.broad_shoulders_narrow_hips, brkn_base.figure.flat_stomach_toned, brkn_base.figure.full_figure, +12 |
| body_artopt | COMBO | random | 18 options: random, none, brkn_base.body_art.behind_ear, brkn_base.body_art.collarbone_script, brkn_base.body_art.fine_line_forearm, brkn_base.body_art.full_sleeve, +12 |
| locationopt | COMBO | random | 78 options: random, none, brkn_base.location.alley_doorway, brkn_base.location.astride_the_saddle, brkn_base.location.attic, brkn_base.location.back_deck, +72 |
| atmosphereopt | COMBO | random | 40 options: random, none, brkn_base.atmosphere.autumn_gold, brkn_base.atmosphere.autumn_grey, brkn_base.atmosphere.autumn_mist, brkn_base.atmosphere.autumn_wet_leaves, +34 |
| actionopt | COMBO | random | 125 options: random, brkn_base.action.adjusting_her_sleeve, brkn_base.action.applying_mascara, brkn_base.action.asleep_against_the_window, brkn_base.action.astride_the_saddle, brkn_base.action.browsing_a_rail, +119 |
| hair_styleopt | COMBO | random | 45 options: random, none, brkn_base.hair_style.air_dried_texture, brkn_base.hair_style.asymmetric_bob, brkn_base.hair_style.bantu_knots, brkn_base.hair_style.beachy_waves, +39 |
| poseopt | COMBO | random | 358 options: random, none, brkn_base.pose.crouching_while_leaning_forward, brkn_base.pose.crouching_with_both_elbows_resting_on_her_knees, brkn_base.pose.crouching_with_both_feet_flat_on_the_floor, brkn_base.pose.crouching_with_both_hands_resting_on_her_knees, +352 |
| fashionopt | COMBO | random | 69 options: random, none, brkn_base.outfit.backless_halter_trousers, brkn_base.outfit.band_tee_baggy_jeans, brkn_base.outfit.belted_shirt_dress, brkn_base.outfit.blazer_over_tee, +63 |
| footwearopt | COMBO | random | 24 options: random, none, brkn_base.footwear.ballet_flats, brkn_base.footwear.barefoot, brkn_base.footwear.black_ankle_boots, brkn_base.footwear.black_high_top_converse, +18 |
| outerwearopt | COMBO | random | 23 options: random, none, brkn_base.outerwear.beige_trench, brkn_base.outerwear.brown_suede_jacket, brkn_base.outerwear.canvas_work_jacket, brkn_base.outerwear.charcoal_wool_coat, +17 |
| accessoryopt | COMBO | random | 49 options: random, none, brkn_base.accessory.anklet, brkn_base.accessory.chain_belt, brkn_base.accessory.chandelier_earrings, brkn_base.accessory.charm_bracelet, +43 |
| eyewearopt | COMBO | random | 53 options: random, none, brkn_base.eyewear.angular_geometric_sunglasses, brkn_base.eyewear.aviator_sunglasses, brkn_base.eyewear.black_glossy_sunglasses, brkn_base.eyewear.butterfly_sunglasses, +47 |
| headwearopt | COMBO | random | 53 options: random, none, brkn_base.headwear.baker_boy_cap, brkn_base.headwear.beret, brkn_base.headwear.boater_hat, brkn_base.headwear.bucket_hat, +47 |
| bagopt | COMBO | random | 43 options: random, none, brkn_base.bag.acrylic_statement_clutch, brkn_base.bag.baguette_bag, brkn_base.bag.belt_bag_worn_crossbody, brkn_base.bag.boxy_purse, +37 |
| handheldopt | COMBO | random | 43 options: random, none, brkn_base.handheld.boarding_pass, brkn_base.handheld.bouquet_of_flowers, brkn_base.handheld.car_keys, brkn_base.handheld.clear_water_bottle, +37 |
| head_positionopt | COMBO | random | 113 options: random, none, brkn_base.head_position.chin_lifted_above_its_neutral_position, brkn_base.head_position.chin_lifted_while_looking_directly_at_the_camera, brkn_base.head_position.chin_lifted_with_the_neck_elongated, brkn_base.head_position.chin_lowered_slightly, +107 |
| gazeopt | COMBO | random | 103 options: random, none, brkn_base.gaze.eyelids_partially_lowered, brkn_base.gaze.eyes_caught_in_the_middle_of_looking_sideways, brkn_base.gaze.eyes_closed_while_facing_the_camera, brkn_base.gaze.eyes_closed_while_the_head_is_turned_sideways, +97 |
| expressionopt | COMBO | random | 218 options: random, none, brkn_base.expression.absorbed_expression, brkn_base.expression.acknowledging_something_with_a_small_smile, brkn_base.expression.amused_expression_with_pursed_lips, brkn_base.expression.amused_sideways_smile, +212 |
| cameraopt | COMBO | random | 45 options: random, none, brkn_base.camera_preset.close_birds_eye, brkn_base.camera_preset.close_dutch, brkn_base.camera_preset.close_eye_level, brkn_base.camera_preset.close_high, +39 |
| lightingopt | COMBO | random | 34 options: random, none, brkn_base.lighting_preset.backlight, brkn_base.lighting_preset.blue_hour, brkn_base.lighting_preset.bounced_fill, brkn_base.lighting_preset.bright_daylight, +28 |
| action_familyopt | COMBO | any | 14 options: any, browsing, cleaning, commuting, cooking, creating, +8 |
| timeopt | COMBO | random | 9 options: random, none, early morning, mid morning, midday, afternoon, +3 |
| seasonopt | COMBO | none | 6 options: none, random, spring, summer, autumn, winter |
| weatheropt | COMBO | none | 7 options: none, random, clear, overcast, light rain, heavy rain, +1 |
| prefixopt | STRING | — | |
| suffixopt | STRING | — | |
| required_termsopt | STRING | — | |
| excluded_termsopt | STRING | Comma-separated tags to exclude, e.g. garage, sleepwear | |
| additional_negative_promptopt | STRING | — | |
| enabled_packsopt | STRING | Comma-separated pack ids. Empty means every loaded pack. | |
| style_rerollopt | INT | 00–10000 | — |
| character_rerollopt | INT | 00–10000 | — |
| body_rerollopt | INT | 00–10000 | — |
| skin_rerollopt | INT | 00–10000 | — |
| eyes_rerollopt | INT | 00–10000 | — |
| face_shape_rerollopt | INT | 00–10000 | — |
| features_rerollopt | INT | 00–10000 | — |
| brows_rerollopt | INT | 00–10000 | — |
| lips_rerollopt | INT | 00–10000 | — |
| hair_color_rerollopt | INT | 00–10000 | — |
| face_paint_rerollopt | INT | 00–10000 | — |
| environment_rerollopt | INT | 00–10000 | — |
| figure_rerollopt | INT | 00–10000 | — |
| body_art_rerollopt | INT | 00–10000 | — |
| location_rerollopt | INT | 00–10000 | — |
| atmosphere_rerollopt | INT | 00–10000 | — |
| action_rerollopt | INT | 00–10000 | — |
| hair_style_rerollopt | INT | 00–10000 | — |
| pose_rerollopt | INT | 00–10000 | — |
| fashion_rerollopt | INT | 00–10000 | — |
| footwear_rerollopt | INT | 00–10000 | — |
| outerwear_rerollopt | INT | 00–10000 | — |
| accessory_rerollopt | INT | 00–10000 | — |
| eyewear_rerollopt | INT | 00–10000 | — |
| headwear_rerollopt | INT | 00–10000 | — |
| bag_rerollopt | INT | 00–10000 | — |
| handheld_rerollopt | INT | 00–10000 | — |
| props_rerollopt | INT | 00–10000 | — |
| head_position_rerollopt | INT | 00–10000 | — |
| gaze_rerollopt | INT | 00–10000 | — |
| expression_rerollopt | INT | 00–10000 | — |
| camera_rerollopt | INT | 00–10000 | — |
| lighting_rerollopt | INT | 00–10000 | — |
| conditions_rerollopt | INT | 00–10000 | — |
| metadata_jsonopt | STRING | Paste metadata_json from a previous run to reuse its scene. | |
| reuse_from_metadataopt | COMBO | off | 3 options: off, lock_content, lock_everything |
| metadata_inopt | PROMPT_COMPOSER_METADATA | — | |
| pack_selectionopt | BRKN_PACK_SELECTION | — |
Outputs (11)
| Name | Type | Description |
|---|---|---|
| positive_prompt | STRING | Rendered positive prompt. |
| negative_prompt | STRING | Merged, de-duplicated negative prompt. |
| metadata | PROMPT_COMPOSER_METADATA | Structured metadata for another Prompt Composer node. |
| metadata_json | STRING | The same metadata as JSON. Paste this back into metadata_json to reuse a scene. |
| summary | STRING | Human-readable summary of what was selected. |
| character_prompt | STRING | Character and expression fragment. |
| fashion_prompt | STRING | Outfit fragment. |
| scene_prompt | STRING | Environment, location, action, pose and props fragment. |
| presentation_prompt | STRING | Style, camera and lighting fragment. |
| warnings | STRING | Warnings and conflicts. Empty when everything resolved cleanly. |
| used_seed | INT | The seed actually used. |