Illo
SkillDev toolsCreates original editorial illustrations where a recurring mascot character performs the idea — one caught scene by default, a hand-built explainer diagram (labeled stages, a fan-out, timeline, loop, or stack) when the structure itself is the point, or a transparent character cutout (pose-only compositing asset, no scene or text) — in one of seventeen bundled looks (sixteen print, plus a photoreal toy-brick set). Also handles "surprise me" / "random" (optionally scoped to a focus or character): rolls provenance, builds three saying candidates, picks via interactive choice or auto-pick-best (`--autopick`), and renders one image. Triggers only when the skill is directly invoked or "illo" is requested; never on generic illustrate / draw / make-an-image requests.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Illo skill
What this skill tells your AI
The instructions your AI receives, as published by tmchow/illo-skill in skills/illo/SKILL.md and read by ahel’s review.
Make original, distinctive editorial illustrations for written content. One
image explains one idea: a key judgment, a flow, a before/after, a trap, a
loop. A recurring mascot is the one performing the idea in every scene —
the subject, never decoration. When one idea advances through stages, it can
be a mini-comic: 2–4 panels inside a single image. And when the idea is
itself a traceable structure — a pipeline, labeled stages, a fan-out, a
timeline, a loop — it can be an explainer: the same mascot and look
drawing the structure as a hand-built sketch-diagram with arrows and
callouts (references/composition.md, "Two registers" and "Pick the
diagram type"; editorial scene is always the default). A named pipeline
or recipe is labeled stages inside that register — named phases in
order, one connected system, pack-solved for this body, never a new look.
Or a character cutout: the mascot alone on a transparent PNG for downstream overlay
— pose and contact continuity only, no idea, no text, no environment
(references/cutout.md).
This is a configurable house style, not a generic image generator. The
methodology is the constant; the character pack and palette are the
parameters — and a character pack carries its style with it: one look
per pack, chosen from the bundled look library (riso — grainy halftone,
ink-layer offset, paper grain, one bold softly-rounded outline — plus
blueprint, woodcut, pixel, clay, manila, chalk, phosphor, enamel,
gouache, felt, diorama, sketchbook, bricks, fizz, bloom, and snes) or a custom style file. The default mascot is
Blot, a deadpan ink-drop in riso. Palettes come
from presets, the user's own palette file, or one derived color. Whatever the
parameters, it is intentionally not a photo — with one deliberate exception, the
bricks look, a toy-brick photography style — not a logo, not a corporate
infographic, not a formal boxes-and-diamonds flowchart look, not a UI
mockup. Asking for a flowchart still means labeled stages in the pack's
look — the formality ban is a look constraint, not a refusal of the word.
Use cases — route the request
| The user wants | The path |
|---|---|
| Illustrate an article / post / newsletter / URL | Steps 0–7: route the source first (thesis → coverage: hero / hero+set / set / mini-comic — references/composition.md, "Source routing"), then shot list (hero row + anchors), one image per anchor, interleave by placement. |
| One image for a single concept | Step 1 concept branch (up to ~3 quick questions if the idea is thin), then a single image. |
| Surprise / random — "surprise me", "random", "surprise me with art quote using bray", "surprise me --autopick" | Read references/surprise.md in full: Step 0 first, then character + provenance (ignore defaultCharacter; * quote forces a cited quote; else ~1/3 roll), build three safe candidates, interactive picker or auto-pick-best (--autopick preferred for schedulers), then register from the locked saying, then Steps 3–7 as one image. Deliver saying + image. Poster titles default off; mini-comics still get per-panel labels. |
| A sequence — story beat, before→after, fail→fix | One mini-comic when the progression sits in one place (shape routing in references/composition.md — the idea picks the shape, the destination never does). A specified process diagram / flowchart / labeled workflow is labeled stages, not this row. |
| A traceable structure — "show the flow", "as labeled stages", "label the steps", "walk the stages", "diagram the pipeline", "like that factory diagram", "map the steps", "as an explainer", or specified flowchart / labeled-workflow / process-diagram intention | The explainer register (references/composition.md, "Pick the diagram type" and "The explainer register"): a hand-built labeled-stages / flow / fan-out / timeline / loop / stack / system slice in the active look, the mascot a working part of it. Specified flowchart / labeled-workflow / process-diagram intention locks labeled stages in the pack's look — the formal-flowchart ban is a look constraint (no Visio, no title/legend/grid), not a refusal of the word. Labeled stages is a structure type inside explainer, not a new register or look — pack-solve it for the active character before the prompt. BEST when a unit's thesis IS a named pipeline, recipe, or staged process; never the automatic choice for every explainer. |
| Social-ready art for X posts / article body images | 16:9 (or 1:1 when square is explicitly useful), bold ink-punch, watermark with the x handle if configured or asked. |
| X Article banner / hero image | Use the unique banner format: 1536 × 640 px when the user asks for an X Article hero/banner. Prompt and render through the normal illo.py generate image pipeline, with normal, undistorted character/object proportions and crop-safe breathing room. Do not satisfy this by manually compositing or rebuilding crops from another image unless the user explicitly asks for post-processing. |
| Blog / brand / site-matched art | A named or custom palette, or derive the palette from one dominant color (references/palettes.md). |
| Their own mascot — "make me a character", "use our mascot", "replace Blot" | The character builder: read references/character-builder.md in full and follow it end to end. |
| Community characters — "what characters are available", "install blip", "install all characters", "update mole", "publish my character" | references/pack-sharing.md — engine packs list/show/install/update, including packs install --all; publish via a GitHub PR. |
| A different look — "in blueprint", "woodcut style", "pixel version of blip" | Styles travel with character packs: build a style variant pack via references/character-builder.md, "Style variants". |
| Options to pick from, or "which model is best" | Step 5b: --count variations or a model loop → gallery with a recommendation. |
| Fix an existing image (stray title, recolor, mascot too decorative) | Edit prompts in references/prompt-recipe.md, passing the image back as --ref. |
| Character cutout / transparent PNG / overlay sticker — "just the mascot", "no background", "paste on something else" | The cutout register (references/cutout.md): read in full, prompt from references/prompt-recipe.md "Cutout variant", generate with --cutout and --aspect 1:1. OpenRouter cutouts default to GPT Image 2 (not Grok). Not for explaining an idea — reroute to editorial if the ask needs a scene. |
| Animated idle / bot avatar / looping GIF of the mascot | The cutout register plus references/cutout.md, "Idle loop / bot avatar": one transparent 1:1 cutout with --cutout and the character sheet as --ref, then programmatic motion on that PNG. |
Prerequisites
The engine (scripts/illo.py, stdlib Python, no installs) renders through one
of three engine backends; python3 and network access are the only hard
requirements. Grok Bot (Cursor's Grok Bot / the Grok desktop assistant) is
a fourth, agent-side transport: use its built-in Grok image tool directly, not
illo.py generate, when no user config explicitly selects an engine backend.
Running the engine — set $SKILL_DIR inline in each block. Every engine
command below is python3 "$SKILL_DIR/scripts/illo.py" …. Set SKILL_DIR to the
absolute path of the directory this SKILL.md was loaded from (it contains
scripts/illo.py and assets/) in the same command block that uses it — shell
state does not persist between separate command runs, so a value set in an earlier
block is gone by the next. If the harness does not expose that path, find the
installed scripts/illo.py and use its parent; if neither resolves, stop rather
than guessing the working directory. The engine self-locates its own bundled
assets, so $SKILL_DIR only has to be right enough to launch illo.py and to
point --ref at the bundled character sheet.
Write the block flatten-safe — some hosts (Codex observed) collapse a fenced
block to one line, turning a newline into a space. Terminate the assignment with
; (SKILL_DIR="…"; — without it, a flattened SKILL_DIR="…" python3 "$SKILL_DIR/…"
becomes an env-prefix whose $SKILL_DIR expands to empty before the assignment
applies, so the path collapses to /scripts/illo.py). Put no comment on an
assignment or command line (a flattened # comments out the rest of the line and
the command silently vanishes), and keep each invocation on one line (a
flattened \ continuation injects stray arguments). A wrong or unset value makes
doctor (Workflow step 0) fail loudly (can't open file …/scripts/illo.py) — the
signal to fix the path, not a skill fault.
- Codex backend (free for Codex subscribers). When the host has a usable
Codex CLI — installed,
codex login-ed, with theimage_generationfeature — illo can generate through the user's Codex subscription at no per-image charge (it draws on their Codex quota). No API key, no token: illo only shells out to the user's own CLI. Detected, not assumed; gpt-image-2 is automatic; unsupported on Windows/WSL. - Grok CLI backend (free for Grok/xAI subscribers). When the host has a usable
Grok CLI — installed and
grok login-ed — illo can generate through the user's Grok subscription viagrok -p(headless), drawing on their Grok quota. Same env-free, token-free subprocess design as Codex. Grok returns JPEG with no alpha, so it cannot make transparent cutouts — those auto-fall back to a cutout-capable backend. The image tool exposes no model selector. - Grok Bot native transport (agent-side, free for Grok Bot users). When
you are Grok Bot — specifically Cursor's Grok Bot / the Grok desktop
assistant with the built-in Grok image tool — build the illo prompt and call
that tool with the active character's model sheet as a reference image. Do
not require the Grok CLI, Codex CLI, or an OpenRouter key; do not treat a
missing engine backend as a reason to run
init. This is not a generic "host image API" rule and not anillo.py --backendvalue. - OpenRouter backend (paid, direct or explicit fallback). Needs an
OpenRouter API key in the user's config file — the single credential
channel — written once by the user-run
init(mode 600). The engine never reads secrets from the environment and never accepts them as command-line arguments. A host without a subscription CLI can select this engine path directly. A failed Codex/Grok CLI render does not spend money automatically: paid fallback requires--allow-paid-fallback. It is model-selectable (--model).
Capsule of the backend/transport model (resolution and precedence, the CLI
requirements, the Grok Bot native path, the built-in image tool being
automatic, quota vs. charge, cutout limits, Windows/WSL, fallback): read
references/backends.md in full before choosing or explaining a backend —
the mechanics live there, once.
Setup is the user's job (never enter the key yourself)
Entering an API key is something the user does. Do not type, paste, print, or store the user's key — direct them to bootstrap it:
- Bootstrap (user runs it):
python3 "$SKILL_DIR/scripts/illo.py" init— prompts for the key at a hidden prompt (never echoed) and writes the YAML config${XDG_CONFIG_HOME:-~/.config}/illo/config.yaml(mode 600). It can also store non-secret defaults:--model,--palette,--aspect,--character,--watermark. Use--no-keyto update preferences without touching the stored key. (The config is read via PyYAML when installed; without it a minimal built-in parser still reads the flat keys —apiKey,model, … — so generation needs no installs. Only nested settings likewatermarkneed PyYAML:python -m pip install 'PyYAML==6.0.2'.) - Non-secret prefs may be seeded for the user with the same command and
--no-key, but the key itself is theirs to enter.
Hermes Agent only: binary asset repair preflight
Some Hermes versions corrupt binary files (the bundled character sheets) when
installing multi-file skills from GitHub — text files survive, binaries don't,
and a corrupted sheet silently breaks the character lock. Under Hermes
Agent, run this once before first use (and whenever doctor reports
assets: CORRUPTED):
bash ${HERMES_SKILL_DIR}/scripts/repair-hermes-assets.sh
It verifies every bundled binary against known-good SHA256 hashes
(assets/checksums.txt) and re-downloads only mismatched files from pinned,
immutable URLs — a no-op when everything checks out. Under Claude Code,
Codex, OpenClaw, or any runtime that installs faithfully: skip this; doctor
checks asset integrity everywhere and will say if repair is ever needed.
Read these references as needed
Do not load everything at once. Pull the file that matches the step:
references/visual-style.md— riso, the house default look: the risograph technique, line language, paper/ink, hard do/don'ts.references/styles/<name>.md— the rest of the look library (blueprint,woodcut,pixel,clay,manila,chalk,phosphor,enamel,gouache,felt,diorama,sketchbook,bricks,fizz,bloom,snes), consumed by character packs. Read the active character's style file in full before generating.references/character.md— the character rules (the load-bearing test, anti-complexity guardrails, value-follows-palette, the interaction model — declared per pack or derived conservatively from the locked design and reference sheet), the default character Blot, and the custom-pack format. Read before any character work.references/character-builder.md— the guided flow for designing and installing a user's own mascot. Read in full before building or replacing a character.references/pack-sharing.md— installing characters from the community repo and publishing a pack via PR. Read before any install/publish request.references/palettes.md— named presets, default resolution, custom palettes, and the derive-a-palette-from-one-color algorithm. Read in full before choosing or deriving any palette.references/composition.md— the two registers (editorial scene / explainer diagram), the diagram-type picker, the explainer's structure types and budget (including labeled stages, arrow notes, and its pack-solve), stagings, turning an idea into a move, the anatomy-action feasibility gate (validate the contact map against the character's interaction model before rendering), the no-recycled-composition rule, and the shot-list format.references/cutout.md— the cutout register: transparent compositing assets, contact continuity, pose vocabulary, and generate flags. Read in full before any cutout request.references/surprise.md— surprise / random mode: preflight-first, scope parse, random character, provenance variety + three saying candidates (optional parallel verify for sourced modes), interactive picker or--autopick/ auto-pick-best, full re-roll on refresh, register after the locked saying, saying bar + sense bar, multi-source quote verification, safety-before-offer, headless contract. Read in full before any surprise/random request.references/backends.md— the three-backend image engine plus the Grok Bot native transport: how the engine backend resolves (precedence Codex > Grok > OpenRouter, and the self-identify rule), when Grok Bot bypassesillo.py generate, the Codex/Grok CLI requirements, artifact-first success, the built-in image tool being automatic (no model selection), quota-vs-charge, Grok's no-cutout limit, Windows/WSL, and opt-in paid fallback. Read before choosing or explaining a backend.references/models.md— the model lineup (OpenRouter backend only): friendly-name → OpenRouter id map, traits, aspect caveats, 404/fallback handling. Read before passing any--model.references/prompt-recipe.md— the generation prompt template and the edit/recolor prompts.references/quality-bar.md— the post-generation checklist and iteration rules. Read before delivering.
assets/character-reference.webp is the default character's canonical model
sheet — the consistency anchor (used by the engine, below); a custom pack
brings its own. Style-calibration examples are not bundled — each style
file links its own by URL (fetch when needed): study line density, negative
space, and accent restraint. Never copy their compositions — invent a
fresh metaphor for the current piece.
Workflow
0. Preflight
Before generating, confirm the engine is ready:
SKILL_DIR="<path to this skill>";
python3 "$SKILL_DIR/scripts/illo.py" doctor
Run the illo.py call standalone — never chained with && — so the displayed exit code is
the readiness signal itself (0 = ready): a chained neighbor's failure paints
a healthy check as an error.
It reports python, the config path, the resolved model/palette defaults,
whether a custom character pack or custom palettes file exists,
Codex/Grok CLI detection and the resolved backend/transport, and whether an
OpenRouter key is found (without revealing it); exit 0 = the resolved backend
is ready. An OpenRouter-only install (no subscription CLI) stays exit 0 —
readiness follows the resolved backend, not a hardwired key check
(references/backends.md).
Grok Bot native path (agent-side). If you are Grok Bot (Cursor's Grok
Bot / the Grok desktop assistant with the built-in Grok image tool) and the
user has not explicitly chosen backend: openrouter, backend: codex, or
backend: grok, initialize the agent-side transport before relying on
doctor:
SKILL_DIR="<path to this skill>";
python3 "$SKILL_DIR/scripts/illo.py" init --backend grok-bot --no-key
Then run doctor normally: exit 0 is meaningful readiness for this path.
Missing Codex CLI, Grok CLI, or OpenRouter key are not failures when
backend: grok-bot; corrupted assets, unreadable custom packs, malformed
palettes, or the wrong SKILL_DIR still fail and must be fixed before
rendering. Generate in Step 5 by calling Grok Bot's built-in Grok image tool
with the active model sheet reference. This route is only for Grok Bot's own
Grok image tool; other agents with unrelated image tools must use the engine
backends below.
Short path for Grok Bot: run init --backend grok-bot --no-key once when
backend is unset/auto, run doctor for assets/config/packs, use packs
commands normally (including packs install --all after install so community
characters are local), read the same references, build the same prompt, then
call Grok Bot's built-in Grok image tool with the active character reference.
Skip illo.py init for OpenRouter unless the user explicitly wants OpenRouter
or another engine backend default, and skip illo.py generate unless the user
explicitly selected an engine backend.
After the first successful Grok Bot install and bulk character install, ask
once whether the user wants periodic checks for skill updates (npx skills update) and character updates (packs update). Default is off: if they
say no, do not answer, or the host has no recurring-job mechanism, set up
nothing. Only create a recurring check/reminder on an explicit yes, and never
silently update — surface the proposed skill/character update and get consent
before applying it.
Config migration — surface the backend choice interactively. When you are
going to use illo.py generate, if doctor reports backend: NEEDS CHOICE
(or generate hard-stops saying the config "is out of date"), this user's
config predates the backend choice — they have an older install and have never
been offered a subscription CLI. Do not pick for them silently. Surface an
interactive choice using the platform's
blocking-question capability (AskUserQuestion in Claude Code, the equivalent
elsewhere; where the host has none — e.g. a plain chat session — ask the same one
choice as a concise message and wait for the reply, never picking silently):
"illo now has image backends/transports — which would you like?" with four
options — Codex (free, your Codex subscription), Grok CLI (free, your
Grok subscription; no transparent cutouts), Grok Bot (agent-side native
tool; use only when you are Grok Bot), and OpenRouter (pick the model: Grok
Imagine, Nano Banana, GPT Image, and others). Persist the answer without
touching any existing key:
python3 "$SKILL_DIR/scripts/illo.py" init --backend <codex|grok|grok-bot|openrouter> --no-key,
then continue. A brand-new install (no config at all) is ordinary onboarding,
not this migration — it does not fire.
Prefer your own CLI when you are a subscription-CLI agent. The engine's
auto-default reads host capability (Codex > Grok > OpenRouter; it can't
tell which agent invoked it) — but you know which agent you are. So when you
are a subscription-CLI agent and your own CLI is usable on this host, add your
own backend flag to generate for non-cutout renders: the Grok CLI agent
adds --backend grok, the Codex agent adds --backend codex. This keeps
"in Grok CLI, generate with Grok" true even on a host that also has Codex, with
no runtime-sniffing in the engine. Cutouts ignore this (Grok can't make them —
they auto-fall back). A user's config backend: overrides everything.
Resolution and precedence mechanics: references/backends.md.
For Grok Bot, the equivalent self-identify rule happens before generate:
when backend is unset/auto, persist backend: grok-bot with
init --backend grok-bot --no-key and use the native Grok image tool path
above. If the user explicitly configured or requested an engine backend, honor
that choice instead of silently switching to Grok Bot native.
Shortened here. Read the whole file on GitHub.
Signals
- GitHub stars
- 374
- Forks
- 17
- Last commit
- Aug 2026
ahel review
K1binfo
installs-packagesK6low
bundled executables the agent is told to runK1binfo
installs-packages (in scripts/illo.py)K1binfo
installs-packages (in README.md)
Automated review, not a security audit. Ruleset v1+k2.
Advanced
- Catalog kind
- skill
- Gateway key
illo- Source
- github.com/tmchow/illo-skill