Extensions/JStudio_Wildcards
ComfyUI Extension

JStudio_Wildcards

A wildcard prompt node for ComfyUI with Jinja2 templating, YAML wildcard support, negative prompt resolution, and hot-reload — no server restart needed when you update…

By cyanideoverdose·Created 4 months ago·Updated 4 months ago· 1
cyanideoverdose/JStudio_Wildcards
Nodes1
On cloudLocal install
CategoryJoaquin Studios
Stars1
Updated4 months ago
Readme

JStudio Wildcards — ComfyUI Custom Node

A wildcard prompt node for ComfyUI with Jinja2 templating, YAML wildcard support, negative prompt resolution, and hot-reload — no server restart needed when you update your wildcard files.

Built by Joaquin Studios (Leizer on Civitai).


Features

  • __wildcard__ and __folder/key__ syntax for .txt and .yaml files
  • {option1|option2|option3} random choice syntax
  • {33%option_a|option_b} weighted probability syntax
  • ✅ Full Jinja2 template support with date-aware logic
  • Negative prompt input with full wildcard and Jinja2 support
  • Shared Jinja2 scope — variables set in positive prompt are available in negative
  • Inline separator — write positive and negative in one template with ###NEGATIVE###
  • Hot-reload button — update wildcard files without restarting ComfyUI
  • ✅ Nested YAML support with key navigation
  • ✅ Holiday-aware wildcard pools (Halloween, Christmas, Valentine's)
  • ✅ Seeded randomness — connect to your KSampler seed for reproducible results
  • ✅ Automatic comma and whitespace cleanup
  • character_name output for automatic filename tagging

Installation

Via ComfyUI Manager (recommended)

  1. Open ComfyUI Manager
  2. Click Install via Git URL
  3. Paste: https://github.com/cyanideoverdose/JStudio_Wildcards
  4. Restart ComfyUI once

Manual

  1. Clone or download this repo into ComfyUI/custom_nodes/jstudio_wildcards/
  2. Install dependencies:
    pip install jinja2 pyyaml
    
  3. Restart ComfyUI once

Nodes

🎲 JStudio Wildcards

The main prompt resolver.

Inputs: | Input | Type | Description | |-------|------|-------------| | prompt | STRING | Positive prompt with wildcard tags and/or Jinja2 templates | | seed | INT | Random seed — connect to KSampler seed for sync | | wildcards_folder | STRING | Path to wildcards folder (leave blank to auto-detect) | | character_wildcard | STRING | Wildcard file to watch for character name extraction | | negative_prompt | STRING (optional) | Negative prompt — supports wildcards and Jinja2, shares variable scope with positive |

Outputs: | Output | Type | Description | |--------|------|-------------| | resolved_prompt | STRING | Fully resolved positive prompt | | resolved_negative | STRING | Fully resolved negative prompt | | character_name | STRING | Detected character name for use in filenames |

Button: 🔄 Refresh Wildcards — reloads all files from disk instantly, no restart needed


🔄 JStudio Reload Wildcards

Standalone reload utility node. Useful if you want reload control as a separate node in your workflow.


Syntax Reference

Wildcard files (txt)

__scene__
__pose/camera_angle__
__outfits/standard__

YAML wildcards (nested keys)

__characters/my_cast/char_a__
__prompts/my_prompts/standard__

Random choice

{option1|option2|option3}

Weighted choice

{33%option_a|option_b}          → 33% a, 67% b
{25%foo|25%bar|baz}             → 25% foo, 25% bar, 50% baz
{33%outerwear|}                 → 33% outerwear, 67% empty string

Jinja2 Templates

Basic usage

{% set char_name = 'char_a' %}
{% set desc = wildcard("characters/my_cast/" ~ char_name) %}
{% set cam = wildcard("pose/camera_angle") %}
{% set is_rear = "behind" in cam or "back" in cam %}
{% if is_rear %}
  {{ wildcard("characters/my_cast/" ~ char_name ~ "_rear") }}, from_behind, back_view
{% else %}
  {{ desc }}
{% endif %}, __outfits/standard__, {{ cam }}, __skin__

Inline negative with ###NEGATIVE### separator

Write positive and negative in one template. Variables are shared across both sides:

{% set outfit_key = ["outfits/revealing", "outfits/standard", "outfits/bodysuit"] | random %}
{% set outfit = wildcard(outfit_key) %}
{% set is_revealing = outfit_key in ["outfits/revealing"] %}
{% set cam = wildcard("pose/camera_angle") %}
{% set is_rear = "behind" in cam %}

{{ wildcard("characters/my_cast/char_a") }}, {{ outfit }}, __pose/action__, __scene__, {{ cam }}, __skin__

###NEGATIVE###

{% if not is_revealing %}visible_nipples, exposed_breasts,{% endif %}
{% if is_rear %}looking_at_viewer, facing_camera,{% endif %}
__negatives/global__

Separate negative prompt input

The negative_prompt input shares the same Jinja2 variable scope as the positive prompt. Variables set in the positive are available in the negative:

Positive prompt:

{% set char_name = 'char_a' %}
{% set is_clothed = true %}
{{ wildcard("characters/my_cast/" ~ char_name) }}, __outfits/standard__

Negative prompt input:

{% if is_clothed %}visible_nipples, exposed_breasts,{% endif %}
__negatives/global__

Holiday-aware pools

{% if is_halloween %}
  {{ wildcard("characters/my_cast/char_a") }}, __outfits/halloween__, __scene/spooky__
{% elif is_christmas %}
  {{ wildcard("characters/my_cast/char_a") }}, __outfits/christmas__, __scene/winter__
{% else %}
  {{ wildcard("characters/my_cast/char_a") }}, __outfits/standard__, __scene/location__
{% endif %}

Available Jinja2 Globals

| Variable | Description | |----------|-------------| | wildcard("key") | Pick one random entry from a wildcard file | | wc_all("key") | Get full list from a wildcard file | | month | Current month (integer) | | day | Current day (integer) | | year | Current year (integer) | | now | Full datetime object | | is_halloween | True during October | | is_christmas | True during December and late November | | is_valentines | True February 1–14 | | is_holiday | True if any holiday is active | | random | Seeded Python random instance |


Recommended Folder Structure

wildcards/
  characters/
    my_cast.yaml          ← character descriptions (front + rear)
  prompts/
    my_prompts.yaml       ← reusable prompt templates
  negatives/
    global.txt            ← negatives applied to everything
    character/
      char_a.txt          ← character-specific negatives
  my_cast.yaml            ← character resolution and random list
  outfits/
  pose/
  scene/
  lighting/
  skin.txt

characters/my_cast.yaml structure

char_a: "1woman, blue skin, colored_skin, long red hair, ..."
char_a_rear: "1woman, blue skin, colored_skin, long red hair, ..."  # face/eye tags removed
char_b: "..."
char_b_rear: "..."

prompts/my_prompts.yaml structure

standard: |
  {% set desc = wildcard("characters/my_cast/" ~ char_name) %}
  {% set cam = wildcard("pose/camera_angle") %}
  {% set is_rear = "behind" in cam or "back" in cam %}
  {% if is_rear %}{{ wildcard("characters/my_cast/" ~ char_name ~ "_rear") }}, from_behind{% else %}{{ desc }}{% endif %}, __outfits/standard__, {{ cam }}, __skin__

club: |
  {% set desc = wildcard("characters/my_cast/" ~ char_name) %}
  {{ desc }}, __outfits/standard__, __scene/club__, __lighting/mood__, __pose/action__, __skin__

my_cast.yaml structure

random:
  - "__my_cast/char_a__"
  - "__my_cast/char_b__"

char_a:
  - "{% set char_name = 'char_a' %}{{ wildcard('prompts/my_prompts/standard') }}"
  - "{% set char_name = 'char_a' %}{{ wildcard('prompts/my_prompts/club') }}"

char_b:
  - "{% set char_name = 'char_b' %}{{ wildcard('prompts/my_prompts/standard') }}"
  - "{% set char_name = 'char_b' %}{{ wildcard('prompts/my_prompts/club') }}"

Adding a new prompt variant: edit one entry in prompts/my_prompts.yaml, add one line per character in my_cast.yaml. Adding a new character: add descriptions to characters/my_cast.yaml, add entries to my_cast.yaml.


Example Wildcard Pack

A complete example wildcard pack with placeholder characters and folder structure is available in the examples/ folder. Drop it into your wildcards directory to get a working pipeline immediately.


Wildcard Folder Auto-Detection

The node walks up from its install location looking for a wildcards folder automatically. To use a custom location, set the wildcards_folder input:

C:/ComfyUI/wildcards
/home/user/ComfyUI/wildcards

License

MIT License — free to use, modify, and distribute.


Joaquin Studios