CommunityImagegithub.com

comic-master-tooling

Comic-specific production tooling: using ComfyUI for consistent panels, vector lettering (balloons, tails, bursts, captions, SFX), detection on your own art, text on props like badges and signs, QA and page assembly. Use alongside comic-master.

What is comic-master-tooling?

comic-master-tooling is a Claude Code agent skill that comic-specific production tooling: using ComfyUI for consistent panels, vector lettering (balloons, tails, bursts, captions, SFX), detection on your own art, text on props like badges and signs, QA and page assembly. Use alongside comic-master.

Works with✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/quantiqueue/comic-skills/tree/HEAD/skills/comic-master-tooling

Installed? Explore more Image skills: steipete/songsee, affaan-m/frontend-design, mattpocock/improve-codebase-architecture · View all 6 →

Ask in your favorite AI

Open a new chat with this agent skill pre-loaded.

Documentation

Comic Master — Tooling

Companion to comic-master. That skill says what good pages look like; this one covers the tools that make them. Most bad lettering comes from bad tooling: hand-drawn raster ellipses, system fonts and text pasted flat over the art.

1. Panel art with ComfyUI

How to run ComfyUI itself (installing models, launching, running templates and workflows) belongs to the generic ComfyUI skills in vendor/comfy-cli-skills/ at the root of this repo. This section covers how to use them for comics.

1.1 A comic project's generation setup

  • Two workflows per project: text-to-image for new panels, image-edit for continuity fixes, matching shots and prop text. Pick them once, with one model and fixed settings, and record them in the project bible.
  • One panel = one job = one saved image. That makes every panel traceable to its prompt, seed and settings.
  • Size each render from the layout, not the other way round. Take the panel's box from the thumbnail and render at about 1 megapixel in that aspect ratio (e.g. 1408×704 wide, 768×1024 tall, 1536×640 strip). Then scale or crop into the box, keeping story-critical details away from the crop edges.
  • Batch by scene, not by page, so light, palette and backgrounds stay consistent across a scene's panels.

1.2 Consistency

  • Model sheet first. Generate a turnaround and expression sheet for each character, pick the best, and reuse it as the reference image (IP-adapter, image-edit input, or a character LoRA if you can train one).
  • Fixed anchors (comic-master comic-characters.md §4.5) word for word in every prompt, enumerated left to right; one style anchor for the whole project.
  • Seeds: record the seed of every accepted panel so it can be regenerated or varied.
  • Pose control: use an OpenPose or depth ControlNet when blocking matters (speaker order, eyelines, the 180° line).

1.3 Prompting rules that hold up

  • Know whether negatives work. Distilled models run at CFG 1 (FLUX.2 klein, Z-Image-Turbo) generally ignore the negative prompt. With them, state what you want positively ("exactly four people", "relaxed smooth brow"). Use negatives only with models run at real CFG, or add a negative-guidance node (e.g. NAG).
  • Prompt in the model's language. FLUX and Qwen/Z-Image read natural sentences; SDXL reads comma tags. For sentence models use a fixed order: shot and angle → each figure with position, left to right → the one action → expression as anatomy → setting → light → style.
  • Expressions as anatomy, never names. "Bored" tends to produce a scowl. Describe it instead: "upper eyelids half lowered, brows high and flat, mouth a closed flat line". Where negatives work, also negative-prompt the failure ("furrowed brow, scowling").
  • Costume colors inside the clause that names the body part ("navy bodysuit across the shoulders"). Close-ups drift toward generic colors; negative-prompt the drift color.
  • No duplicates: one anchor per figure, explicit count and order ("exactly three people: from left, …"), and, where negatives work, "duplicate characters, clone, extra people" in the negative.
  • Reserve text space in the prompt ("upper third is empty flat wall"). Ask for a clean, wordless image ("no text, no letters, no speech bubbles", in the negative where it works, otherwise phrased positively as "clean image without any lettering"), except in a deliberate prop-text edit pass.
  • Stage from the thumbnail. Turn the thumbnail into a rough block-out (stick figures, boxes for furniture) and feed it as a pose, lineart or depth control image, so cast placement, scale and who-is-in-the-room follow the plan.
  • Generate several, pick one. Render 3–4 seeds per panel and choose against the panel's GOAL and the anchors before any lettering.

