pxart 0.1.0 free software, MIT licensed
Pixel art
as text.
A sprite is a small plain-text file: a palette, then a grid of characters. It renders to PNG. Language models can write it, git can diff it, and you can read it.
$ pip install git+https://github.com/thethirdbearsolutions/pxart01 A format, and a tool for it
The .px and .map files are the product: plain text, in git, readable by people and models. pxart is one Python file whose commands read them, write them back, or turn them into pictures and other tools' files.
pxart, one Python filehero.pxa sprite: a palette, then grids of its keys; frames, animations, variants
palette.pxa palette file: colors (and variants) that sprites import
room.mapa map: a legend of sprites, then rows of cells, in layers
Nothing procedural lives in these files. Every command reads them, writes them, or turns them into something else; a drawing command leaves behind ordinary rows of keys.
02 Write, render, look, fix
The tool is built for one loop. Every step is plain text in and a picture or a number out, so a person or a model can run it.
- write
# A barrel from the harbor-market pack: a palette, then the grid. pxart 1 k #2b1e2f G #5d5869 b #9b6440 B #5e3a2a h #6e4230 ....kkkkkkkk.... ...kBbbbbbbbk... ..kBbbbbbbbbbk.. ..kGGGGGGGGGGk.. .kBbbhbbbbhbbbk. .kBbbhbbbbhbbbk. .kBbbhbbbbhbbbk. .kGGGGGGGGGGGGk. .kBbbhbbbbhbbbk. .kBbbhbbbbhbbbk. .kBbbhbbbbhbbbk. ..kGGGGGGGGGGk.. ..kBbbhbbbhbbk.. ...kBbbbbbbbk... ....kkkkkkkk.... ................barrel.px: a palette, then rows of its keys, typed in any editor. The sprite's size is the grid's size: there's nothing to declare or count. - render

pxart renderdraws each pixel as a block, with a grid and coordinate rulers so you can count pixels. - look
$ pxart anim hero.px:walk/down walk/down/1 110ms vs walk/down/0: shift +0,+1 then 26px (7%) (no shift: 205px) walk/down/2 110ms vs walk/down/1: shift -1,-1 then 82px (23%) (no shift: 278px)anim,onion,statsanddiffprint what changed as numbers, so a 1px jump that's too faint to see still shows up. - fix
$ pxart check face.px FAIL face.px: 1 error(s) face.px:8: E_UNKNOWN_KEY (row 2, x=[8]): keys 'q' aren't in the palettecheckreports every problem at once, each with a stable code, a line and a pixel. Edits rewrite only the lines that changed.
03 Why text?
A model can write it
A sprite is characters on a grid, with no binary format and no coordinates to get wrong. A language model writes the rows, renders them, reads the numbers and fixes what's off, in the same loop you'd use.
Git can diff it
--- face.px
+++ face.px
@@ -9 +9 @@
-...kggggk...
+...kgyygk...Two pixels changed, so the diff is two characters. Review art in a pull request the way you review code.
You can read it
Open any .px in an editor and the picture is right there. Comments say what each key is for, and shared palette files keep a whole pack on the same colors.
04 What it does

A palette, then a grid of its keys, typed in any editor. Sprites that share a palette file share its dusk too.

Frames, timing and pivots in the file. anim prints what moved between frames once the whole-body bob is removed, so a walk cycle that's secretly a bob shows up as a number.

A @variant recolors a palette. Derive a night from the base colors, fit a dusk to another pack's, and keep the lamps lit.

Lines, polygons, pixel-clean ellipses, fills, light-aware shading and outlines, for sprites too big to type pixel by pixel.

Stack sprites from packs whose colors clash. Conflicts are reported key by key, and --rekey resolves them without touching the sources.

A text .map of tiles, in layers, becomes a level: as a PNG, as a .px frame, or as a Tiled world.

Slice a PNG sprite sheet into named frames with from-png, then prove the import lossless with diff.

Hand your art to other tools: one PNG per frame, an Aseprite sheet with its tags and pivots, or a Tiled tileset with animated tiles.

check reports every problem in a file at once, each with a stable code, a line and a pixel, so a broken file is quick to fix.

One legend line lists a few tiles and each cell of a map picks one, the same way every time. Water that animates once the room is in Tiled.