@pebbly/aseprite-ai-artist 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/CHANGELOG.md +170 -0
  2. package/LICENSE +21 -0
  3. package/README.md +169 -0
  4. package/agents/animation-director.md +65 -0
  5. package/agents/palette-smith.md +57 -0
  6. package/agents/pixel-critic.md +69 -0
  7. package/agents/rig-builder.md +46 -0
  8. package/bin/aseprite-ai-artist +6 -0
  9. package/bin/aseprite-ai-artist.mjs +44 -0
  10. package/dist/bridge/bridge.d.ts +52 -0
  11. package/dist/bridge/bridge.js +230 -0
  12. package/dist/bridge/bridge.js.map +1 -0
  13. package/dist/bridge/client.d.ts +54 -0
  14. package/dist/bridge/client.js +214 -0
  15. package/dist/bridge/client.js.map +1 -0
  16. package/dist/cli.d.ts +10 -0
  17. package/dist/cli.js +272 -0
  18. package/dist/cli.js.map +1 -0
  19. package/dist/extension.d.ts +21 -0
  20. package/dist/extension.js +65 -0
  21. package/dist/extension.js.map +1 -0
  22. package/dist/install.d.ts +35 -0
  23. package/dist/install.js +185 -0
  24. package/dist/install.js.map +1 -0
  25. package/dist/lib/color.d.ts +66 -0
  26. package/dist/lib/color.js +170 -0
  27. package/dist/lib/color.js.map +1 -0
  28. package/dist/lib/protocol.d.ts +78 -0
  29. package/dist/lib/protocol.js +72 -0
  30. package/dist/lib/protocol.js.map +1 -0
  31. package/dist/lib/render.d.ts +62 -0
  32. package/dist/lib/render.js +134 -0
  33. package/dist/lib/render.js.map +1 -0
  34. package/dist/lib/skills.d.ts +43 -0
  35. package/dist/lib/skills.js +112 -0
  36. package/dist/lib/skills.js.map +1 -0
  37. package/dist/lib/version.d.ts +4 -0
  38. package/dist/lib/version.js +25 -0
  39. package/dist/lib/version.js.map +1 -0
  40. package/dist/server.d.ts +15 -0
  41. package/dist/server.js +144 -0
  42. package/dist/server.js.map +1 -0
  43. package/dist/tools/assets.d.ts +3 -0
  44. package/dist/tools/assets.js +181 -0
  45. package/dist/tools/assets.js.map +1 -0
  46. package/dist/tools/craft.d.ts +12 -0
  47. package/dist/tools/craft.js +143 -0
  48. package/dist/tools/craft.js.map +1 -0
  49. package/dist/tools/draw.d.ts +3 -0
  50. package/dist/tools/draw.js +256 -0
  51. package/dist/tools/draw.js.map +1 -0
  52. package/dist/tools/escape.d.ts +12 -0
  53. package/dist/tools/escape.js +49 -0
  54. package/dist/tools/escape.js.map +1 -0
  55. package/dist/tools/kit.d.ts +29 -0
  56. package/dist/tools/kit.js +85 -0
  57. package/dist/tools/kit.js.map +1 -0
  58. package/dist/tools/look.d.ts +7 -0
  59. package/dist/tools/look.js +215 -0
  60. package/dist/tools/look.js.map +1 -0
  61. package/dist/tools/palette.d.ts +3 -0
  62. package/dist/tools/palette.js +232 -0
  63. package/dist/tools/palette.js.map +1 -0
  64. package/dist/tools/session.d.ts +3 -0
  65. package/dist/tools/session.js +231 -0
  66. package/dist/tools/session.js.map +1 -0
  67. package/dist/tools/structure.d.ts +3 -0
  68. package/dist/tools/structure.js +218 -0
  69. package/dist/tools/structure.js.map +1 -0
  70. package/examples/mcp-configs/claude-code.json +9 -0
  71. package/examples/mcp-configs/codex.toml +13 -0
  72. package/examples/mcp-configs/cursor.json +9 -0
  73. package/examples/mcp-configs/gemini-cli.json +9 -0
  74. package/examples/mcp-configs/vscode.json +10 -0
  75. package/extension/ai-artist.lua +3291 -0
  76. package/extension/package.json +14 -0
  77. package/hooks/hooks.json +25 -0
  78. package/hooks/look-nudge.mjs +46 -0
  79. package/hooks/session-status.mjs +47 -0
  80. package/knowledge/palettes.json +60 -0
  81. package/package.json +69 -0
  82. package/rules/00-core-principles.md +57 -0
  83. package/rules/01-palette-and-color.md +51 -0
  84. package/rules/02-shading-and-light.md +56 -0
  85. package/rules/03-silhouette-and-form.md +60 -0
  86. package/rules/04-outlines-and-edges.md +46 -0
  87. package/rules/05-animation.md +62 -0
  88. package/rules/06-layers-and-rigging.md +52 -0
  89. package/rules/07-review-checklist.md +51 -0
  90. package/rules/README.md +16 -0
  91. package/skills/README.md +29 -0
  92. package/skills/pixel-animate/SKILL.md +91 -0
  93. package/skills/pixel-brief/SKILL.md +61 -0
  94. package/skills/pixel-draw/SKILL.md +93 -0
  95. package/skills/pixel-export/SKILL.md +80 -0
  96. package/skills/pixel-fix/SKILL.md +91 -0
  97. package/skills/pixel-new/SKILL.md +70 -0
  98. package/skills/pixel-palette/SKILL.md +80 -0
  99. package/skills/pixel-review/SKILL.md +81 -0
  100. package/skills/pixel-rig/SKILL.md +76 -0
  101. package/skills/pixel-shade/SKILL.md +77 -0
  102. package/skills/pixel-tileset/SKILL.md +104 -0
  103. package/templates/AGENTS.section.md +33 -0