1.4 Editing instead of re-rolling

Use the image-edit workflow with the existing panel as input:

  • Matching panels (same room, repetition gags, reaction shots): grade the earlier panel into the new one instead of generating from scratch.
  • Removal beats restaging. "Remove the second person at the table" works; "move him behind the chair" usually fails.
  • Continuity fixes: stray extras, wrong costume colors, a prop in the wrong hand. Inpaint or edit just that region.
  • Prop text (§4): a short word written onto a badge or sign, checked at 1:1.

1.5 Review before lettering

  • Compare every render with its anchors and the panel's GOAL: face, costume colors, props and hands, light direction, extra people, stray glyphs, empty text zone.
  • Keep a log per panel (prompt, seed, settings, accepted or rejected and why) so fixes are reproducible.

1.6 Recommended model setups

8 GB VRAM (the working default):

JobModel and filesNotes
Panels and editsFLUX.2 [klein] 4B fp8 (flux-2-klein-4b-fp8) + qwen_3_4b text encoder + flux2-vae~4 steps, CFG 1. Edit mode takes reference images (model sheets) for on-model characters. Apache-2.0.
Higher-quality single panels, prop textZ-Image-Turbo int8 (z_image_turbo_int8_convrot) + qwen_3_4b_fp8_mixed + ae.safetensorsTemplate image_z_image_turbo_int8; ~8 steps. Better text and instruction following; no reference-image editing. Pose/depth control via the Z-Image-Turbo Fun Union ControlNet template. Apache-2.0.
Staging controlSDXL + OpenPose ControlNet + IP-adapterMost mature pose and layout control at 8 GB; refine the result with Klein.
Character cut-outscomfyui-rmbg with BiRefNet toonout (made for cartoons and illustration) or RMBG-2.0For the layered workflow below.
Upscaling4x-UltraSharp, tiledRender ~1 MP, then upscale to print size.

At 8 GB: use fp8/int8/GGUF weights; move the text encoder to CPU or a second GPU when tight; tiled VAE decode for large images; one model loaded at a time; keep any local LLM on a different GPU.

Layered characters: generate each character on a flat plain background, cut it out (BiRefNet toonout), and composite over one shared background per scene. This fixes staging, scale and who-is-in-the-room problems that prompting alone won't, and lets props stay the same size across panels.

With more VRAM: FLUX.2 [klein] 9B (~20 GB; non-commercial), Qwen-Image-2.1 (~24 GB; 10 reference images, transparent RGBA output, masked edits; research license), FLUX.2 [dev] (24 GB+ in fp8; top quality and multi-reference; non-commercial). Check each model card's license before commercial use; the 8 GB stack above is all Apache-2.0.

2. Lettering engine: draw vectors, not pixels

2.0 Use the letterer tool (default)

Don't write lettering code. Use scripts/letterer.py, which ships inside this skill's folder (next to this SKILL.md), together with scripts/README.md, scripts/styles.json and the approved fonts in scripts/fonts/. Resolve the path relative to this SKILL.md, wherever the repo was cloned; never copy the script into a project. It already follows every rule in this section and runs the QA checks in §5 itself. Requirements: Python 3.9+ with Pillow and numpy (pip install -r scripts/requirements.txt); recommended mediapipe, which turns on the automatic face check (balloons must stay off faces) and "tail_to": "auto".

