pixelclaw 0.0.0-stage → 0.2.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.
@@ -0,0 +1,281 @@
1
+ ---
2
+ name: pixelclaw
3
+ description: Make pixel art for a game with PixelClaw, an indexed-colour editor driven by commands through its MCP tools (project, run, seeds, view, check, changes, history, plan, work, review, export, import), while a person watches, edits and asks for work in the browser. Use when asked to draw or fix tiles, sprites, autotile families, maps or a game's whole art set, to plan a set from a theme (manifest and style guide), to review pixel art blind, or to export it to a game.
4
+ ---
5
+
6
+ # PixelClaw
7
+
8
+ You draw pixel art by writing commands. Every pixel is a palette entry; every command goes on the
9
+ asset's tape, so a document is its tape replayed and every edit (yours and the person's) can be
10
+ read back. You see your work through `view` (images and exact text grids) and `check` (numbers
11
+ with pixel coordinates). The person watches the same document live, and can draw, leave notes and
12
+ approve work in the dashboard.
13
+
14
+ If the tools are missing, the server is not connected:
15
+ `claude mcp add pixelclaw -- npx pixelclaw serve --project <folder>.pclaw` (then restart Claude Code).
16
+
17
+ ## Every session
18
+
19
+ 1. `project` (with `path` to open or create a project). Give the person the watch link it prints,
20
+ and the dashboard (`…&tab=dashboard`) when there is a plan.
21
+ 2. `changes` at the start of every turn while someone watches, and whenever they say they did
22
+ something. Carry on from their edits; never silently redo their pixels. Close a note you have
23
+ dealt with: `note done <id>`.
24
+ 3. `plan` at the start of the session and again after each finished asset: it lists the
25
+ **requests** people made in the dashboard first, then what is left and what is failing.
26
+ If you are driving a project served with `pixelclaw serve` and a person may be watching, start
27
+ a background wait right away and keep one running between tasks:
28
+ `pixelclaw await <project folder>` (run it in the background; it blocks, prints what people asked
29
+ for and a cursor, then exits). When it exits, handle what it printed (`work` for a request,
30
+ `changes` for an approval or rejection), then **start it again with `--since <cursor>`**. Exit
31
+ code 3 means nothing happened; restart it the same way. Without it, nobody knows you are there
32
+ and a request the person filed just sits. `plan` tells you when open requests have no listener.
33
+ 4. **Requests before planned work.** `work` claims the next open request and says what is asked
34
+ (draw a planned asset, change a drawn one, or a new asset the person added to the manifest).
35
+ Do it, then `work(action="done", text=<what changed>)`. If you cannot go on without the person
36
+ (a choice only they can make), `work(action="blocked", text=<one clear question>)` and move on;
37
+ their answer opens the request again. Post `work(action="progress", text=…)` on long ones: the
38
+ person sees it on the card. Without PixelClaw's MCP tools, the same actions are
39
+ `pixelclaw work <project> claim | progress "…" | done "…" | block "…"` (below).
40
+
41
+ ## House rules
42
+
43
+ - **Look, then verify.** After each meaningful batch, look once at an image (`render`, `tile3x3`
44
+ for tiles, `game` for sprites, `map` for families and maps), then use `grid` (or a region of it)
45
+ to confirm exact pixels. Never judge a tile alone when it will be seen tiled; never judge a sprite
46
+ away from its ground.
47
+ - **Small exact shapes as `paint` blocks** (up to about 32x32), outlines and silhouettes from
48
+ primitives, `mirror … live` for symmetric shapes. Count and quote coordinates.
49
+ - **Texture by generators, not by hand:** `noise` (clustered, on a ramp), `scatter`, `voronoi`,
50
+ `bricks`; tiles are `wrap=on` so they tile by construction. Another seed is another variant.
51
+ - **Structure by generators too:** `pebbles ramp=<stone ramp>` (stones with a shadow side and a lit
52
+ pixel) and `tufts ramp=<grass ramp>` (blades) are lit from the style guide's light, never
53
+ overlap, and keep the tile's rows and columns even, so they pass `repetition`, `seam` and
54
+ `jaggies` at 16, 24 and 48 px with their defaults. Lay them over a calm `noise` ground.
55
+ - **Choose seeds by the checks, not by hand:** `seeds(asset, line, count=8)` tries a generator
56
+ line with N seeds as dry runs and ranks them (fewest failing, least over, most room);
57
+ `apply=true` keeps the best. **Try before you keep:** `run(…, dry=true)` applies to a copy,
58
+ checks it, and keeps nothing (a pebble, a walkable flag, a `family cut`).
59
+ - **Helpers apply the style guide exactly:** `outline` (the style guide's ink when you leave out
60
+ `c=`), `shade` (its light when you leave out `light=`), `clean orphans`, pixel-perfect lines,
61
+ `shadow` (an ellipse under a sprite, away from the light, in `style.shadow.c`). On maps, set
62
+ `style.shadow` (`{"c": "darker"}`) and every objects layer casts shadows on the ground (`layer add
63
+ props objects` writes `shadow=darker shadowdir=se`); do not also bake a shadow into those objects.
64
+ - **Keep the checks green, but do not stop at green.** Look at the 3x3 or the game view and judge
65
+ it as a player would. Fix by coordinates from `check`, not by redrawing.
66
+ - **Keep art inside its cell and in one piece:** `margin` fails a sprite touching the top or sides
67
+ of its cell (it stands on the bottom), `pieces` a part floating apart (a lamp room above its
68
+ tower: join it). Colours meant for one thing only (a lantern's glow, a gem) go in
69
+ `style.reserved` (`{"glow": ["lantern"]}`); `palette` then flags them anywhere else.
70
+ - **One light, one outline rule, one level of detail across a set.** The `consistency` check
71
+ compares each asset with its set; a recolour (palette swap) is recognised and not compared with
72
+ its source.
73
+ - **Never fake a pass.** If a check is wrong for an asset, say so and turn it off for that asset in
74
+ the style guide (`style.assets.<name>.checks`) with the reason in style.md; do not draw to
75
+ satisfy a number.
76
+ - Native grid 24 px is fully verifiable; 48 px needs regions and helpers; 96 px needs an underlay
77
+ and region work, with a hand-made 24 px copy beside it.
78
+
79
+ ## Per-size defaults
80
+
81
+ Set the project's grid first (`project(grid=48)`, or `pixelclaw new <dir> --grid 48`): the project
82
+ summary's second line says what follows from it.
83
+
84
+ | | 16 px | 24 px (default) | 48 px |
85
+ |---|---|---|---|
86
+ | `new map` without `tile=` | 16 (grid 16) | 24 | 48 |
87
+ | camera (`style.camera` unset) | 256x144 | 384x216 | 768x432 (16x9 cells) |
88
+ | draw scale (`style.drawScale` unset) | 2x | 2x | 1x (the game view shows the scene once) |
89
+ | `noise` specks (no `cluster=`) | 1..3 | 1..3 | 2..6 |
90
+ | tile `jaggies` allowance | 2 | 2 | 8 (per 24x24 px) |
91
+ | `repetition` band widths | 1..4 lines | 1..6 | 1..12, counted in lines of 24 px |
92
+ | map `lattice`: a mark is at least | 2 px | 5 px | 18 px, ±2 px counts as the same spot |
93
+ | icon stroke / centre limits | 1 / 1.5 px | 1.5 / 2.25 px on 24 px icons | 3 / 4.5 px on 48 px icons |
94
+
95
+ At 48 px: look with `view grid region=` (a whole 48x48 grid is long), `render` comes back at 4x
96
+ (192 px) and `tile3x3` at 4x (576 px). Make texture variants by **forking the base and changing
97
+ only its inside** (`fork moor moor_b`, `variant of=moor`, then `noise 4,4 40x40 … base=keep
98
+ wrap=off` and your own marks): two independent noise tiles side by side show a seam where their
99
+ bigger specks are cut at the border. With the structure generators the fork can lay the same
100
+ ground again and only change the generator's seed, keeping its `edges=` (`examples/ember-moor.pclaw`
101
+ uses three looks of noise and `tufts edges=2`, map seam 0.17, lattice 12%).
102
+ Expect more `jaggies` from long curves: a big ellipse is fine alone, but where a second shape meets
103
+ its outline the step runs go uneven; let one shape make the silhouette and shade inside it.
104
+
105
+ ## Workflows
106
+
107
+ ### A theme → a whole set (the project pipeline)
108
+
109
+ 1. **Write the style guide**: `style.md` (palette and ramps, light direction, outline rule,
110
+ dithering, cluster size, sizes, what each material looks like) and the matching settings in
111
+ `project.json` `style` (`palettes`, `outline`, `light`, `ground`, `drawScale`, `sizes`,
112
+ `checks`, `sets`). The palette goes in `palettes/<name>.json` (keys, names, hex, ramps).
113
+ 2. **Write the manifest** with `plan(manifest=…)`: the theme paragraph, the sets, and every asset
114
+ with its kind, size, set, a one-line description (what it is meant to read as), and as needed
115
+ scheme, inside/outside and band (families), frames and views (sprites), cells (objects), the
116
+ drawn height in pixels (props and figures: this is what keeps a chest smaller than a person),
117
+ `recolourOf`/`variantOf`, and `flat` (its colour in templates). See manifest.md. The tool
118
+ checks it against its schema and writes nothing if it has problems.
119
+ 3. **Flat templates**: `plan(templates=true)` draws a mockup screen and a coverage map per family
120
+ in `templates/`. Show the person the mockup; adjust sizes and sets before drawing.
121
+ 4. **Author** each asset. A planned asset's `new` line can leave out its size, palette and scheme
122
+ (`new sprite urn`): the manifest fills them in and the line records them.
123
+ 5. **Derive** the families, **compose** sample maps (`view map`), run every check.
124
+ 6. **Review**: the blind review below, then `mark reviewed "<what was found and fixed>"` on each
125
+ asset; the person approves in the dashboard (`mark approved`) or asks for changes
126
+ (`mark rejected "…"`: read it with `changes`, fix, review again).
127
+ 7. **Export** with the game's profile (`export(profile=…, dest=…)`); `plan` shows `exported`.
128
+
129
+ Statuses are worked out, never set by hand: planned → drafted (exists) → checked (every check
130
+ passes) → reviewed → approved → exported. A change to the art after a mark or an export sends the
131
+ asset back down, and `plan` says why.
132
+
133
+ ### Requests from the dashboard
134
+
135
+ People ask for work without talking to you: "Draw this" on a planned card, "Ask for changes" on
136
+ a drawn one (also a `mark rejected "…"` on its tape), "Add an asset" (a new manifest entry). They
137
+ wait in `requests.jsonl`; `plan` lists them first and `work` hands them out one at a time. The
138
+ person's card reads *sent* until something hands it to you, then *seen by claude*: keep a background
139
+ `pixelclaw await <project>` running (restart it after each exit, `--since` the cursor it printed) so
140
+ that happens as soon as they press the button, and the card never claims more than is true.
141
+
142
+ 1. `work` → read what is asked, the asset's plan entry and status, and any answer to an earlier
143
+ question.
144
+ 2. Draw or change it as for any asset (the house rules, the checks, a look at the game view).
145
+ For a change, `changes` shows the person's own edits and notes on it.
146
+ 3. `work(action="done", text="…")` with what you did in a sentence the person can check against
147
+ the card; or `blocked` with a question. `done` is refused while the asset fails a check: the
148
+ reply lists them; fix them, or block with a question when only the person can decide. Then `plan`, and `work` again until it says there are
149
+ no open requests; then carry on with planned work.
150
+
151
+ **No PixelClaw MCP tools in this session** (the project is served with `serve --no-mcp`, or you
152
+ only have a shell): the same routine with the CLI, which goes through the running server so the
153
+ cards move live:
154
+
155
+ ```sh
156
+ pixelclaw work <project> list # the open requests (now seen by claude)
157
+ pixelclaw work <project> claim # step 1: the next open one (or claim r3)
158
+ pixelclaw work <project> progress "<a short note>"
159
+ pixelclaw work <project> done "<what changed>" # step 3; refused while a check fails
160
+ pixelclaw work <project> block "<one clear question>"
161
+ ```
162
+
163
+ Draw with `pixelclaw run <project> -e "…"` (or a script file), look with `pixelclaw view`, check
164
+ with `pixelclaw check`; `pixelclaw plan <project>` for what is left.
165
+
166
+ A headless worker (`pixelclaw work <project> start`, or Start Claude in the dashboard when the project enables
167
+ it) follows the same routine with no one at the keyboard: never ask in chat, ask with `blocked`.
168
+ It has only the PixelClaw tools (no shell, files or web; files outside the project are refused),
169
+ its system prompt ends with every command of the language, and a session that makes no tool call
170
+ for a while is stopped (docs/worker.md).
171
+
172
+ ### Importing existing art
173
+
174
+ `import(path=<sheet.png>, slice="24x24", set=…)` cuts a sheet into one asset per non-empty cell
175
+ (names by `pattern`, a `names` list, or `namesFrom="manifest"` for the planned entries of a set);
176
+ a folder imports every PNG and .aseprite in it. New assets get manifest entries and every check
177
+ is run; fix what fails by coordinates like any drafted asset.
178
+
179
+ ### A tile
180
+
181
+ `new tile <name> 24x24 bg=<base>` → `seeds` on its `noise`/`scatter` line (apply the best) →
182
+ `view tile3x3` → fix stripes and repeated marks (`check` repetition, seam; one mark on a calm
183
+ tile is fine: the limit rises with the band's spread) → a variant or two by `seeds` from another
184
+ `from=` (`new tile <name>_b …`, `variant of=<name>`) so maps do not weave.
185
+
186
+ A structured ground (shingle, grass with tufts): the calm ground, then `pebbles`/`tufts` (its line
187
+ says `edges=<n>`); each look is a fork of it (`fork shingle shingle_b`, `variant of=shingle`), the
188
+ ground laid again and the same generator with **the same `edges=` and another seed** (rank it with
189
+ `seeds`): every look then has the same stones across its edges and its own inside, so a map can
190
+ `fill mix=` them in any order with no seam and no lattice.
191
+
192
+ ### A sprite or prop
193
+
194
+ Silhouette first (`paint` or primitives), then materials in ramp steps, `shade`, `outline`,
195
+ `clean orphans`; `view game` on its ground beside its set; `check` readability (edge contrast,
196
+ distinct silhouette, lightness spread) and consistency. Animation: frames with ticks, `view S
197
+ frames=…`, `view W mirror=E`, `view anim`; the anim check (8-35 % change per frame, no drift).
198
+
199
+ ### An autotile family
200
+
201
+ `new family <name> 24x24 scheme=blob47` (or the manifest's), `family texture inside|outside
202
+ from=<tile>`, `family band 3:outside 1:foam 2:sand1 radius=3 jitter=2` (jitter: edges that are not
203
+ ruler-straight; pick its seed with `seeds`), then hand-detail the pieces on the band layer (`paint
204
+ @cell(o) …`); every variant follows. Judge on `view map` (seam ≤ 1, ideally ≤ 0.5) and `view
205
+ family`. The family follows the tiles its textures came `from=`: fix the tile, and the family is
206
+ copied again. Rounder corners: `scheme=blob47-round` (built in; fillets). Cliffs: `scheme=face`, paint
207
+ the faces on the band layer: south faces `@cell(face_o)` (ends), `@cell(face_ew)` (the middle),
208
+ `@cell(face_ie_iw)` (inner corners, where the face meets the terrain beside it); side faces
209
+ `@cell(side_e)`/`@cell(side_e_ns)` on the cell's west half (the terrain's east side) and
210
+ `side_w`/`side_w_ns` on its east half; `@cell(corner_ew)` where a side meets the south face's end.
211
+ Give a long cliff other looks: `family detach face_ew_b` (and `face_ew_c`, `side_e_ns_b`,
212
+ `side_w_ns_b`) and draw them; a map spreads them by cell. Roads and rivers that widen or step
213
+ diagonally: `scheme=lane` (a wide lane has a plain middle; a diagonal step draws a strip to the
214
+ corner). A texture variant that should follow later band fixes:
215
+ `fork <f> <f>_b`, `variant of=<f> band=inherit`, then change only its textures. After a `family
216
+ cut`, heed the seam warning.
217
+
218
+ ### A map
219
+
220
+ `new map <name> 40x30 tile=24`, `tiles floor fill <ground tile>` (the floor in one line; `tiles floor fill mix=bed:2,bed_b:1,bed_c:1`
221
+ scatters several looks by weight, the cure for a failing `lattice`), terrain
222
+ layers per family (`walkable=on` when a layer's filled ground is ground objects stand on, not sea;
223
+ terrain that runs off the map has no band along the border unless `border=not`; `mix=meadow:2,clover:1`
224
+ draws the terrain's inside as a scatter of tiles that match its inside texture, a clean border and a
225
+ varied inside),
226
+ `terrain … rect|ellipse|brush`, `place`, `road`, `scatter`; look at it with `view map camera=x,y` (a player's screen); fix
227
+ repetition hot spots with texture variants, and a failing `lattice` (one mark at the same spot of
228
+ most cells, a grid of dots at map scale) with variants that move or leave out the mark; consistency on a map compares the objects standing on
229
+ it.
230
+
231
+ ### A mockup underlay, snapped (optional; costs money with a real provider)
232
+
233
+ On a sheet the size of the scene (`new sheet yard 144x96 cell=24x24`):
234
+ `underlay generate "<the theme, the scene, top-down pixel art>" layout=templates/mockup.png`
235
+ (OpenAI, the person's `OPENAI_API_KEY`; about $0.05 an image at the default; a cost cap per call,
236
+ every call in `logs/underlay-costs.jsonl`; ask before spending) or `underlay import <file.png>
237
+ layout=…`. Show the person the underlay; then `snap`. Read its line: block R² ≥ 0.8 and material
238
+ ≥ 0.85, else reroll (another prompt) or trace over the underlay by hand instead. Cut tiles from the
239
+ draft (`new tile <t>` then `import 0,0 asset=yard region=<x,y>,24x24 layer=draft`), clean them by
240
+ coordinates (`clean orphans size=2`, then what `check` flags) until every check passes, and hold
241
+ them to the set (`consistency`). Never ship a snapped draft unchecked; small fixes are commands,
242
+ not another generation.
243
+
244
+ ### A font
245
+
246
+ `new font <name> 5x7 chars="ABC…"` (or the manifest's), a `glyph <c> << rows >>` per character
247
+ (letters and digits as themselves, others as `U+0021`), `font set line= spacing=`. The `font` check
248
+ holds cap height, x-height, the baseline and advances; the preview's text tab sets it. Export with
249
+ `export(asset, format=strip|bmfont)` or the profile's `fonts`.
250
+
251
+ ### Icons
252
+
253
+ `new icon <name> 16x16`, `icon mode=tone|full|channel` (tone: roles, recoloured by the game; full:
254
+ as drawn; channel: pure-RGB masks), then as a small sprite. Plan the icons as one manifest set:
255
+ `consistency` holds them to one stroke weight and box fill, each optically centred.
256
+
257
+ ## The blind review hand-off
258
+
259
+ The tool calls no model. You hand its bundle to a fresh agent and bring the findings back:
260
+
261
+ 1. `review(set=<set>)` (or `assets=[…]`) writes `reviews/<date>-<set>/`: each asset at game scale
262
+ and enlarged with rulers, tiles 3x3, sprites on their ground, maps, scenes, the palette, the
263
+ style guide, the brief (the theme and what each piece is meant to be) and `rubric.md`. It names
264
+ no author and no method, so the reviewer judges the art alone.
265
+ 2. Start a **fresh-context** agent (the Agent tool, no conversation history) with only:
266
+ *"Review the pixel art in <folder> by following rubric.md in it. Report as rubric.md asks."*
267
+ Do not tell it who made the art, how, or what you think of it.
268
+ 3. Save its answer as `reviews/<date>-<set>/findings.md`.
269
+ 4. Pin each finding on its pixels: `note <x>,<y> [<W>x<H>] "<finding>"` on that asset (scene
270
+ findings by cell, map findings by tile and pixel). Fix them by coordinates and close each note
271
+ (`note done <id>`), or leave it open with a reason the person can read.
272
+ 5. `mark reviewed "<n> findings; fixed …; left open …"` on each reviewed asset.
273
+
274
+ ## Tools in one line each
275
+
276
+ `project` open/list · `run` a batch (one undo group; any error applies nothing; ends with a check
277
+ summary; `dry=true` keeps nothing) · `seeds` rank a generator line's seeds by the checks · `view` render, grid, diff, tile3x3, game, recolour, anim, map, family, density ·
278
+ `check` the full table with coordinates · `changes` the person's edits and notes · `history` the
279
+ tape · `plan` the manifest and statuses (write a manifest, draw templates) · `review` a blind
280
+ bundle · `export` / `import` through profiles. The command language: commands.md beside this
281
+ file, or `docs/commands.md` in the PixelClaw repo.