Skip to main content

PAGAN — Pixel Art Grammar And Notation

PAGAN is a translator between AI and pixel art. It defines a small text notation for pixel art — palette-keyed grids written in YAML — that an AI agent can write fluently, and a Python tool that reads the same notation and turns it into PNGs, sprite sheets, and game-engine-ready assets.

frames:
  idle_0: |
    .....000000.....
    ....05566650....
    ...0556776650...

Status: early development, but the full pipeline works: palettes, 2D sprites and tilesets, 3D voxel models rendered from 8 headings or exported as real meshes (glTF) for 3D games, previews, lint, import, and builds into Godot 4. See CHANGELOG.md and the issues.

Docs: install, a tutorial, and references generated from the code: every notation field, pagan.toml settings and lint rules. The full notation with examples is the skill's docs topics (pagan docs).

Install

pip install pagan-gen      # the package is pagan-gen on PyPI; the command and the import are `pagan`
pagan --version

Install (development)

Requires Python 3.11+.

python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
pagan --version
pytest

Quick start

pagan init my-art            # creates pagan.toml, STYLE.md, palettes/, sprites/, tiles/
cd my-art
pagan new palette dusk       # scaffolds palettes/dusk.pal.yaml; then set default_palette = "dusk" in pagan.toml
pagan palette show           # renders swatches to previews/palettes/*.png

pagan new sprite potion --size 16x16 --description "red health potion"   # 2D: edit the grid
pagan new model ship --size 96x96 --directions 8                          # 3D: shapes + materials
pagan lint                   # format errors + style warnings
pagan preview potion         # upscaled sheet, frames and GIFs in previews/potion/
pagan gallery                # every asset side by side
pagan build                  # sheets + manifest (+ Godot SpriteFrames) into output_dir

Every command accepts --json for machine-readable output and exits non-zero on errors. See examples/demo/ for an example project (palettes, a potion, a slime, meadow tiles and an 8-heading 3D ship) and examples/godot/ for the Godot project it builds into: open it in Godot 4.7 and press Play.

Using the output in a game

pagan build writes PNG sheets and manifest.json (frame rects, animations, pivots, tile coordinates) for any engine. With export = ["png", "godot"] it also writes Godot 4 resources:

  • Sprites and 3D models: <name>.tres SpriteFrames. Godot resources can't hold the pivot, so apply it on the node, using the asset's godot_offset from the manifest:

    $AnimatedSprite2D.sprite_frames = load("res://assets/generated/sprites/ship.tres")
    $AnimatedSprite2D.centered = true
    $AnimatedSprite2D.offset = Vector2(0.0, -12.0)   # manifest: assets.ship.godot_offset
    $AnimatedSprite2D.play("sail_ne")                 # 3D models: one animation per heading
    
  • Tilesets: tiles/<name>.tres is a TileSet with every tile in atlas source 0; the manifest's tiles gives each tile name's atlas coordinates. Terrains, collision and other tile data are set up in Godot.

Isometric tile games: the dimetric camera

