A text language + compiler for LLM-authored low-poly characters: mesh, skeleton, and animations from many lines of readable source, compiled to glTF 2.0 with software-rendered turntables for visual iteration.
Paste this into your favorite LLM:
Clone https://github.com/elliottdehn/wam and make me [what you want to model] that I can see
It will read the spec, author the model, compile it, look at the renders it produced, and iterate until the thing holds together — then hand you a glTF and a turntable sheet. "that I can see" is the part that matters: it puts the model in the loop of looking at its own output.
The founding rule: the author only makes discrete, named, relative,
symmetric decisions — bone angles as words+degrees, body masses as
cross-section rings, membranes as fans of ribs, symmetry via mirror
blocks, props in local-frame groups. The compiler generates every vertex,
skin weight, normal, and winding, and a semantic linter rejects the classes
of silent geometry bugs that renders hide (folds, wrong-bone bindings,
floating feet, inside-out faces, parts buried inside other parts) — plus
whatever proportions you write down yourself in a checks section.
Models aren't limited to characters: scripts/compose_town.py composes a set
of prop models into a single scene with a packed mega-atlas, and wam.zone
compiles whole environments from landforms and placement rules.
A textures section gives materials a hand-painted look from named
procedural operators (gradients, noise, grain, bricks, planks, AO...),
baked into an auto-unwrapped texel atlas that ships inside the glTF.
python3 -m wam.cli mymodel.wam # compile + render 4-view sheet
python3 -m wam.cli mymodel.wam --anim walk --frames 6
python3 -m wam.cli mymodel.wam --bones # skeleton overlay
python3 -m wam.cli mymodel.wam --width 760 --height 560 # landscape panelsOutputs land in out/: a skinned, animated .gltf (drops into
Blender/three.js/engines), PNG render sheets, the texture atlas, and a
*_viewer.json — open viewer/template.html in a browser and drop the
JSON onto it for an interactive orbit/animation view. Requires Python 3 + numpy.
The repository ships no example models — SPEC.md is the reference, and every construct in it has a worked snippet. A taste of the language:
skeleton
root pelvis at 0.52
bone spine1 parent=pelvis dir=up pitch=13 len=0.13
mirror
bone thigh parent=pelvis side=0.07 dir=down pitch=-8 len=0.22
end
parts
loft torso bones=pelvis..spine2 material=skin
ring 0.00 w=0.25 d=0.185 material=cloth
ring 0.80 w=0.315 d=0.225
cap start=dome end=dome
group axe bone=hand.r at=1.0 dir=up pitch=45 yaw=-15
loft haft at=(0,-0.03,0) dir=up len=0.47 material=leather
...
end
animations
anim walk loop dur=1.15
ch thigh.l pitch 0%=-22 50%=19 100%=-22
mirrorphase 50%
This repo is a Claude Code plugin: it ships a wam skill that teaches
Claude the language, the compile-render-iterate workflow, and the hard-won
authoring rules (gait timing, prop groups, cloth skinning, fold avoidance).
/plugin marketplace add elliottdehn/wam
/plugin install wam@wam
Then ask Claude for a model ("make a WoW-style troll") and it will author, compile, and visually iterate using the bundled toolchain.
wam/— compiler: parser → skeleton solver → mesh generation → texture baker → lint → glTF export, plus a dependency-free software rasterizer.wam/checks.py— thecheckssection: proportion, clearance, clipping, rig-quality and animation assertions re-run on every compile.wam/modelset.py—.wamsetfiles: cross-model checks in meters, so a whole cast stays to one scale.SPEC.md— the language specification.scripts/crop.py— cuts matching regions out of a reference image and a render and pairs them at the same scale, for comparisons that are not just silhouette-deep.viewer/— template for a self-contained WebGL viewer page (wam/viewer_export.pyproduces the data blob to inject).skills/wam/— the Claude Code skill.
MIT — see LICENSE.
python3 dice.py # a brine-crusted heron with a crown of horns too heavy for its neck
python3 dice.py -n 5 # five, and pick oneA finished model can be given a link at
wamshare — private and unlisted, or
public under CC0 1.0. Agents: read PUBLISHING_MUST_READ.md. You must offer
both, with their licences named, and you must never publish unasked.