Workflow:

  1. python scripts/letterer.py grid --image panel_or_page.png --out grid.png and look at the overlay. Read the panel rectangles, each speaker's head box and mouth, and the open areas. Then choose each balloon's position and tail aim point by the placement rules in comic-master comic-lettering.md §12.2 and the step-by-step procedure in §12.7: balloon in open space close to the head, tail aimed at the mouth but ending outside the head. All coordinates are relative: 0.0–1.0 from the top-left.
  2. Write a page spec (JSON) with the items in reading order:
{
  "image": "strip.png", "out": "strip_lettered.png",
  "panels": [[0.0125,0.03,0.329,0.97], [0.342,0.03,0.658,0.97], [0.671,0.03,0.988,0.97]],
  "avoid": "faces_mask.png",
  "items": [
    {"style": "declaration", "text": "The city calls. I answer.", "zone": [0.03,0.06,0.31,0.24]},
    {"style": "speech", "text": "Did anyone else|hear that noise?", "at": [0.46,0.30], "tail_to": [0.52,0.52]},
    {"style": "sfx-micro", "text": "bzzt bzzt", "at": [0.39,0.62]},
    {"style": "sfx", "text": "KA-CHUNK", "at": [0.80,0.88], "size": 2.4, "rotate": -8}
  ]
}
  1. python scripts/letterer.py page spec.json. Exit code 0 means every QA check passed; 1 means it rendered but QA failed, so read the printed failures, fix the spec (move the balloon closer to the speaker, enlarge the zone, cut words, re-wrap with |) and run it again; 2 means an error (unknown style, missing font, bad spec).
  2. Look at the PNG at full size and as a thumbnail. Keep the SVG (editable) and the _qa.json (measured numbers) with the page.

Item fields: style; text (| forces a line break, otherwise it auto-wraps into a diamond; _word_ underlines for emphasis); at [x,y] center or zone [x0,y0,x1,y1] to fit inside; tail_to [x,y] aim point: not the mouth itself but a point in open space just outside the head, on the line from the balloon toward the mouth, about 1 ch off the face (the tool stops the tip a little short of it, so the tail aims at the speaker without touching them); omit it with "no_tail": true. Don't use "auto": it returns the lips themselves; optional panel index, size multiplier, rotate (degrees, clockwise), fill (background), ink (outline), text_color, font, tail_bend, link (index of an earlier balloon by the same speaker: joins the two), bleed (true to break the panel border on purpose), seed.

Page fields beyond the basics: defaults sets colors and font for every item ({"fill": "#FDF6E3", "ink": "#2B2B2B", "text_color": "#1F3A7A"}); styles overrides one style for this page ({"speech": {"fill": "#FFF7D6"}}); avoid defaults to "auto" (detected faces are protected), or a mask image, or false.

Letter the assembled page or strip in one page run, never panel by panel. One run keeps the lettering size identical across panels and lets QA check reading order and overlaps across the whole page.