@@ -0,0 +1,81 @@
1
+ ---
2
+ name: pixel-review
3
+ title: Review a sprite before calling it done
4
+ description: Run the mechanical checks and the by-eye checks, then report what you found with evidence instead of declaring success. Use before finishing any pixel-art task, and when the user asks "is this good" or "why does this look off".
5
+ ---
6
+
7
+ # Review a sprite before calling it done
8
+
9
+ "Done" is a claim. This is how you earn it.
10
+
11
+ ## Procedure
12
+
13
+ ### 1. Mechanical checks
14
+
15
+ ```
16
+ validate
17
+ ```
18
+
19
+ Reports off-palette colours, semi-transparent pixels, isolated stray pixels,
20
+ untagged animation frames, uniform timing and unsaved state — each with a
21
+ location where one exists.
22
+
23
+ Fix every **error**. For each **warning** you do not fix, have a reason and say
24
+ it.
25
+
26
+ ### 2. Look at it
27
+
28
+ ```
29
+ look op="preview"
30
+ ```
31
+
32
+ Work down `rules://07-review-checklist`:
33
+
34
+ - **Silhouette** — recognisable as one flat shape?
35
+ - **Value contrast** — would it survive desaturation?
36
+ - **Light** — one direction, everywhere?
37
+ - **Ramps** — do shadows hue-shift, or are they just darker?
38
+ - **Lines** — even runs, no doubled pixels?
39
+ - **Outline** — one style, applied consistently?
40
+ - **Banding** — long parallel stripes of adjacent ramp steps?
41
+ - **Detail placement** — spent on the face and weapon, not the boots?
42
+
43
+ ### 3. Look closely at anything that felt off
44
+
45
+ ```
46
+ look op="ascii"
47
+ ```
48
+
49
+ This is where you find the pixel one row too low and the line run of 3 in a
50
+ sequence of 2s. If step 2 left you with "something is wrong but I cannot say
51
+ what", this is the step that names it.
52
+
53
+ ### 4. For animation
54
+
55
+ ```
56
+ look op="filmstrip"
57
+ ```
58
+
59
+ Volume consistent? Height consistent? Does it loop? Do contact poses hold
60
+ longer? Is there anticipation before strong actions?
61
+
62
+ ### 5. Report
63
+
64
+ State what you checked, what you found, and what you chose not to change:
65
+
66
+ > Validated clean. Silhouette reads at 1×; value contrast holds desaturated.
67
+ > Two compromises: the plume colour snapped from `#e04a6a` to `#ff77a8`
68
+ > (ΔE 14) because PICO-8 has nothing closer, and the far arm is 2px thick
69
+ > rather than 3 to keep the silhouette from fusing with the torso.
70
+
71
+ A user can act on a stated compromise. They cannot act on one you hid.
72
+
73
+ ## When the user asks "why does this look off"
74
+
75
+ Run the same checks, then name the specific cause rather than listing
76
+ possibilities. The usual answers, in order of frequency: too many colours, flat
77
+ shading, semi-transparent pixels, mushy silhouette, uniform animation timing.
78
+
79
+ ## Related
80
+
81
+ `rules://07-review-checklist`, and every other rule it points at.
@@ -0,0 +1,76 @@
1
+ ---
2
+ name: pixel-rig
3
+ title: Rig a character for animation
4
+ description: Split a character onto named layers — head, torso, arms, legs — so it can be animated by moving cels instead of redrawing pixels. Use before animating anything, or when limbs are baked into one layer.
5
+ ---
6
+
7
+ # Rig a character for animation
8
+
9
+ Pixels baked into a single layer cannot be animated without redrawing them. Rig
10
+ first; separating a finished sprite later is more work than building it split.
11
+
12
+ ## The standard rig
13
+
14
+ Bottom to top, so nearer parts draw over farther ones:
15
+
16
+ ```
17
+ arm-near ← camera-side arm
18
+ leg-near
19
+ head
20
+ torso
21
+ arm-far ← partly hidden by the torso; this is what sells depth
22
+ leg-far
23
+ shadow ← ground contact, if the style has one
24
+ ```
25
+
26
+ Add `weapon`, `cape`, `hair-front`, `hair-back` as the design needs. Keep names
27
+ stable — every later call refers to them by name.
28
+
29
+ ## Building it fresh
30
+
31
+ One batch, one undo step:
32
+
33
+ ```
34
+ layer batch=[
35
+ {op:"create", name:"shadow"},
36
+ {op:"create", name:"leg-far"},
37
+ {op:"create", name:"arm-far"},
38
+ {op:"create", name:"torso"},
39
+ {op:"create", name:"head"},
40
+ {op:"create", name:"leg-near"},
41
+ {op:"create", name:"arm-near"},
42
+ ]
43
+ ```
44
+
45
+ Then draw each part on its own layer from the start.
46
+
47
+ ## Splitting an existing sprite
48
+
49
+ When the art is already baked into one layer:
50
+
51
+ 1. `sprite_info` to see what you have, and `look op="ascii"` to find exact part
52
+ boundaries. Guessing at coordinates here is how limbs get clipped.
53
+ 2. Create the rig layers (above).
54
+ 3. For each part, in one `draw` call per target layer:
55
+ ```
56
+ draw layer="head" ops=[{ kind:"blit", from:{x:12,y:4,width:8,height:8}, to:{x:12,y:4} }]
57
+ ```
58
+ `blit` copies from the source layer; `skipTransparent` keeps the copy clean.
59
+ 4. Clear the copied region from the original layer, or rename the original to
60
+ `flat-original` and hide it. **Prefer hiding** — if a boundary was wrong you
61
+ want the original still there.
62
+ 5. `look op="preview"` with the original hidden. The sprite should look
63
+ unchanged. If a limb lost pixels, the boundary was wrong.
64
+
65
+ ## Overlap matters
66
+
67
+ A limb needs a pixel or two of overlap with the torso, or a gap appears the
68
+ moment it rotates. Copy generously and let the stacking order hide the excess.
69
+
70
+ ## Then
71
+
72
+ `pixel-animate`.
73
+
74
+ ## Related
75
+
76
+ `rules://06-layers-and-rigging`, `rules://03-silhouette-and-form`.
@@ -0,0 +1,77 @@
1
+ ---
2
+ name: pixel-shade
3
+ title: Shade a sprite
4
+ description: Add light and shadow with proper hue shifting, one step at a time, so the sprite gains form without gaining the flat-luminance look that marks generated pixel art. Use when flat art needs volume.
5
+ ---
6
+
7
+ # Shade a sprite
8
+
9
+ Flat shading — the same hue, darker — is the clearest signal that a sprite was
10
+ made by moving a brightness slider. Real shading shifts hue.
11
+
12
+ ## The rule
13
+
14
+ - **Shadows** rotate toward blue/purple and desaturate slightly.
15
+ - **Highlights** rotate toward yellow/orange and saturate slightly.
16
+
17
+ `recolor` op `shade` implements this. Use it instead of choosing darker hex
18
+ values yourself.
19
+
20
+ ## Procedure
21
+
22
+ 1. **Fix the light direction** and state it. Upper-left is the safe default. It
23
+ does not move again — not across the sprite, not across animation frames.
24
+
25
+ 2. **Confirm the flat art is right first.** `look` op `preview`. Shading a bad
26
+ silhouette wastes the effort.
27
+
28
+ 3. **One shadow step.** Select the region away from the light, then:
29
+
30
+ ```
31
+ select op="rect" rect={…}
32
+ recolor op="shade" amount=-0.2 selectionOnly=true
33
+ ```
34
+
35
+ Or draw the shadow shape directly with `draw` if it needs to follow a form
36
+ the selection tools cannot describe.
37
+
38
+ 4. **Look.** `look op="preview"`. Does it read as volume, or as a stain? A
39
+ shadow that follows the form's cross-section reads; one that follows the
40
+ outline does not.
41
+
42
+ 5. **One light step**, on the side facing the light: `amount=0.2`.
43
+
44
+ 6. **Look again.** Most sprites are finished here.
45
+
46
+ 7. **Only if it needs it**: a deep shadow (`amount=-0.4`) in occluded crevices,
47
+ a specular highlight of one or two pixels on the hardest material, or
48
+ reflected light — a faint cool step on the shadow side's outer edge, which
49
+ makes metal read as metal.
50
+
51
+ ## Ramps
52
+
53
+ If you will shade a material more than once, put its ramp in the palette:
54
+
55
+ ```
56
+ palette op="ramp" base="#c04030" steps=5
57
+ ```
58
+
59
+ Then draw with ramp entries directly. Reuse the darkest step across materials —
60
+ it ties a sprite together and costs no palette slots.
61
+
62
+ ## Dithering
63
+
64
+ Only on 32px+ and only in large flat areas. Use `bayer4`, keep the two colours
65
+ adjacent in a ramp, and stop if it reads as noise. See
66
+ `rules://02-shading-and-light`.
67
+
68
+ ## Checks
69
+
70
+ - Is the light in exactly one place?
71
+ - Do the shadows hue-shift, or are they the same hue darker?
72
+ - Any banding — long parallel stripes of adjacent steps?
73
+ - Any semi-transparent pixels? (`validate` will tell you.)
74
+
75
+ ## Related
76
+
77
+ `rules://02-shading-and-light`, `rules://01-palette-and-color`.
@@ -0,0 +1,104 @@
1
+ ---
2
+ name: pixel-tileset
3
+ title: Build a tileset
4
+ description: Design seamless tiles and autotile sets, or deduplicate a hand-painted mockup into a reusable tileset, then export for Tiled or Godot. Use for level art, terrain and anything that repeats.
5
+ ---
6
+
7
+ # Build a tileset
8
+
9
+ Requires an extension advertising the `tileset` feature — check `preflight`
10
+ first. Older builds answer `unsupported_command` loudly rather than doing
11
+ nothing.
12
+
13
+ ## Decide the grid before anything else
14
+
15
+ The tile size is the one decision everything else depends on, and it belongs to
16
+ the game, not to the art. Ask if you do not know it. 16×16 and 32×32 are the
17
+ common answers.
18
+
19
+ ## Seamless tiles
20
+
21
+ A tile is seamless when its right edge continues into its own left edge, and its
22
+ bottom into its own top.
23
+
24
+ Method that works:
25
+
26
+ 1. Draw the tile's interior first, ignoring edges.
27
+ 2. Draw the edge pattern on one side.
28
+ 3. `look op="ascii"` the first and last columns and make them continue into each
29
+ other. This is exact work; do it in the text grid, not by eye.
30
+ 4. Same for top and bottom rows.
31
+ 5. Stamp the tile in a 3×3 block and `look op="preview"`. Seams show up
32
+ immediately when tiled; they are invisible in isolation.
33
+
34
+ **Avoid a repeating feature.** A distinctive rock in the middle of a grass tile
35
+ becomes a visible grid the moment it repeats. Keep repeating tiles low-contrast
36
+ and put the distinctive elements in occasional variant tiles.
37
+
38
+ ## Autotiling
39
+
40
+ A blob-47 set covers every combination of neighbours for a 4-connected terrain.
41
+ It is 47 tiles, and hand-authoring them in the right order is where this goes
42
+ wrong — build the terrain body first, then the edge and corner cases, then
43
+ export with `layout="blob47"` so the exporter writes the wangset.
44
+
45
+ ## From a painted mockup
46
+
47
+ Painting a level by hand and extracting tiles from it produces better-looking
48
+ tilesets than authoring tiles in isolation, because you see the whole picture
49
+ while drawing.
50
+
51
+ 1. Paint the mockup on a normal layer, on a canvas that is a whole number of
52
+ tiles in each direction. `pack` refuses otherwise rather than silently
53
+ losing a partial edge tile.
54
+ 2. Pack it:
55
+ ```
56
+ tileset op="pack" layer="mockup" name="terrain" tileWidth=16 tileHeight=16
57
+ ```
58
+ You get a tileset plus a tilemap layer that reconstructs the mockup exactly.
59
+ The mockup is **hidden, not deleted** — unhide it to compare if a tile looks
60
+ wrong.
61
+ 3. Read the result. `cellCount` against `tileCount` tells you how much the
62
+ mockup actually reused. A 400-cell mockup that yields 300 tiles was painted
63
+ without regard to the grid; the tool says so, and the fix is to redraw with
64
+ the grid visible, not to accept it.
65
+ 4. `tolerance` merges near-identical cells (per-channel difference, 0–255). It
66
+ is off by default because a merge changes the art: the tilemap becomes an
67
+ approximation of the mockup rather than a copy, and the result says how many
68
+ cells that affected.
69
+
70
+ ## Export
71
+
72
+ ```
73
+ tileset op="export" layer="terrain" format="tiled" path="…/terrain.tsj"
74
+ ```
75
+
76
+ Writes three files: the packed PNG, the `.tsj` tileset, and a `.tmj` map that
77
+ uses it — so the export opens in Tiled as a level, not just an image.
78
+
79
+ - `format="godot"` writes a Godot 4 `TileSet` resource (`.tres`).
80
+ - `format="json"` writes the tile grid plus the tilemap layout, for a custom
81
+ engine. It states its own index convention in the file.
82
+ - LDtk needs no exporter — it reads `.aseprite` directly, so just save the
83
+ document.
84
+
85
+ Aseprite reserves tile index 0 for the empty tile. The exporter drops it from
86
+ the atlas so engine indices line up, and index 0 becomes "no tile", which is
87
+ what every engine expects.
88
+
89
+ ## Autotiling
90
+
91
+ ```
92
+ tileset op="export" format="tiled" layout="blob47" path="…/terrain.tsj"
93
+ ```
94
+
95
+ Adds a Tiled wangset for 4-connected autotiling. It assumes the 47 tiles are
96
+ authored in **canonical blob47 order** — the 47 distinct neighbour masks in
97
+ ascending order, after Aseprite's empty tile — and refuses if the set is
98
+ incomplete rather than writing a wangset that autotiles wrongly. If you are not
99
+ sure of the ordering, export `format="json"` first: it reports the
100
+ index-to-mask mapping so you can check a few tiles by eye.
101
+
102
+ ## Related
103
+
104
+ `rules://04-outlines-and-edges` for edge consistency.
@@ -0,0 +1,33 @@
1
+ ## Pixel art in Aseprite
2
+
3
+ This project has `aseprite-ai-artist` wired in as an MCP server. It draws into
4
+ the Aseprite window that is open on this machine — not into files on disk.
5
+
6
+ **Before any pixel-art work:**
7
+
8
+ 1. Call `preflight`. If `ready` is false, stop and tell the person. Do **not**
9
+ fall back to editing `.aseprite` or `.png` files directly: they would not see
10
+ the change in their open editor, and their next save would overwrite it.
11
+ 2. Call `sprite_info`. Layer names, frame count and palette come from the
12
+ document, never from assumption.
13
+ 3. Read the workflow that matches the task. The server exposes them as MCP
14
+ resources — `skill://pixel-draw`, `skill://pixel-animate`,
15
+ `skill://pixel-review` and others — and the craft rules as `rules://index`.
16
+ Start with `rules://00-core-principles`.
17
+
18
+ **While working:**
19
+
20
+ - **Batch.** One `draw` call carrying every operation is correct; forty calls
21
+ carrying one each is wrong. Every call is one undo step for the person.
22
+ - **Look at your work.** After drawing, call `look` — op `preview` for the
23
+ overall read, op `ascii` for exact pixel positions, op `filmstrip` to review
24
+ an animation. A tool result saying "412 pixels changed" is not evidence that
25
+ the sprite is right.
26
+ - **Keep the palette.** `draw` and `recolor` snap colours to the sprite's
27
+ palette by perceptual distance. If a colour you want is far from every palette
28
+ entry, say so and ask before widening the palette.
29
+ - **Do not change what was not asked about.** No resizing, re-indexing,
30
+ flattening or overwriting without a request.
31
+
32
+ **Before saying anything is finished:** call `validate`, fix every error, and
33
+ report the warnings you chose not to fix along with the reason.