A JSON-based system for organizing and generating AI image prompts with nested refinements. Designed for flexible prompt management with support for multiple characters, variants, poses, and hierarchical rule application.
This system organizes character prompts with support for nested refinements. Each character can have multiple forms, and each form can have multiple poses or variations. The system supports flexible addressing syntax that allows you to reference prompts by number, name, or a combination.
template.json- Generic template for creating new projectssrc/create_image.py- Python script to generate images using OpenAI APIsrc/- Python source modulesrules/- Directory for reusable rule definitions (optional)generic_render_rules.json- Universal rendering rulespose_library.json- Reusable pose definitions
readme.md- This file
garou.json- Old West Werewolf Pack (9 characters, 45 refinements) - demonstrates the system
The system supports multiple ways to reference characters and refinements:
- By number:
1:1= character 1, refinement 1 (e.g., first form) - By name:
alpha:human= character named 'alpha', refinement named 'human' - Mixed:
alpha:1or1:human= mix numbers and names - Deep nesting:
1:1:1= character:form:pose (or any other levels)
1oralpha= entire character (all refinements)1:1oralpha:human= specific form1:1:1oralpha:human:standing= specific pose within form (if implemented)
metadata- Project information (title, version, description, date)generic_render_rules- Universal rules applied to ALL promptsthematic_rules- Optional theme-specific rulesminiature_scale_rules- Scale-specific rendering rules (e.g., 40mm tabletop)characters- Array of character definitions
Each character has:
id(number) - Numeric identifiername(string) - Text identifier for name-based addressingtitle(string) - Display titledescription(string) - Character backgroundvisual_notes(string) - Visual reference notesequipment(array) - Equipment/props with structured formatrefinementsorposes(array) - Nested refinements (forms, poses, etc.)
Each refinement can have:
id(number) - Numeric identifier within parentname(string) - Text identifierdescription(string) - Description of this refinementpose(string) - Optional pose descriptionprompt(string) - The actual prompt textthematic_snippet(array of strings, optional) - List of thematic rule references or custom snippets- Each item can be:
- A reference to a form name from
thematic_rules.forms(e.g.,["glabro"]) - A custom snippet string (e.g.,
["aggressive stance, prop displayed"]) - Multiple references or combinations (e.g.,
["glabro", "combat-ready"])
- A reference to a form name from
- The script resolves references and applies all snippets in order
- If omitted, only global thematic rules are applied
- Each item can be:
refinements(array) - Optional nested sub-refinements
Equipment uses a structured format that separates item details, position, and usage:
Format:
"equipment": [
"item_name (visual_detail) : position : usage_description"
]Position values:
main_hand- Primary weapon/tool in dominant handoff_hand- Secondary weapon/shield in off handdual_wield- Paired weapons in both handsholstered_belt,holstered_hip,holstered_thigh,holstered_back- Storage locations
Example:
"equipment": [
"longsword (straight blade, wrapped leather grip) : main_hand : held at ready",
"round shield (wood planks, steel rim) : off_hand : held at guard",
"dagger (simple blade, leather sheath) : holstered_belt : sheathed"
]Output in prompts:
PROPS:
- longsword (straight blade, wrapped leather grip) [main_hand] held at ready
- round shield (wood planks, steel rim) [off_hand] held at guard
- dagger (simple blade, leather sheath) [holstered_belt] sheathed
Pose-level equipment_override:
Poses can completely replace character equipment using the same format:
{
"id": 5,
"name": "unarmed_ready",
"pose_library_ref": "un_fighter_ready",
"equipment_override": [
"longsword (straight blade) : holstered_back : slung on back",
"shield (wood planks) : holstered_back : slung on back"
],
"character_override": "combat ready with hands empty; weapons stowed"
}This completely replaces the character's default equipment for that specific pose, allowing different equipment configurations per pose (e.g., weapons drawn vs weapons stowed).
The thematic_rules section supports project-wide theming:
prompt_snippet(string) - General thematic snippet applied to ALL prompts globallyforms(object) - Optional reusable form definitions that can be referenced by refinements- Each form has:
description,anatomy, andprompt_snippet - Useful for standardizing common variants (e.g., werewolf forms, armor types, etc.)
- Each form has:
- Refinements reference forms using
thematic_snippet: ["form_name"] - Multiple forms or custom snippets can be combined:
thematic_snippet: ["form1", "custom text", "form2"]
Example workflow:
- Define reusable forms in
thematic_rules.forms(optional) - Character prompt defines unique features
- Refinement's
thematic_snippetarray references forms or adds custom snippets - Global
thematic_rules.prompt_snippetadds overall theme (applied to ALL prompts) - Generic and miniature rules add technical requirements
Form Definitions Example:
"thematic_rules": {
"prompt_snippet": "Old West frontier horror",
"forms": {
"human": {
"description": "Fully human form",
"anatomy": "human anatomy, human proportions",
"prompt_snippet": "fully human form, predatory stillness"
},
"glabro": {
"description": "Near-human hybrid",
"anatomy": "enlarged hands and claws, elongated jaw",
"prompt_snippet": "near-human hybrid, enlarged hands and claws"
}
}
}Using Form References in Refinements:
{
"id": 1,
"name": "human",
"thematic_snippet": ["human"],
"prompt": "Character-specific details..."
},
{
"id": 2,
"name": "glabro",
"thematic_snippet": ["glabro"],
"prompt": "Character-specific details..."
},
{
"id": 3,
"name": "custom",
"thematic_snippet": ["glabro", "heavily scarred", "aggressive posture"],
"prompt": "Can combine form refs and custom text..."
}Snippet Resolution:
thematic_snippet: ["glabro"]→ Looks up "glabro" inthematic_rules.formsand uses itsprompt_snippetthematic_snippet: ["custom text"]→ Uses "custom text" as-is (not a form reference)thematic_snippet: ["form1", "form2"]→ Resolves multiple forms and combines them- No
thematic_snippet→ Only global thematic rules are applied
# List all available characters and refinements
python src/create_image.py myproject.json --list
# Generate prompts for all refinements of a character (default behavior)
python src/create_image.py myproject.json 1 --dry-run
python src/create_image.py myproject.json hero_name --prompt-only
# Generate prompt for a specific refinement
python src/create_image.py myproject.json 1:3 --dry-run
python src/create_image.py myproject.json hero_name:variant --dry-run
# Generate actual images (requires OpenAI API key)
$env:OPENAI_API_KEY = "your-key-here"
python src/create_image.py myproject.json 1 # All refinements for character 1
python src/create_image.py myproject.json hero_name:variant # Specific variant
# Copy prompt to clipboard (Windows)
python src/create_image.py myproject.json 1:1 --dry-run --copy
# Remove miniature base from prompt
python src/create_image.py myproject.json 1:1 --no-base
# Exclude generic or miniature rules
python src/create_image.py myproject.json 1:1 --no-generic
python src/create_image.py myproject.json 1:1 --no-miniature
# Generate reference sheets (multiple poses in one prompt)
python src/create_image.py myproject.json --page 1 --prompt-only --copy # First 9 poses
python src/create_image.py myproject.json --page 2 --prompt-only --copy # Poses 10-18
python src/create_image.py myproject.json --page all --prompt-only # All pages
# Example using the garou.json demo project
python src/create_image.py garou.json alpha:human --dry-run
python src/create_image.py garou.json --listfilename- JSON file to use (e.g.,garou.json,myproject.json)character- Character ID or path (positional or--character/-c)- Format:
1,alpha,1:2, oralpha:human - If only character specified (e.g.,
1oralpha), generates all refinements - If full path specified (e.g.,
1:2), generates only that specific refinement - Not required when using
--listor--reference-sheet
- Format:
--out- Output directory (default:./out)--model- OpenAI model (default:gpt-image-1)--size- Image size (default:1024x1024)
--dry-run- Print prompt only, don't call API--prompt-only- Alias for--dry-run--copy- Copy prompt to clipboard (Windows only)
--json, -j- Alternative way to specify JSON file (overrides positional filename)--list- List all available characters/refinements and exit--all- Generate all refinements for specified character (default behavior when no refinement path specified)--page, -p- Generate reference sheet for a specific page number (each page shows up to 9 poses)- Page 1: poses 1-9
- Page 2: poses 10-18
- Page 3: poses 19-27, etc.
- Use
allto generate all pages - Examples:
--page 1,--page 2,--page all
--no-miniature- Don't append miniature scale rules--no-base- Remove base/stand from miniature rules (keeps miniature styling)--no-generic- Don't append generic render rules
-
Copy the template
cp template.json myproject.json
-
Fill in generic_render_rules
- Add universal rendering requirements that apply to all prompts
- Keep these concise and focused on technical requirements
-
Add thematic_rules (optional)
- Add project-specific style guidance
- Theme, mood, or genre-specific rules
- Optionally define reusable forms in
thematic_rules.forms- Useful for standardizing variants (e.g., werewolf forms, armor types)
- Each form includes
description,anatomy, andprompt_snippet
-
Define characters
- Each character gets an
id(number) andname(string) - Add description and visual notes
- Create refinements array
- Each character gets an
-
Add refinements
- Each refinement is a variation (form, pose, etc.)
- Refinements can nest infinitely
- Each level inherits and extends parent rules
-
Test prompts
python src/create_image.py myproject.json --list python src/create_image.py myproject.json 1:1 --dry-run
- Generic rules: Keep concise and universal (lighting, camera, materials)
- Thematic rules: Project-specific style guidance (genre, mood, theme)
- Global snippet: Applied to ALL prompts automatically via
thematic_rules.prompt_snippet - Form definitions: Define reusable forms in
thematic_rules.formsfor consistency across characters - Example: All werewolf characters share the same 5 forms (human, glabro, crinos, hispo, wolf)
- Global snippet: Applied to ALL prompts automatically via
- Character prompts: Focus on unique identifying features specific to that character
- Refinement prompts: Add specific pose, action, or variation details
- Refinement thematic_snippet: Array of form references or custom snippets
- Use
["form_name"]to reference a form fromthematic_rules.forms - Use
["custom text"]for one-off snippets not defined as forms - Combine multiple:
["form1", "custom text", "form2"]
- Use
- Test combination: Ensure prompts combine well at each nesting level
- Use clear, descriptive names for characters and refinements
- Use underscores for multi-word names (
crow_eyed_one,powder_burn) - Keep IDs sequential for easy reference
- Document poses in the description field
The final prompt is constructed in this order:
- Character/refinement specific prompt (from refinement
promptfield) - Refinement thematic snippets (resolved from
thematic_snippetarray references) - Global thematic rules
prompt_snippet(applied to ALL prompts automatically) - Generic render rules (if not excluded with
--no-generic) - Miniature scale rules (if not excluded with
--no-miniature) - Additional flags (e.g.,
--no-baseadds "no base, no stand...")
Example for Alpha's Glabro form:
- Refinement prompt: "Glabro female -- enlarged hands, elongated jaw..."
- Thematic snippet:
["glabro"]→ resolved to "near-human hybrid with distinctly human features..." - Global thematic: "Old West frontier horror, evil werewolf pack, territorial and predatory"
- Generic rules: "single character, centered composition, full figure..."
- Miniature rules: "40mm scale tabletop miniature, hard plastic/resin model..."
This layering ensures consistent theming across all variants while allowing refinement-specific details.
The included garou.json demonstrates the system's capabilities with a complete Old West werewolf pack project.
- Alpha (The Iron Wolf) - Native American war leader
- Breaker (Beta) - European-American executioner
- Crow-Eyed One (Scout) - Silent hunter
- Long Shadow (Scout) - Endurance tracker
- Powder Burn (Hunter) - Gun-fighter outlaw
- Undertaker (Hunter) - Body arranger
- Red Howl (Hunter) - Berserker
- Bone-Singer (Elder) - Ritual keeper
- Lost Cub (Newblood) - Recently turned
The Garou pack uses standardized werewolf forms defined in thematic_rules.forms:
-
Human - Fully human form with subtle predatory tells
- Anatomy: human anatomy, human proportions
- Snippet: "fully human form, predatory stillness and unnatural gaze"
-
Glabro - Near-human hybrid form (the "almost human but wrong" state)
- Anatomy: enlarged hands and claws, elongated jaw with visible fangs, hunched posture, human-like feet (larger with clawed toes)
- Snippet: "near-human hybrid, enlarged hands and claws, elongated jaw with fangs, hunched posture, human-like feet (larger with clawed toes)"
-
Crinos - The war form (massive bipedal werewolf)
- Anatomy: towering bipedal werewolf, wolf-like head with elongated muzzle and massive fangs, powerful shoulders and chest, digitigrade legs
- Snippet: "massive bipedal werewolf war form, towering scale, full spiritual transformation"
-
Hispo - Dire-wolf form (massive prehistoric wolf)
- Anatomy: massive quadruped dire wolf, exaggerated shoulders and spine, oversized paws and jaws
- Snippet: "dire wolf form, massive quadruped, exaggerated shoulders and spine"
-
Wolf - Wolf form (near-natural but larger and unsettling)
- Anatomy: large wolf anatomy, slightly oversized compared to natural wolves, intelligent eyes
- Snippet: "large intelligent wolf, near-natural but larger and uncanny"
Each character's refinements reference these form definitions in their thematic_snippet to ensure consistency across all 9 characters.
# Alpha in Crinos form (by number)
python src/create_image.py garou.json 1:3 --dry-run
# Alpha in human form (by name)
python src/create_image.py garou.json alpha:human --dry-run
# All forms for the Lost Cub (default behavior when no form specified)
python src/create_image.py garou.json 9 --dry-run
python src/create_image.py garou.json lost_cub --dry-run
# Breaker in wolf form with no base
python src/create_image.py garou.json breaker:wolf --no-base --dry-run- Python 3.10+
- OpenAI Python SDK (
pip install openai) - OpenAI API key (for actual image generation)
Error: "Character not found"
- Check available characters with
--list - Verify spelling of character names
- Character names are case-insensitive
Error: "Refinement not found"
- Use
--listto see available refinements for each character - Check spelling and ensure the refinement exists
Error: "OPENAI_API_KEY is not set"
- Set the environment variable:
$env:OPENAI_API_KEY = "your-key" - Use
--dry-runto test without API key
- Support for deeper nesting (pose level:
1:1:1) - Import/export between formats (JSON ↔ Markdown)
- Batch generation with progress tracking
- Template validation and linting
- Multi-view generation (front/side/top)