Page fields: image, out/svg/qa paths, panels (strongly recommended: used for edge gaps, reading order and lettering size), ch (cap height in px; default is the median panel's short side ÷ 30, the same everywhere), avoid (white = faces, hands or key action that must stay clear; build it from a segmentation pass), direction (ltr, or rtl for manga).

Styles (run python scripts/letterer.py styles for the live list with one-line uses):

  • Dialogue: speech, speech-hand (hand-inked, italic, curvy tail), emphasis (the big line; underline with _word_), whisper (dashed), strain (trembling outline, pale yellow: words through clenched teeth), electronic (zigzag tail).
  • Thoughts: thought-1 (= thought, puffy cloud), thought-2 (fine scallops), thought-3 (smooth oval with bubbles). When in doubt, use thought-1: it's the default whenever a thought balloon is asked for without more detail. A thought trail needs at least 2.5 ch of open space between the balloon and its aim point, or QA fails it. See comic-master comic-lettering.md §12.8.
  • Loud: shout, shout-2 (hand-drawn burst), burst (no tail).
  • Boxes: caption, caption-hand, declaration and declaration-hand (quoted voice-over; stack several down a page for a monologue), locator, narrator.
  • SFX: sfx (at the source, with a thin white outer outline), sfx-micro (small sounds), sfx-stack (a repeating sound stacked beside its source: "wub|wub|wub").

Keep one dialogue look per book: either the plain styles or the -hand ones, not a mix within a scene. See examples/styles/sheet_lettered.png at the repo root for every style side by side. Add a style by adding an entry to styles.json, never by writing new drawing code.

Quick single item: python scripts/letterer.py bubble --image in.png --out out.png --text "GET DOWN!" --style shout --at 0.17,0.25 --tail-to 0.155,0.47 --panel 0.0125,0.03,0.329,0.97

If the tool is missing, follow the rules below to build the equivalent, and still produce the same QA numbers.

  • Build lettering as SVG and render it with resvg, cairosvg or headless Chromium (Playwright). Vectors give smooth curves, real kerning, clean strokes and an editable layer. Don't draw balloons with raster ellipse calls.
  • Use a real comic font.
    • Dialogue: Comic Neue, Patrick Hand, Anime Ace or another hand-lettered face, all caps, one font for the whole work.
    • SFX and titles: a heavy display face such as Bangers.
    • Never a system sans (Arial, Helvetica, DejaVu). Fail loudly if the font file is missing instead of falling back silently.
    • Dialogue and captions use a plain, upright, hand-lettered face only. No display, techno, futuristic, stencil, horror or novelty fonts for words people must read: letters with missing crossbars or stylized E/A/M forms slow reading and change the tone. Decorative faces are for SFX, titles and logos only.
    • Keep an approved list in the project bible (e.g. dialogue: Comic Neue Bold or Anime Ace; SFX: Bangers) and refuse any font not on it.
  • Balloons are fitted to the text:
    1. Wrap the text into a diamond: short top line, widest middle, short bottom, no one-word last line.
    2. Measure the text block and draw a rounded oval or superellipse around it.
    3. Grow the wall until every corner of the text clears it by at least one cap height.
    • Never squeeze text into a fixed ellipse.
  • Tails are curved, tapered paths, not triangles:
    • Base about ⅛ of the balloon width (never under ~0.8 cap height), on the side nearest the speaker.
    • Length up to about half the balloon height (or 2.5 ch for small balloons), curving toward the mouth and ending in open space outside the head, 1–2 ch short of the face. Never touching the lips or lying across the face. If the speaker is farther away, move the balloon closer rather than stretching the tail.
    • Never a needle: a hairline spike running across the panel reads as a scratch, not a pointer.
    • Draw balloon and tail as one outline so they join smoothly.
  • Balloon size follows the text. Set the body lettering at the project size (see specs), then fit the balloon with 1–1.5 cap heights of padding. Don't shrink the text to fill a big balloon or inflate the balloon around a few small words.
  • Bursts: star polygons with jittered point radii, with the text fitted to the inner valleys. A burst needs no tail.
  • Captions: rectangles with even padding (about half a cap height at the sides), in the same font family as the dialogue and readable at print size. Locator captions take no quotation marks.
  • SFX are drawn objects:
    • display font and a fill color chosen for contrast with that panel
    • a heavy outline, about ¼ of the letter height
    • rotation or a slight warp
    • sized to the event and placed at its source
    • in front of the art, unless a figure mask deliberately tucks part of the word behind something
    • no sticker, box or white backing behind the word; the heavy outline does the separating
  • Keep one reusable module with balloon, tail, burst, caption, sfx and check_layout, instead of writing new drawing code for every page.

Default specs (cap height = ch)

ElementDefault
Cap height≈ 1/30 of the panel's short side
Line spacing≈ 1.15× font size
Balloon padding1–1.5 ch to the curved wall (not more)
Balloon wall≈ 1/8 ch
Tail length≤ ½ of balloon height (or 2.5 ch); aims at the mouth, ends 1–2 ch outside the head
Tail base≈ ⅛ of balloon width, ≥ 0.8 ch
Gap to panel border≥ 1 ch
SFX height / outline2–5× body / ≈ ¼ of SFX letter height

3. Detection on your own art

These detectors run on panels you generated, to place lettering. They are not for reading published comics; study those by eye.

  • Mouths: run a face-landmark model (e.g. MediaPipe Face Mesh) to find each speaker's mouth, which tells you where tails should aim. Never use the mouth as the tail's end: set the tail's end point in open space just outside the head on the line toward the mouth. For masked, stylized or turned-away faces, mark the point by hand on a coordinate-grid overlay.
  • Figures and faces: get masks with background removal or segmentation (rembg, SAM). Use them to keep balloons off faces, hands and key action, and to layer SFX behind or in front of figures on purpose.
  • Free space: combine the masks with the panel's planned text zone to find the emptiest area for each balloon. Then confirm reading order: the first speaker's balloon is highest and leftmost (mirrored for manga).

4. Text that lives in the art (badges, signs, screens, labels)

Never paste flat text over an object in the scene. It ignores the object's angle, curve and lighting and reads as fake at once. Use one of these methods:

  1. Edit-model pass (§1.4). Ask the image model's edit mode to write a short word on the object ("the round name badge reads MORVAX in black marker"), keeping everything else unchanged. Check the spelling at 1:1 and redo it if wrong. Short words work; long phrases fail.

  2. Warp and blend. Render the text flat, then warp it to the object:

    • a perspective transform for flat signs
    • an arc or mesh warp for curved badges

    Multiply it into the object's shading, then add slight blur and grain to match the render.

  3. Insert panel. Stage a close-up of the object facing the camera, where flat text is correct, and make it a planned panel in the layout. Never use a box stuck in a corner.

  • Keep prop text identical across panels: same words, size and position on the object. Log it in the continuity tracker.
  • Never enlarge a prop to make its text readable. If the reader needs to read it, change the shot (closer framing, an insert panel) so the prop appears at its true size.
  • If a joke depends on a prop's text, the text must be legible at the moment of the reveal and not before it.

5. Automated QA before a human looks

Check in code and fix every failure:

  • Text-to-wall clearance ≥ 1 ch in every balloon and caption
  • Every balloon ≥ 1 ch from panel borders and page edges; nothing clipped
  • No balloon or SFX overlapping a face or hand mask
  • No balloon on the eyeline between two speakers
  • Each tail aims at its speaker's mouth, ends in open space outside the head (no tip on lips or face), and crosses no other balloon or tail
  • Balloon reading order matches script order
  • Only project fonts used; no fallback font; dialogue font is on the approved plain list
  • Every tail base ≥ 0.8 ch and about ⅛ of balloon width; tail length ≤ ½ of balloon height (or 2.5 ch) and it reaches its aim point outside the head
  • Balloon padding between 1 and 1.5 ch (not cramped, not ballooned around tiny text)
  • No SFX has a backing shape
  • Props appear at the same size and position on the character in every panel

Then look at the page yourself:

  • at 1:1 crops, where tangents and cramped text show
  • at full page
  • as a thumbnail

Check the art for continuity slips, such as extra people appearing between panels or a prop changing. Fix art slips with an edit or inpainting pass (§1.4), not a full re-roll.

6. Assembly and delivery

  • Compositing order: art → in-world text fixes → SFX → balloons and captions → panel borders.
  • Borders by weight: page edge > panel border > figure contour > interior line > balloon wall.
  • Deliver PNG pages, plus a PDF for multi-page work. Keep the text-free art, the vector lettering file and the final render as separate files.

7. Failure gallery (what the tools must prevent)

  • Plain ellipse balloons with text squeezed against the wall.
  • Stubby triangle tails aimed at an ear.
  • System fonts instead of comic lettering; captions in a different, tiny font.
  • Flat gray SFX parked far from the sound's source.
  • Text pasted flat onto a badge or sign; prop text that changes between panels.
  • An inset box in a corner explaining a prop instead of a planned insert panel.
  • Stray extra characters appearing between panels.
  • Techno or novelty display fonts used for dialogue and captions.
  • Needle tails: long hairline spikes instead of short tapered wedges.
  • Huge balloons around three or four small words.
  • SFX sitting on a white sticker.
  • A prop that grows between panels so its text can be read.

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

Related Skills