From summer
Generates a single polished bust/portrait of a character for dialogue UI, character-select screens, lore cards, or codex entries. One character, locked composition, VN-style.
How this skill is triggered — by the user, by Claude, or both
Slash command
/summer:character-portraitassets/**art/portraits/**ui/portraits/**This skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
This skill produces ONE polished character portrait — bust or shoulders-up framing, neutral or stylized background, designed to drop into a dialogue UI, character-select screen, or lore card. It is the **opposite** of `summer:2d-assets/concept-art`: concept art explores; this skill commits.
This skill produces ONE polished character portrait — bust or shoulders-up framing, neutral or stylized background, designed to drop into a dialogue UI, character-select screen, or lore card. It is the opposite of summer:2d-assets/concept-art: concept art explores; this skill commits.
The single biggest failure mode is inconsistency across a cast. Generating five party members one at a time without a locked anchor produces five images that look like they're from five different games — different lighting, different angle, different palette, different rendering style. This skill makes you write a locked anchor suffix the first time and re-use it verbatim for every subsequent portrait.
If the user is still exploring the look, this is the wrong skill — route to summer:2d-assets/concept-art first, lock a direction, then come back here. The summer:asset-pipeline/asset-strategy meta-router asks "Quick check — exploring the look (3-4 variants for art direction) or generating a final character portrait for dialogue UI?" to disambiguate.
summer:2d-assets/concept-art.summer:2d-assets/pixel-art.summer:asset-pipeline/asset-strategy.referenceImageUrl for each expression.Check .summer/portrait-anchor.md first.
Read .summer/portrait-anchor.md
If it doesn't exist, this is the first portrait in the cast — you must define the anchor now. Ask the user (or infer from .summer/GameSoul.md):
Write the anchor to .summer/portrait-anchor.md:
## Portrait anchor (re-use verbatim for every cast member)
framing: bust, shoulders to crown of head visible
angle: three-quarter view, slight turn to character's left
lighting: soft warm key from upper right, cool fill from left, gentle rim
background: muted painterly gradient, dark teal to deep brown, no scene detail
style: semi-realistic painterly, soft edges, oil-painting feel
aspect: portrait_4_3
Every subsequent portrait in this cast appends the anchor to the prompt verbatim. Do not edit the anchor mid-cast unless the user explicitly says "I want the new ones to look different."
summer_search_assets(query="<character name> portrait", filter={ kind: "image" })
Reuse beats regenerate. If the user wants to iterate on an existing one, pull its URL and pass it as referenceImageUrl for img2img.
Pattern:
<character description>. <anchor framing/angle/lighting/background/style>
The character description should include: identity (age, build, hair, distinctive features), expression, costume/equipment, any signature prop. Keep it under 60 words including the anchor.
Generating Aria the witch portrait — 1 image, ~$0.02, model nano-banana-2, anchor locked from
.summer/portrait-anchor.md. OK?
summer_generate_image(
prompt="Aria, young witch, mid-twenties, pale skin, long black hair with silver streak, sharp green eyes, half-smile, wearing dark indigo robes with silver embroidery, raven on shoulder. <anchor verbatim>",
model="nano-banana-2",
style="none",
options={ image_size: "portrait_4_3" }
)
style: "none" because the anchor's "semi-realistic painterly" already specifies style; the preset would fight it.
summer_import_from_url(
url="<fileUrl from generation>",
path="res://ui/portraits/aria.png"
)
For dialogue UI nodes, wire the texture into a TextureRect:
summer_set_resource_property(
nodePath="/root/UI/DialogueBox/PortraitRect",
resourceProperty="texture",
value="res://ui/portraits/aria.png"
)
For character-select with multiple portraits, name files consistently: aria.png, borin.png, cael.png, dara.png. Index-able from code via "res://ui/portraits/%s.png" % character_id.
If the user wants the portrait tweaked ("smaller smile", "darker robes"), use img2img with the existing image as referenceImageUrl. Preserves identity and lighting.
summer_generate_image(
prompt="<original prompt> with a smaller, more subtle smile",
referenceImageUrl="<previous fileUrl>",
model="nano-banana-2",
style="none"
)
| Goal | Prompt skeleton (subject part only — append anchor verbatim) | Why |
|---|---|---|
| Generic NPC | <name>, <age> <build>, <hair>, <eyes>, <expression>, wearing <costume> | Identity-first; no scene context |
| Hero / protagonist | <name>, <age> <build>, <hair>, <distinctive feature>, confident <expression>, wearing <signature outfit>, holding <signature prop> | Adds prop for memorability |
| Antagonist | <name>, <imposing detail>, <unsettling expression>, wearing <costume with menacing detail>, <signature scar/mark> | Antagonists need visual asymmetry |
| Lore card / king | <name>, <age>, regal <expression>, wearing <ornate detail>, <crown/insignia>, formal portrait pose | Formal pose overrides anchor's three-quarter |
| Expression variant | <previous prompt> with <new expression: angry / surprised / sad / laughing> + referenceImageUrl: <base portrait> | img2img preserves identity |
| Younger / older variant | <character> as a <child / elder> + referenceImageUrl: <base> | For flashback / time-skip portraits |
| Bad | Failure mode |
|---|---|
cool warrior portrait | No identity, no anchor. Returns generic stock art. |
the witch but make her sad (no img2img ref) | Without referenceImageUrl, you get a different witch who is sad. Identity drift. |
| Anchor inconsistent across cast | Each portrait looks like a different game. The cast doesn't read as a cast. |
full body portrait | "Portrait" implies bust. If you want full body, say so explicitly AND switch to image_size: "portrait_4_3" framed full-body — but that's a different asset class; consider concept-art or 3D pipeline. |
transparent background for a painterly portrait | Painterly + transparent fails on most models. Use a flat or gradient background, then alpha-cut in an editor if you must. |
referenceImageUrl.summer:asset-pipeline/asset-strategy.style: "realistic" or "cartoon" when the anchor already names a style. The preset overrides the anchor.aria_traveler.png, aria_robes.png, aria_armored.png) and switch by index. Use img2img from the base for consistency.summer:2d-assets/pixel-art.Print the prompt and the call:
summer_generate_image(prompt="<character + anchor>", model="nano-banana-2", style="none", options={ image_size: "portrait_4_3" })
Tell the user to run via the Summer dashboard, then summer_import_from_url the result to res://ui/portraits/<name>.png.
After the portrait is wired:
referenceImageUrl set to the base portrait.summer:2d-assets/pixel-art.summer:asset-pipeline/asset-strategy (the portrait is NOT a usable 3D reference; generate a separate T-pose).summer:scene-composition for the UI hierarchy.summer:2d-assets/concept-art — explore the look first if not yet locked.summer:asset-pipeline/asset-strategy — meta-router and the 3D pipeline.summer:scene-composition — wiring the portrait into a dialogue UI scene.references/mcp-tools-reference.md — summer_generate_image parameter schema.npx claudepluginhub summerengine/summer-engine-agent --plugin summerGenerates a magazine-style character sheet from a portrait URL or base64 image, with optional short description for name/age/vibe hints.
Creates production-ready character design sheets for animation, games, or comics: orthographic turnarounds, expression sheets, proportion guides, and costume/accessory callouts.
Writes Midjourney prompts that keep a character's face, build, clothing, and presence consistent across multiple images for editorial series, podcast artwork, YouTube thumbnails, or visual narratives.