Help us improve
Share bugs, ideas, or general feedback.
From claude-code-config
Generates pixel art sprites, animations, sprite sheets, and converts images to pixel art using 30+ palettes, dithering algorithms, and automated quality scoring for retro/indie game art.
npx claudepluginhub anastasiyaw/claude-code-configHow this skill is triggered — by the user, by Claude, or both
Slash command
/claude-code-config:pixel-art-studioThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Programmatic pixel art creation with palette discipline, dithering, animation, and automated quality control. Designed for **production-quality output**, not "look-pixelated filter on a photo."
elements/catalog.htmlelements/elements.jsexamples/bounce-tag.gifexamples/bouncing-dot-sheet.pngexamples/bouncing-dot.apngexamples/bouncing-dot.gifexamples/bouncing-dot.jsonexamples/endesga-32-preview.pngexamples/fantasy-covers/index.htmlexamples/fantasy-covers/scenarios.mdexamples/heart-bayer4-db16.pngexamples/heart-preprocessed-16x16.pngexamples/heart-test.jsonexamples/heart-test.pngexamples/heavenly-hues-preview.pngexamples/library-demo/index.htmlexamples/tier2-detail-demo/index.htmlexamples/twilight-covers/index-v2-static.htmlexamples/twilight-covers/index-v2.htmlexamples/twilight-covers/index.htmlRefines pixel art sprites using dithering, palette optimization, shading, antialiasing, and color theory with Aseprite tools for professional results.
Generates pixel-art sprites, tiles, icons, and portraits at fixed resolutions (16×16 to 128×128) with grid alignment, limited palette, and retro styling. Useful when building 2D games that need crisp pixel assets.
Generates true pixel art sprites, tilesets, and animations via the Retro Diffusion API. Useful for quick 2D game prototyping and replacing placeholder art with cohesive pixel art.
Share bugs, ideas, or general feedback.
Programmatic pixel art creation with palette discipline, dithering, animation, and automated quality control. Designed for production-quality output, not "look-pixelated filter on a photo."
| User says | What to do |
|---|---|
| "make a pixel art X" / "create a sprite" | Static sprite workflow |
| "animate this", "walk cycle", "idle animation" | Animation workflow |
| "convert this image to pixel art", "pixelate this" | Preprocessing workflow |
| "generate sprite sheet" | Sprite sheet workflow |
| "review this pixel art / score it" | Quality review workflow |
| "show palette options" / "use Endesga 64" | Palette browsing |
If user provides only a vague description ("a cat sprite"), pick the standard sprite workflow with 32×32 + Endesga 32 palette as the safe default, then offer to iterate.
pip install Pillow numpy
# Optional but recommended for advanced quality checks:
pip install scikit-image scipy
Pillow is mandatory; numpy is mandatory; the rest are optional (the scripts will degrade gracefully).
A 16×16 sprite with deliberate cluster choices reads better than a 64×64 with random pixel noise. Always start from the smallest grid that conveys the subject, expand only when needed for detail.
The four pillars of quality (encoded in scripts/quality_check.py):
When in doubt, run quality_check.py after generation and fix issues until score ≥ 80/100.
| Subject complexity | Canvas | Examples |
|---|---|---|
| Icon / glyph | 8×8 | heart, key, arrow, smiley |
| Simple sprite | 16×16 | NES character, item, tile |
| Standard sprite ⭐ | 32×32 | indie character, animal, prop |
| Detailed character | 48×48 - 64×64 | hi-bit hero, boss, building |
| Mobile RPG humanoid (CN/KR) | 48×72 | 8-direction walking character |
| Hero / portrait | 96×96 - 128×128 | promotional art, big boss |
When user is vague: 32×32.
Three modes:
scripts/palette.py --list to enumerate. Default for vague subjects: Endesga 32.references/02-palette-theory.mdCommon style → palette mapping:
| User intent | Palette |
|---|---|
| Generic, modern indie | endesga-32 or endesga-64 |
| 8-bit retro / Famicom feel | nes or pico-8 |
| Mono / GameBoy DMG | gameboy-dmg |
| Soft pastel / cute | sweetie-16 |
| Atmospheric / cinematic | apollo or slso8 |
| Industrial / cool | steam-lords |
| Chinese xianxia / palace | gugong-red-wall or qinghua |
| Korean traditional | obangsaek (5-color) |
| Dark fantasy (Stoneshard-style) | stoneshard-inspired |
Always think in this order, not free-form:
NEVER do pillow shading: dark border + light center regardless of light source. Auto-detected as anti-pattern in quality_check.py.
Use the Sparse Coordinate JSON format. Minimal example:
{
"width": 16,
"height": 16,
"background": "transparent",
"pixel_size": 16,
"palette_ref": "endesga-32",
"pixels": [
{"x": 7, "y": 4, "color": "#a8ca58"},
...
]
}
For animation, use the multi-frame extended schema (frames array — see Workflow 2).
python ${CLAUDE_PLUGIN_ROOT}/skills/creative/pixel-art-studio/scripts/render.py \
sprite.json -o sprite.png
python ${CLAUDE_PLUGIN_ROOT}/skills/creative/pixel-art-studio/scripts/quality_check.py sprite.png
Output is JSON. Score ≥ 80 = ship. Score 60-80 = fix issues listed. Score < 60 = redesign.
Read the PNG with the Read tool to show user. Offer fixes for any quality issues flagged.
Pick from this table — do NOT improvise frame counts.
| Animation | Min | Standard ⭐ | Premium | FPS |
|---|---|---|---|---|
| Idle (breathing) | 2 | 4 | 6-8 | 6 |
| Walk | 4 (Celeste) | 6 (Shovel Knight) | 8-12 | 8 |
| Run | 6 | 8 | 10 | 10 |
| Attack | 3 | 5 | 6-8 | 10-12 |
| Death | 4 | 6-8 | 10+ | 8-10 |
| Hit reaction | 1 | 2-3 | — | 10 |
Cultural variations:
Only 3 of 12 translate without modification:
For walk cycles: 4-frame minimum is [contact, recoil, passing, high-point] and back. Don't add frames just to "smooth" — add anticipation/follow-through instead.
For attacks: [anticipation (slow), strike (1 frame, fast), recovery (eases back)]. Slowing down anticipation + speeding up action ≫ adding frames.
For fast attacks/throws, insert 1-2 stretched intermediate frames (smear). Heavy in Skul, less in Sanabi. See references/04-animation.md.
{
"width": 32,
"height": 32,
"background": "transparent",
"palette_ref": "endesga-32",
"frames": [
{"id": 0, "duration_ms": 120, "pixels": [...]},
{"id": 1, "duration_ms": 120, "pixels": [...]},
{"id": 2, "duration_ms": 120, "pixels": [...]},
{"id": 3, "duration_ms": 120, "pixels": [...]}
],
"tags": [
{"name": "walk", "from": 0, "to": 3, "direction": "forward"}
]
}
direction ∈ forward | reverse | pingpong (Aseprite convention).
# Animated GIF
python scripts/animate.py walk.json --format gif -o walk.gif
# APNG (better, supports semi-transparency)
python scripts/animate.py walk.json --format apng -o walk.apng
# Sprite sheet (for game engines)
python scripts/animate.py walk.json --format spritesheet -o walk_sheet.png --layout horizontal
python scripts/quality_check.py --animation walk.json
Checks: palette stability across frames (no off-palette colors), pixel rate consistency (sub-pixel-AA matches), total mass conservation (8-pixel torso stays 8 pixels across frames), per-frame quality scores.
When user provides a real photo / hi-res illustration and asks for pixel art version.
Pipeline (in scripts/preprocess.py):
Image.NEAREST (NOT bicubic — that introduces fractional pixels = AI-slop signal)Usage:
python scripts/preprocess.py photo.jpg --target-size 64x64 --palette aap-64 --dither floyd-steinberg -o pixel.png
Important: AI-generated art (Stable Diffusion, Midjourney) is NOT pixel art even if it looks pixelated. It usually has fractional pixel widths and noise instead of dithering. Always run preprocess pipeline + quality check on AI output before treating it as pixel art.
For game engines (Unity, Godot, Unreal) wanting a single PNG with all frames.
# Layout: rows = animation type, cols = frames (canonical convention)
python scripts/animate.py character.json --format spritesheet \
--layout grid --rows 4 --cols 8 -o character_sheet.png
Conventions:
.json metadata file alongside (Aseprite-compatible format)When user asks "review this pixel art" or "is this good":
python scripts/quality_check.py existing_sprite.png --verbose
Returns JSON with:
For Generator-Evaluator review (independent agent), invoke the pixel-art-reviewer agent (see agents/pixel-art-reviewer.md). It runs quality_check.py + reads the image with fresh context and writes a verdict.
python scripts/palette.py --list
Returns 30+ palettes grouped by category:
python scripts/palette.py --extract photo.jpg --colors 16 --method median-cut
Methods: kmeans (slow, high quality), median-cut (default, balanced), octree (fast).
python scripts/palette.py --ramp "#5b3a3a" --steps 5 --hue-shift 40
Generates a 5-step ramp from dark→bright with proper hue rotation (Endesga rule). Use this when you need a fresh material color (skin tone, metal, leather) without a full palette.
The skill respects multiple cultural canons. Match the user's stated style:
| User mentions | Read this |
|---|---|
| 武侠 / 仙侠 / wuxia / xianxia | references/07-cultural-styles.md#chinese-xianxia |
| 故宫 / palace / red wall | Use gugong-red-wall palette |
| 道袍 / robe animation | Add sleeve secondary animation channel |
| 도트 / dot graphic / Korean | references/07-cultural-styles.md#korean-dot |
| 산나비 / Sanabi / Skul | "Hand-drawn dot" quality discriminator |
| MapleStory / 메이플스토리풍 | High-detail 64-128px portraits, costume-friendly |
| Punch Club / Stoneshard | Mandatory contour darker than darkest pixel |
| Loop Hero | Multi-tier sprite consistency mode |
| Celeste | 320×180 base resolution, 4-frame animations |
| Hyper Light Drifter | 480×270, "pixel impressionism", no outlines |
endesga-32, output must use ≤32 unique colors.Image.quantize defaults to median cut. For better quality on photos use method=Image.Quantize.LIBIMAGEQUANT if pyImageQuant is installed; otherwise MEDIANCUT is fine.--indexed flag when palette is fixed..aseprite) preserve tags, layers, palette in original form. If user has Aseprite installed, offer to export .aseprite alongside PNG."background": "transparent" ≠ "#FFFFFF". Default to transparent for game sprites; use solid color only for non-cutout art.preprocess.py pipeline. Don't trust their pixel grid alignment.| Symptom | Cause | Fix |
|---|---|---|
| "Pillow not installed" | Missing dependency | pip install Pillow |
| Garbled output | Pixel coordinates outside grid | Check 0 ≤ x < width, 0 ≤ y < height |
| Colors look wrong | Hex shorthand or named color mismatch | Use full #RRGGBB hex |
| Image looks blurry | Pillow used BILINEAR resize | Use Image.NEAREST for pixel art |
| Quality score < 60 | Multiple quality issues | Read full JSON output; common fixes: reduce palette to ≤32 colors, remove orphan pixels, redo with single light source |
| GIF has color bands | Limited 256-palette quantization | Switch to APNG or use --no-quantize |
| Animation jitters | Inconsistent pixel positions across frames | Run quality_check.py --animation to identify frame with mass deviation |
| Pillow shading detected | Anti-pattern shading | Re-shade with explicit light source (top-left), darkest pixels in shadow side only |
| Doublies detected | Two parallel 1-px lines | Merge into single 2-px line OR remove the redundant line |
| Topic | File |
|---|---|
| Drawing techniques (cluster, AA, jaggies, doublies, outlining) | references/01-techniques.md |
| Palette theory, dithering, banding | references/02-palette-theory.md |
| Shading, light, materials | references/03-shading-materials.md |
| Animation principles, frame counts, smear, sub-pixel | references/04-animation.md |
| Quality rubric + anti-AI-slop checklist | references/05-quality-rubric.md |
| Tools and libraries (Aseprite, Pillow, pyxelate, etc.) | references/06-tools-and-libraries.md |
| Cultural styles (CN/KR/RU/Western) | references/07-cultural-styles.md |
| Extended JSON schema spec | references/08-json-schema.md |
For independent quality review (Generator-Evaluator pattern): invoke pixel-art-reviewer agent. It runs the quality scripts + reads the rendered image with fresh context, returning PASS/HOLD/REJECT verdict — see agents/pixel-art-reviewer.md for invocation pattern.