For a 2:1 isometric TileMap (e.g. Godot's TileMapLayer, 64x32 cells), set the exact pixel dimetric camera:

[camera]
projection = "dimetric"   # default "orthographic" (any elevation, `scale` px per voxel)
tile = [64, 32]           # pixels per grid cell: the floor diamond
cell = 16                 # voxels per grid cell side
z_step = 0                # pixels per voxel of height; 0 = tile height / cell (2 here)

A cell x cell floor then renders to the hand-drawn 64x32 diamond (rows 2, 6, ... 62, 62, ... 6, 2) and tiles at the grid pitch with no gaps or overlap; walls and furniture share that scale, and a 1-voxel move is always whole pixels (2 across and 1 down along x/y, z_step up). Models use heading: 45 with directions: 4 (frames ne, nw, sw, se); other headings can't land on whole pixels and are an error. Meshes are unaffected.

3D games: meshes

For a free 3D camera, add "mesh" to export: every 3D model also builds models/<name>.glb (binary glTF: one node per part, animations, part metadata) plus a palette ramp texture, and with "godot" a models/<name>.tscn with PAGAN's palette-locked ramp shader applied. Pick the project's texel density with pagan config set mesh.voxel_size 0.0625 (metres per voxel). Models face +Z, +Y is up, the model's origin is the mesh origin; rig: in a model sets part pivots, parents and metadata (hit zones, detachable parts).

var soldier: Node3D = load("res://assets/generated/models/soldier.tscn").instantiate()  # manifest: mesh.godot_scene
add_child(soldier)
soldier.look_at(target, Vector3.UP, true)                  # true: the model's front (+Z) faces the target
soldier.get_node("AnimationPlayer").play("walk")           # looping animations loop
var helmet: Node3D = soldier.get_node("body/torso/head/helmet")   # manifest: mesh.parts.helmet.node
if helmet.get_meta("extras").get("detachable", false):    # rig meta -> node metadata "extras"
    helmet.reparent(get_tree().current_scene)              # knock it off: keeps its place in the world

Light the scene with a DirectionalLight3D (shadows on) and use the Linear tonemapper: the ramp shader then keeps every lit pixel a palette colour (Forward+ and Compatibility renderers; Mobile can be a few levels off in dark colours). Big repeating surfaces (ground, walls) are tileset textures: export_textures writes repeatable PNGs and triplanar Godot materials. Review models with pagan preview <model> --orbit (all headings, from below too), --closeup <part> and --engine. examples/godot/scenes/mesh_test.tscn shows the demo meshes on turntables under a moving sun.

Using PAGAN with Claude

PAGAN ships a Claude skill that teaches an agent the whole workflow: setting up a game's art folder, asking the right questions, drawing/modelling, looking at previews, and changing the look over time.

pagan skill install          # copies it to <repo>/.claude/skills/pagan/

Then just ask: "I'm making a naval exploration game; make the player's ship, three masts, 8 headings."

Using PAGAN from any agent (MCP)

pagan mcp runs PAGAN as an MCP server, so any MCP client (Claude Desktop, Claude Code, Cursor, your own agent) can make, lint, preview and build art for one project. Tools return the same JSON as the CLI's --json, and previews come back as images the model can look at.

claude mcp add pagan -- uvx pagan-gen mcp --project /path/to/art     # no install needed (uv); or `pagan mcp` after pip install

Other clients take the same command in their config:

{ "mcpServers": { "pagan": { "command": "uvx", "args": ["pagan-gen", "mcp", "--project", "/path/to/art"] } } }

PAGAN is listed in the MCP Registry as io.github.lukasgolino/pagan.

Add --allow-godot to let the build tool verify output in a headless Godot. Then ask: "make a 16x16 health potion", "give the zombie an attack animation", "make the whole game a bit darker".

License

Apache 2.0 — see LICENSE.

Metadata

Release files for pagan-gen 0.22.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pagan-gen 0.22.1
File Size Uploaded Provenance Actions
pagan_gen-0.22.1.tar.gz 346.5 kB With provenance Details for pagan_gen-0.22.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for pagan-gen 0.22.1
File Interpreter ABI Platform Actions
pagan_gen-0.22.1-py3-none-any.whl Python 3 none any Details for pagan_gen-0.22.1-py3-none-any.whl

Total release size: 625.3 kB

Release files / pagan_gen-0.22.1.tar.gz

Download URL pagan_gen-0.22.1.tar.gz
Size 346.5 kB
Tags Source
SHA-256 checksum
How to use checksums
4b4fe4590a9925742f8890decfef135062d36e23144a00ad2f153a34a3960055
BLAKE2b-256 checksum
How to use checksums
00e8af388fb423123d95016883b4fdf13e58fd8fb6c0e00f5578ca1e8a787395
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 9, 2026.

Transparency log

Release files / pagan_gen-0.22.1-py3-none-any.whl

Download URL pagan_gen-0.22.1-py3-none-any.whl
Size 278.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3d0dfe41130606297d75d64230d601f692e590f1f8ff22bd485bf531a2b863bf
BLAKE2b-256 checksum
How to use checksums
6d04d040570f7459bf6c1183eca8bf801c7899a92a4189cbd45570d5ab053ca5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 9, 2026.

Transparency log

Security for pagan-gen 0.22.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for pagan_gen-0.22.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 9, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.22.1 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page