icon-critique
Judge icons by their renders, never their source code. An SVG that looks right as markup routinely dies at 16 px — thin strokes vanish, closure gaps stop closing, counters fill in. This skill runs the render → critique → targeted-fix loop that every credible icon pipeline converged on, with a hard iteration cap.
When NOT to use
- Creating an icon from scratch →
icon-draw(aftericon-brief). - Producing favicon/asset files or plain SVG→PNG conversion →
icon-export. - UI icon-set consistency reviews, page/UX critiques, code review.
Workflow
Lint before rendering. Renderers are an attack/crash surface — run the safe-subset linter on every input first and refuse to render files that fail its security checks (external refs, DOCTYPE, scripts,
<image>):python3 "${CLAUDE_SKILL_DIR}/../icon-draw/scripts/check_svg.py" <file>.svg # or the skill's installed pathIf the linter isn't available, say the file is unvetted and get explicit user confirmation before rendering. House-geometry errors (off-palette, wrong rx) are critique findings, not render blockers — note them.
Render. For each candidate (a file argument, or every SVG in
icon-design/candidates/):python3 "${CLAUDE_SKILL_DIR}/scripts/render_icon.py" <file>.svg --sizes 512,64,32,16 --htmlThe script autodetects a renderer (rsvg-convert → resvg → cairosvg → inkscape → ImageMagick → macOS qlmanage) and exits non-zero with install hints if none exists — in that case relay the hints and stop; never critique unrendered markup.
Read the renders (the PNG files, with the Read tool) — 512 px for craft, the 64/32/16 strip for survival (
preview.htmlshows 16 px both native and pixel-doubled). Score each candidate against the rubric inreferences/critique-rubric.md: reads as its subject (can a stranger name the thing?), mass (theink=figure the renderer prints — under ~16% at 64 px is thin, over ~21% is safe), 16 px silhouette, one dominant Gestalt device, stroke consistency, optical centering, contrast on dark, plus a distinctiveness note. Score 1–5 per axis with a one-line reason grounded in what you actually see ("the gap between the arcs closes up at 32 px"). Distinctiveness — including collision with a universal UI glyph — is recorded and shown to the human, never used to drop a candidate: that call belongs to whoever owns the product.Fix with targeted edits — only when asked. Pure review requests ("rate", "critique", "compare") end at the verdict; edit only when the user asked to fix/improve or approves your proposed fixes. Edits are non-destructive: write revisions as
<n>-<slug>-r1.svg,-r2.svg… next to the original, patching the specific failing element — thicken a stroke, widen a counter, drop the detail that dies smallest — never regenerate wholesale. Stay insideicon-draw's constraints (itscheck_svg.pymust pass on every revision). Typical fixes ranked in the rubric reference.Re-render and re-score each revision. Hard cap: 3 fix iterations per candidate. If it still fails an axis at the cap, report the residual honestly — do not loop, do not lower the bar.
Verdict + human gate. Present every candidate — including the ones you scored badly — in a ranked table (candidate, axis scores, one-line verdicts), point at
icon-design/renders/*/preview.html, and ask the human to pick. Say plainly that the ranking is advisory. On approval, copy the winner toicon-design/icon.svg— the handofficon-exportexpects — but never replace an existingicon-design/icon.svgwithout explicit confirmation. Never auto-promote, headless included: report the scores, name the top scorer, and stop without writingicon-design/icon.svg. A run with no human in it produces a recommendation, not an approval.
Output spec
icon-design/renders/<candidate>/— PNGs at 512/64/32/16 +preview.html.- A scored comparison table + recommendation with per-axis reasons.
- On approval: the winner at
icon-design/icon.svg, passingcheck_svg.py, plus its final render set.
Gotchas
- Self-review bias is real: you are grading your own drawing. Ground every score in a visible pixel fact, not the intention behind the code. When another reviewer is available (subagent, second model, or the human), prefer it for the final pass.
- This rubric is a failure detector, not a ranker. In this repo's own bake-off it agreed with the human on every bottom-ranked mark and disagreed on two of three winners — the candidate it declared unrecoverable was the human's first pick. Trust it when it says something is broken; do not trust it to tell you which working mark is best, and never let it be the thing that removes an option from the table.
- Automated taste doesn't exist: VLM judgment of operational qualities (legibility, contrast, balance) is workable; open-ended "is it beautiful" is not — leave taste to the human, and say so when asked to "make it prettier".
- Distinctiveness needs comparators: name the 2-3 category-cliché marks (from the brief) and check the silhouette against them; "clean" is not "distinct".
- qlmanage (macOS fallback) antialiases slightly differently than librsvg — fine for review; recommend installing librsvg/resvg before pixel-exact work.
- A fix that passes 16 px but breaks the Gestalt device at 512 px is a regression — always re-read the whole ladder after an edit.