| name | vermilion-sketch |
| description | Turn a photo into a minimalist East Asian zen ink sketch: a few black brush strokes with dry-brush ends on rough embossed watercolor paper, the subject alone on empty sheet, and one small vermilion-red accent. Keeps the subject's pose and placement, strips everything else. Use whenever a user wants a photo turned into a 'zen sketch', 'ink line sketch', 'minimal ink drawing', 'brush line art', a red-accent Japanese/Chinese minimal illustration, or attaches a photo and says 'make it that simple ink style', including batches and illustrations for wallpapers, posts, slides or covers. Chinese triggers: 简笔画、禅意简笔画、水墨简笔画、极简线稿、毛笔线描、一抹红、把照片画成简笔画. Works with the host's built-in image tool (Codex, ChatGPT, Doubao, Gemini) or through any OpenAI-compatible image API that accepts several input images (gpt-image-2). |
Vermilion Sketch
Redraw a photo as a minimalist zen ink sketch: black brush-pen lines with varied weight and dry-brush ends, drawn on
cool off-white watercolor paper whose embossed tooth is clearly visible, the subject alone with generous empty paper,
and one vermilion-red motif shown as a few small stamp-like dabs. The core of the style is subtraction plus one
decision: what stays, how many strokes it gets, and where the single red goes.
Style anchors live in assets/style-refs/ (two reference sketches that are sent to the model with every request)
and finished results in assets/examples/. When unsure whether a result looks right, compare against them first;
the details are in references/style-guide.md.
Language
Reply in the language the user used in their first message of the conversation, and keep it for the whole session
even if later messages contain English paths, prompts or script output. Prompts sent to the image model and the
Subject Brief are always English.
How it gets invoked
- Claude Code / Open Design:
/vermilion-sketch process this photo, with the image dragged into the terminal (it becomes a
path) or a path typed in. In Codex: $vermilion-sketch ....
- If the user only says "process this" or "make it that style", run the full default pipeline without asking:
aspect follows the subject, the agent picks the red and the stroke budget, one image per photo. Ask one plain-text
multiple-choice question only when the photo has two or more equally plausible subjects.
- If the user pasted an image without a file path (common in Claude Code): look at it and write the brief first,
then ask for the file (drag it into the terminal or give a path). The script needs a file on disk.
Workflow
0. Confirm an image backend first (ten seconds; don't let the user wait until the end to discover nothing is configured)
- Host with a built-in image tool that accepts several reference images (Codex, ChatGPT, Doubao, Gemini): go to
step 2A; no configuration needed.
- Other hosts: run
python3 "$SKILL/scripts/sketch.py" --doctor. If it passes, continue. If it fails, no image API
is configured yet: run python3 "$SKILL/scripts/sketch.py" --open-env (creates a commented .env from
.env.example and opens it in the system editor), then tell the user in plain text, in their language, no forms:
No image backend is configured yet. I created and opened the config file <absolute path>/.env; the comments explain each line:
- You have an OpenAI-compatible image API (302.AI, OpenAI, any relay): fill section A with the key, base URL and model name.
- You have your own image-generation command: fill the single line in section B.
- Neither: reply "3" and I will hand you a prompt plus the two reference sketches for a web image tool.
Save the file and reply "done".
When the user replies "done", run --doctor --ping; continue if it passes, otherwise translate the doctor output into
plain language and say which line to fix. If the user pastes the key into the chat, write it into .env yourself
(chmod 600) and remind them not to commit the file. "3" means the script-free path in references/prompt-recipe.md.
Users who prefer a terminal Q&A can run --setup themselves (key input is hidden). The agent's own shell has no
interactive terminal, so never try to run --setup on the user's behalf.
1. Look at the photo and write the Subject Brief
Actually look at the photo with Read; never guess from the filename. Then write the brief as a JSON file next to
the output (<subject>.brief.json, English values; schema and four real examples in
references/prompt-recipe.md). The brief holds every decision; the image model only executes it.
- subject / silhouette / key_features: what the user named > the largest, clearest nameable thing in the frame >
people and animals before objects > objects before environment. Describe the pose, facing direction and the 2–4
features that make it recognisable; the model drifts toward a generic version otherwise.
- red_accent — you decide, never the model: one vermilion motif,
count pieces (1–5), each where spelled out,
and rest naming what stays black. Choose the motif in this order: a small thing already red or warm in the photo
(lantern, blossom, bell, collar, ribbon) > a natural small focal point (sun, moon, one fruit, one bird) > the
smallest, most distant part of the subject (a far tower in fog) > fallback: a small low sun. If the whole subject
is red (a red bridge, a pink lotus) draw it black and put red on its smallest part only. Count: one focal
element = 1; a pair or small group = 2–3; scattered pieces = 3–5. count: 0 for a pure black sketch when the
user asks for no red.
- stroke_plan — you decide, never the model: list the parts worth drawing and give each an exact count and
strokes-each (normally 1 contour). The references carry 60–80 strokes; never plan under 15 or the result is an
icon. Ranges: a single animal 15–25, landscape 20–40, architecture 25–45; repeated units (petals, tiles, leaves,
cables) keep the number the photo shows, up to about 30. Texture is forbidden at every budget; the budget only
says how many things are drawn.
- composition: where the subject sits and how much sheet it fills; keep the photo's placement unless it fights
the style. aspect: 3:4 for flowers, people, buildings, hanging branches; 4:3 for animals in profile and wide
scenes; 1:1 otherwise; a user-specified aspect wins.
- drop: be blunt and complete: the town, the bridge, the reflections, the sky colour, the fur texture.
User instructions override any field ("red on the lantern", "three red spots", "no red", "simpler", "richer").
2. Generate: does the host have a built-in image tool?
2A. Host with a built-in image tool (Codex, ChatGPT, Doubao, Gemini, or an agent with an image-generation MCP):
no API needed.
- Get the exact prompt with
python3 "$SKILL/scripts/sketch.py" --image photo.jpg --brief photo.brief.json --dry-run --prompt-out prompt.txt
(costs nothing; if Python is unavailable, assemble it by hand from the blocks in references/prompt-recipe.md).
- Hand the tool the photo first and then the two sketches from
assets/style-refs/ as references, choose the
aspect from the brief, paste the prompt. The paper texture comes from the references, so attach them whenever the
tool allows. If the tool takes only one image, rerun --dry-run with --no-style-ref so the prompt carries the
words-only paper description, and expect a flatter paper.
- If the tool has a "high fidelity to the reference" switch, leave it off unless the subject drifts.
2B. Local script + image API (Claude Code, Open Design and other hosts without built-in generation):
SKILL=<this skill's directory>
python3 "$SKILL/scripts/sketch.py" --image photo.jpg --brief photo.brief.json --out outputs/red-fox-sketch.png
- The default backend is an OpenAI-compatible image-edit endpoint (
/v1/images/edits) with three input images:
the photo, then the two style references. The prompt is saved next to the output as .prompt.txt.
- Default quality is
medium (about ¥0.34 / $0.05 per 1536x1152 image on 302.AI, 35–60 s); it is enough for this
style. Use --quality low while iterating on a brief and high only for a final print. Say the expected cost
before a batch.
- If polling is interrupted, do not regenerate: the script prints a task id on submission, and
--resume <task_id> --image photo.jpg --out ... fetches the finished result at no extra cost.
- Open Design's own
media generate accepts a single input image and cannot attach the references; use any
OpenAI-compatible key through the script instead.
3. Quality check
Look at the result with Read and compare it against assets/examples/ and the anti-patterns in
references/style-guide.md. Repair with --extra "..." (appended to the prompt), one change per round, at most two
rounds:
| Symptom | Fix |
|---|
| Background, ground, sky or horizon came back | --extra "Absolutely no scenery, ground plane, sky or horizon; only the listed parts on empty paper." |
| Fur, feathers, veins, hatching or shading appeared | Name the texture: --extra "No fur texture at all: the body is a single clean contour." |
| Too sparse, looks like an icon (the lotus became an eight-petal symbol) | Raise stroke_plan.total and the repeated-unit count in the brief; add "as many petals as the photo shows" |
| Red on more spots than planned, or a red gradient | Make where name each spot and rest name the others explicitly; --extra "Red on those spots only; every other part is black." |
| Red sun appeared although the brief asked for something else | Keep count exact and add rest: "no sun, no other red element" |
| Paper flat and white, no tooth | The references were not attached; attach them, or run scripts/paper_relief.py in.png out.png --strength 0.6 --bump 14 (needs Pillow) as a last resort |
| Paper looks like a stucco wall with perspective | Remove any "heavily textured / handmade paper" words from extra; keep "flat top-down scan" |
| Subject changed species, breed or model | Make key_features more specific and try --input-fidelity high |
| Grey wash or soft ink-painting look | --extra "Crisp black lines only, no grey, no wash, no soft edges." |
On hosts that cannot run the script, judge by eye against the same examples and anti-patterns.
4. Deliver
Tell the user, in their language: the path of the sketch (<subject>-sketch.png), what you chose as the subject,
where the red went and why, roughly how many strokes you budgeted, what you dropped, and which backend was used.
Process several photos one at a time and name each file after its own subject; never call everything output.png.
Configuration (first use)
python3 "$SKILL/scripts/sketch.py" --open-env
python3 "$SKILL/scripts/sketch.py" --doctor --ping
Three kinds of backend, details in references/backends.md:
- OpenAI-compatible image API (302.AI, OpenAI, any relay): the default path; key, base URL and model name.
The model must accept several input images on
/v1/images/edits; gpt-image-2 does.
- Your own image command or agent tool: an
IMG_GENERATOR_CMD template in .env; the script fills the
placeholders (including {refs}) and runs it.
- A web image tool:
--dry-run --prompt-out prompt.txt produces the prompt; the user uploads the photo and the two
reference sketches and pastes it.
If no configuration can be found, never guess: show the user the --doctor output and .env.example.
Don'ts
- Writing the brief without looking at the photo, or applying a "filter" to the whole photo. If the background
stays, it is not this style.
- Leaving the red or the stroke budget to the model. It picks a red sun every time and either floods the sheet with
red dots or collapses the subject into an icon.
- Writing ranges into the prompt ("three to five", "at most 20"). Every number is
EXACTLY N plus what the rest does.
- Describing the paper in adjectives instead of attaching the references; "heavily textured handmade paper" turns
into a plaster wall.
- Adding things the photo doesn't have: a second animal, calligraphy, a seal, a frame, gold, glow, gradients.
- Using
--quality high by default.