Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Generates/edits filmmaking canvas images via generate_image.js and generate_image_pro.js. Use before image CLIs for character/location design, refs, starting frames, storyboards, stills, edits, variations, and downstream video anchors. Video-bound characters default to Pattern 7 4-panel sheets; one-off static portraits use Pattern 1. Story/script breakdowns should create detailed location anchors plus material character/location variants. Storyboards use Pattern 6: one pro composite mosaic per c
.claude/skills/utopai-research-image-compose/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-11 | ✗→✓ | ▲ Improved | 225% | 0% |
| case-12 | ✗→✓ | ▲ Improved | 121% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 141% | 0% |
| case-01 | ✗→✓ | ▲ Improved | 164% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 417% | 0% |
Standard tier:
node "$PAI_REPO_ROOT/server/cli/generate_image.js" --prompt "..." [--aspect-ratio 16:9] [--image-size 2K] [--label "..."] [--subtype <character|location|edit|reference|split|storyboard>] [--name "..."] [--role "..."] [--description "..."] [--source-node-id <id>] [--ref-source-id <id> ...]Pro tier for storyboard mosaics and video-bound character sheets:
node "$PAI_REPO_ROOT/server/cli/generate_image_pro.js" --prompt "..." --size 2560x1440 [--label "..."] [--subtype <character|location|edit|reference|split|storyboard>] [--name "..."] [--role "..."] [--description "..."] [--source-node-id <id>] [--ref-source-id <id> ...]Pro accepts --size only; no --aspect-ratio / --image-size. Common sizes: 1024x1024, 1280x720, 720x1280, 1920x1920, 2560x1440, 1440x2560, 3840x2160, 2160x3840.
--label defaults to the truncated prompt (≤30 chars) if omitted; pass an explicit one when you have a better caption.
Use @Image1, @Image2, … in --ref-source-id order. The CLI emits one derived edge per ref.
Mirror external URLs first with mirror_url.js --url <URL>, then pass the returned node_id via --ref-source-id.
If a note authored the image, pass --source-node-id <note_id>.
Do not attempt to invent images via ASCII art or markdown embedding — call the CLI.
For the ask-once flow and per-mode prices, see the project PROJECT_AGENT.md § "First-use generation choices".
Mode mapping: Standard 2K -> generate_image.js --image-size 2K; Pro 2K -> pro exact 2K; Max quality -> pro exact 4K.
Pick the one that fits. For source lookup, follow the project PROJECT_AGENT.md § "Choosing context"; this skill only owns image-specific prompt and CLI shape.
Character pre-flight. First ask: will this character appear in downstream video (video, clip, promo, 宣传片, 短片, 连续剧, film, scene, 拍片, shot, short film)?
workflow.json for uploaded refs (subtype:"reference", metadata.source:"user_upload", not archived).This pre-flight is non-negotiable. Pattern 1's single front portrait gives the video model an anchor that's too narrow; identity drifts shot-to-shot. Skipping straight to Pattern 1 for video work is the single most-common mistake.
Story/script anchor defaults. When script-compose or story-to-video-workflow routes a breakdown here:
Triggers: character portrait/headshot/hero/villain/lead only for one-off static stills. Video-bound -> Pattern 7.
node "$PAI_REPO_ROOT/server/cli/generate_image.js" --prompt "..." --aspect-ratio 9:16 --image-size 2K --subtype character --name "Detective Morris" --role "..." --description "..." — no refs. A character is an identity anchor, not a derivative.> [style] character portrait of [NAME], [role]. [age, build, wardrobe, distinguishing features]. Front-facing medium close-up, eye-level, looking directly at camera, neutral expression. Plain neutral background, soft even lighting. No dramatic shadows, no stylized lighting, no side profile, no multiple views.
--ref-source-id.Triggers: establish/design/picture a location, or approval of a script-compose location offer.
node "$PAI_REPO_ROOT/server/cli/generate_image.js" --prompt "..." --aspect-ratio 16:9 --image-size 2K --subtype location --name "Causeway" --description "..." [--source-node-id <script_or_shot_note_id>] — no refs. A location is a setting anchor, not a derivative.> [style] establishing still of [LOCATION NAME]. [visual brief — architecture, lighting, atmosphere]. Wide shot, eye-level, no characters present.
--source-node-id so the authorship edge lands.Triggers: change/edit/swap/replace/add/remove/tweak/what-if/variation on an existing image.
image_result, or one the user named). Grab source.id and source.metadata.aspect_ratio.node "$PAI_REPO_ROOT/server/cli/generate_image.js" --prompt "..." --aspect-ratio <source ratio> --image-size <source size or 2K> --subtype edit --source-node-id <source.id> --ref-source-id <source.id>.> <concrete change>. Preserve everything else.
✅ "Change the rain to falling snow. Keep the detective, wardrobe, and camera framing unchanged." ✅ "Render as a full 3D turnaround sheet of the same character. Preserve face, wardrobe, and proportions." ❌ "A detective in a snowy alley at night wearing a trench coat…" — over-specifies, identity drifts.
<source.id> based on --ref-source-id.Triggers: put character in setting / shot of X and Y / character action in location.
image_result of that person (up to 16). Collect each one's id.node "$PAI_REPO_ROOT/server/cli/generate_image.js" --prompt "..." --aspect-ratio <fit the shot> --image-size 2K --ref-source-id <char1.id> --ref-source-id <char2.id> ....@Image1, @Image2, … in --ref-source-id order.--subtype — a scene is neither a character nor an edit. CLI emits one derived edge per --ref-source-id.Triggers: a fresh image unrelated to existing canvas content ("generate a mountain at dusk", "a noir alley — just the setting").
node "$PAI_REPO_ROOT/server/cli/generate_image.js" --prompt "..." with sensible defaults (16:9, 2K unless the user asks otherwise). No subtype, no refs.Triggers: storyboard, mosaic, grid, shot list, coverage, keyframe sheet, shot planning, image previs. Output is ONE composite per clip/<=15s shot note, not one image per panel.
generate_image_pro.js --size 2560x1440 --subtype storyboard --label "Storyboard — Shot <N>" --source-node-id <shot_note_id> per mosaic.2560x1440; grid shape is cell layout, not canvas shape. Override only for explicit portrait/square/vertical/ratio:2560x1440 (default)1920x19201440x25601440x2560For the canvas pre-flight, per-shot-note iteration logic, missing-anchor nudge, verbatim prompt template, and default panel coverage when no script slice exists: see references/storyboard-mosaic.md.
image_result node PER mosaic.data.subtype = "storyboard" by passing --subtype storyboard.Use proactively for any character that will appear in downstream video, regardless of actor refs.
Mode A — ≥3 uploaded actor refs. Pass photos as --ref-source-id; add --source-node-id <note_id> if a script/shot authored the design.
Mode B — 0-2 refs / from scratch. Omit actor refs; describe age/build/wardrobe/distinguishing features explicitly. Add --source-node-id <note_id> when authored by a note.
Also fires on explicit asks: "design a character sheet / turnaround / reference sheet / character design for character]", "make a 4-panel character design", "generate a production reference sheet for downstream video work".
Output: one Front-full / Profile-full / Back-full / Closeup-bust sheet, passed directly to video as --ref-source-id.
subtype:"reference", ideally ≥3 photos). Confirm ref count in one line.node "$PAI_REPO_ROOT/server/cli/generate_image_pro.js" --prompt "..." --size 2560x1440 --subtype character --name "<character_name>" --role "..." --ref-source-id <ref1> --ref-source-id <ref2> --ref-source-id <ref3> [--source-node-id <script_or_shot_note_id>] — pro tier is the default for character sheets because panel layout, text suppression, and identity consistency are load-bearing. Do not pass --aspect-ratio or --image-size. Never fire Mode A with fewer than 3 refs (model overfits to the one angle it has).references/character-sheet.md: same pro command, but omit every actor-photo --ref-source-id; include --source-node-id only when a script or shot note authored the design.--ref-source-id <sheet_id> for downstream shots; no normal cropping needed.For the verbatim 4-panel prompt template, optional per-angle crops, and gotchas (no-text rule, photo-priority, exact panel counts): see references/character-sheet.md.
image_result node with data.subtype = "character".data.name, data.role, data.description from the CLI flags.derived edge per --ref-source-id (so the sheet is provenance-linked to each actor photo it triangulated from).For draft-stage JSON, one sentence with the price/status — see the project PROJECT_AGENT.md § "Draft gate". For terminal results, run the alignment check before the next-step recommendation — see the project PROJECT_AGENT.md § "Prompt alignment check".
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-11 | fail→pass | 7,796 | 6,549 | -16% | 1 | 1 | 0% | 1,300 | 4,229 | +225% | 0 | 0 | — |
case-12 | fail→pass | 13,380 | 7,259 | -46% | 1 | 1 | 0% | 2,088 | 4,621 | +121% | 0 | 0 | — |
case-05 | fail→pass | 11,295 | 7,802 | -31% | 1 | 1 | 0% | 1,927 | 4,635 | +141% | 0 | 0 | — |
case-01 | fail→pass | 11,060 | 7,720 | -30% | 1 | 1 | 0% | 1,793 | 4,740 | +164% | 0 | 0 | — |
case-02 | fail→pass | 5,430 | 9,171 | +69% | 1 | 1 | 0% | 790 | 4,087 | +417% | 0 | 0 | — |
case-03 | fail→pass | 6,311 | 4,134 | -34% | 1 | 1 | 0% | 1,017 | 3,951 | +288% | 0 | 0 | — |
case-04 | fail→pass | 7,645 | 3,143 | -59% | 1 | 1 | 0% | 1,269 | 3,794 | +199% | 0 | 0 | — |
case-06 | fail→pass | 5,873 | 3,132 | -47% | 1 | 1 | 0% | 987 | 3,731 | +278% | 0 | 0 | — |
case-07 | fail→pass | 4,846 | 4,910 | +1% | 1 | 1 | 0% | 798 | 4,148 | +420% | 0 | 0 | — |
case-08 | fail→pass | 9,174 | 4,665 | -49% | 1 | 1 | 0% | 1,654 | 4,073 | +146% | 0 | 0 | — |
case-09 | fail→pass | 6,634 | 3,037 | -54% | 1 | 1 | 0% | 1,022 | 3,715 | +264% | 0 | 0 | — |
case-10 | fail→pass | 14,928 | 8,709 | -42% | 1 | 1 | 0% | 2,761 | 4,916 | +78% | 0 | 0 | — |
case-13 | fail→pass | 12,058 | 5,188 | -57% | 1 | 1 | 0% | 1,961 | 4,121 | +110% | 0 | 0 | — |
case-14 | fail→pass | 5,478 | 6,565 | +20% | 1 | 1 | 0% | 985 | 4,559 | +363% | 0 | 0 | — |
case-15 | fail→fail | 18,977 | 10,076 | -47% | 1 | 1 | 0% | 2,925 | 4,816 | +65% | 0 | 0 | — |
case-16 | pass→pass | 9,633 | 6,297 | -35% | 1 | 1 | 0% | 1,534 | 4,513 | +194% | 0 | 0 | — |
case-17 | fail→pass | 9,943 | 4,047 | -59% | 1 | 1 | 0% | 1,729 | 4,004 | +132% | 0 | 0 | — |
case-18 | fail→pass | 11,546 | 2,755 | -76% | 1 | 1 | 0% | 2,189 | 3,605 | +65% | 0 | 0 | — |
case-19 | fail→pass | 12,300 | 2,953 | -76% | 1 | 1 | 0% | 1,028 | 3,702 | +260% | 0 | 0 | — |
case-20 | pass→pass | 16,136 | 9,397 | -42% | 1 | 1 | 0% | 2,255 | 4,263 | +89% | 0 | 0 | — |
case-21 | pass→fail | 7,871 | 13,282 | +69% | 1 | 1 | 0% | 1,318 | 5,754 | +337% | 0 | 0 | — |
case-22 | pass→pass | 11,305 | 7,617 | -33% | 1 | 1 | 0% | 943 | 4,200 | +345% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +73 percentage points is the difference between those two pass rates over the 22 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.