Back to list
KvFxKaido

portrait

by KvFxKaido

Tactical, Relationship-Driven TTRPG with AI Game Master - 11 factions, narrative choices, consequence tracking

0🍴 0📅 Jan 25, 2026

SKILL.md


name: portrait description: Generate character portraits using Gemini NanoBanana. Reads from character YAML and calls gemini directly with full guardrails. allowed-tools: Bash, Read, Glob, Write user-invocable: true proactive: false

Portrait Generation

Generate character portraits using Gemini's NanoBanana extension. Reads character appearance from YAML files and builds explicit prompts with all guardrails to prevent style drift.

Portraits are campaign-specific - each campaign has its own portrait set in portraits/campaigns/{campaign_id}/.

Usage

/portrait <character_name>
/portrait cipher
/portrait elder_kara
/portrait vex --regenerate

How It Works

  1. Determine current campaign ID from bridge API or config
  2. Read the character YAML from campaign-specific folder (fall back to global)
  3. Build an explicit prompt with all guardrails
  4. Call gemini --yolo -e nanobanana directly via Bash
  5. Handle the nanobanana-output fallback if needed
  6. Report success with the file path

Step 0: Get Current Campaign ID

First, get the current campaign ID. Check the bridge API:

curl -s http://localhost:3333/state | python -c "import json,sys; d=json.load(sys.stdin); print(d.get('sentinel',{}).get('campaign',{}).get('id',''))"

If bridge isn't running, check the config file:

cat C:/dev/SENTINEL/sentinel-agent/campaigns/.sentinel_config.json

The last_campaign field contains the campaign ID. If no campaign is loaded, ask the user to load one first.

IMPORTANT: Store the campaign ID - you'll need it for all paths.

Step 1: Find and Read Character YAML

Look for the character file in this order:

  1. Campaign-specific: C:\dev\SENTINEL\assets\characters\campaigns\{campaign_id}\{name}.yaml
  2. Legacy global: C:\dev\SENTINEL\assets\characters\{name}.yaml

If not found in either location, ask the user if they want to create one.

Step 2: Build the Prompt

Required Structure

Cinematic portrait, photorealistic digital art style.
Modern post-apocalyptic cyberpunk aesthetic. NOT fantasy, NOT medieval, NOT anime, NOT elf, NOT blue hair.
[EXPLICIT_PERSON_DESCRIPTOR] with [BUILD] build, [HAIR_DESCRIPTION], [EYE_DESCRIPTION], [FACIAL_FEATURES], [DISTINGUISHING_MARKS], [EXPRESSION].
[FACTION] [ROLE] survivor. [FACTION_GEAR].
Dark atmospheric background with [FACTION_COLOR] accent lighting.
High detail, dramatic rim lighting, shallow depth of field.
Bust framing, 3/4 angle, looking slightly off-camera.
Save the image to C:\dev\SENTINEL\sentinel-ui\public\assets\portraits\campaigns\{campaign_id}\{name}.png

NOTE: Always use the campaign-specific path for saving.

Person Descriptor Mapping (CRITICAL)

Build explicit descriptors to anchor generation. DO NOT use vague terms.

Skin ToneGender: MasculineGender: FeminineGender: Androgynous
palepale-skinned white manpale-skinned white womanpale-skinned person
lightlight-skinned white manlight-skinned white womanlight-skinned person
mediumolive-skinned manolive-skinned womanolive-skinned person
tantan Latino mantan Latina womantan person
brownBlack manBlack womanBlack person
darkdark-skinned Black mandark-skinned Black womandark-skinned Black person

For elderly characters, prepend "elderly" (e.g., "elderly olive-skinned woman").

Faction Colors

FactionColorHexGear Description
nexusblue#00A8E8Data visors, sensor arrays, sleek tech fabric
ember_coloniesorange#E85D04Salvaged leather, wool layers, fire-scarred gear
latticeyellow#FFD000Work gear, tool belts, utility harness
convergencepurple#7B2CBFBio-tech integration, visible augmentations
covenantwhite#E8E8E8Clean white/silver cloth, formal bearing
wandererstan#C9A227Dust cloaks, travel packs, road-worn appearance
cultivatorsgreen#2D6A4FNatural fibers, soil-stained hands
steel_syndicategunmetal#5C677DHeavy armor layers, tactical gear, intimidating
witnessessepia#8B4513Document satchels, ink-stained fingers
architectscyan#0077B6Pre-collapse uniforms, credential badges
ghost_networksblack#0D0D0DNondescript dark clothing, deep shadows

Expression Mapping

YAML ValuePrompt Description
neutralcalm alert expression
warywary guarded expression
warmwarm approachable expression
sternstern serious expression
tiredtired world-weary expression

Step 3: Execute Generation

First, ensure the campaign portrait directory exists:

mkdir -p "C:/dev/SENTINEL/sentinel-ui/public/assets/portraits/campaigns/{campaign_id}"

Then run the generation:

gemini --yolo -e nanobanana "Generate a portrait image: [FULL_PROMPT]"

Use a 3-minute timeout (180000ms).

Step 4: Handle Output

NanoBanana sometimes saves to nanobanana-output/ instead of the requested path.

  1. Check if file exists at sentinel-ui/public/assets/portraits/campaigns/{campaign_id}/{name}.png
  2. If not, check nanobanana-output/ for recent PNG files
  3. Move the most recent one to the correct location:
    mv "C:/dev/SENTINEL/nanobanana-output/[filename].png" "C:/dev/SENTINEL/sentinel-ui/public/assets/portraits/campaigns/{campaign_id}/{name}.png"
    

Step 5: Report Result

Show the user the generated portrait using the Read tool on the PNG file.

Example: Full Prompt for Cipher (in campaign "cipher")

Character YAML (from assets/characters/campaigns/cipher/cipher.yaml):

name: Cipher
faction: nexus
role: analyst
gender: masculine
age: adult
skin_tone: brown
build: lean
hair_color: black
hair_length: short
hair_style: dreadlocks
eye_color: augmented
facial_features: [sharp, high cheekbones]
augmentations: subtle blue data overlay in eyes, small temple implant
other_features: always wears a data visor
default_expression: neutral

Generated prompt:

Cinematic portrait, photorealistic digital art style.
Modern post-apocalyptic cyberpunk aesthetic. NOT fantasy, NOT medieval, NOT anime, NOT elf, NOT blue hair.
Black man with lean build, short black dreadlocks, cybernetic eyes with subtle blue data overlay, sharp features, high cheekbones, small temple implant, always wears a data visor, calm alert expression.
Nexus analyst survivor. Data visors, sensor arrays, sleek tech fabric.
Dark atmospheric background with blue (#00A8E8) accent lighting.
High detail, dramatic rim lighting, shallow depth of field.
Bust framing, 3/4 angle, looking slightly off-camera.
Save the image to C:\dev\SENTINEL\sentinel-ui\public\assets\portraits\campaigns\cipher\cipher.png

Error Handling

  • No campaign loaded: Ask user to load a campaign first with /load <name>
  • YAML not found: Ask user if they want to create one with /portrait create {name}
  • Gemini not available: Report error, suggest checking Gemini CLI installation
  • Generation fails: Show error output, suggest retrying
  • Wrong style generated: Regenerate with stronger guardrails (add more NOT constraints)

Creating New Characters

If the user wants to create a new character:

  1. Ask for the key details (or use the table format from create_character.py)
  2. Create the YAML file in assets/characters/campaigns/{campaign_id}/{name}.yaml
  3. Generate the portrait

Or direct them to run:

python scripts/create_character.py

Score

Total Score

70/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

+10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

Reviews

💬

Reviews coming soon