Drag the world

The plugin your agent installs

Isometric games made easy

Lattice is an agentic isometric game kit: 12 skills that teach your coding agent to build a game, over 9 TypeScript core packages. No sprite sheets, no audio files, no asset paths — the art is derived and the sound is synthesized.

>/plugin marketplace add C-Aniruddh/lattice
>/plugin install lattice@lattice

Two slash commands inside a Claude Code session. Then /lattice a game where…

$codex plugin marketplace add C-Aniruddh/lattice
$codex plugin add lattice@lattice

Then start a new session; /plugins in the TUI shows what is loaded.

$grok plugin install C-Aniruddh/lattice

Grok Build reads the same plugin manifest with no configuration. Confirm the trust prompt, then run /plugins

All six measured at cbd48bd, 2026-08-18, Apple Silicon, Node v24.18. Hover or tap any of them for the command that produced it.

From one sentence

This went in. This came out.

>/lattice a game where you place stalls and open gates to pull the crowd to your bakery before the market closes

Grok's agent, in an empty directory, with the packages from npm and no access to this repository. Nobody here designed it, named a file or fixed a bug — the source is unedited, and these are not gallery exhibits: nothing in them was held to a line rule and nothing was tidied.

Two more, the same way

>/lattice a game where you hang chimes along a mountain path and tune each one, so the wind plays them in order as walkers pass

Chime Path

Claude · 1,341 lines over 6 modules

five HUD nodes ship under the contrast floor, and the agent that drove a browser still missed them

>/lattice a game where you plant an orchard and each evening choose to harvest or let it grow, and it keeps growing while the tab is closed

Evenfall Orchard

Codex · 73 lines in one module

one phase of its day is 84% one near-black color, which its author never saw

All three, their transcripts, what was verified by hand and the defects left in: from-one-sentence/. The 9 packages they installed are the ones on npm, at the version their lockfiles pin.

The fan-out

Eight exhibits, three vendors, one written spec.

Eight of the worlds above were built by agents from three different companies, each given one row of the gallery brief, the standard it is held to, and the tools — and none of them allowed to read another exhibit's source, because an agent that can copy its neighbour tests the neighbour rather than the writing. Seven of the eight passed every row of the looking harness unaided.

The exception was Replay, on legibility: a bare · separator is its own text node, and one narrow glyph in a five-pixel box reports a luminance range of 0.003 at a contrast of 7.2. It was not hard to read. It was too small to measure.

Each of the eight changed on the way in and its README says how. What all eight of them found missing in the brief is collected in what eight strangers found in this document.

Why

Why the agent gets it right.

Ask a general coding agent for a game and it invents a sprite sheet, an asset path and a physics constant, and hands you something that compiles and is broken. None of those three exists here.

  • No asset files, so no asset paths. A solid is one color with its faces derived; a sound is synthesized from a declaration. Nothing to draw, nothing to load, nothing to license — and nothing to name wrongly. A recolor is a runtime value.
  • Deterministic by rule, not by discipline. Math.random(), Date.now() and performance.now() are lint errors inside a package. Same seed, same world, on every machine — so a bug is reproducible from a link, and a fix can be shown to have worked.
  • Nothing owns your main. No engine, no editor, no loader, no scene format and no build step past a bundler. There is no framework shape to get wrong because there is no framework.

The traps, written down

An agent can read a .d.ts. What it cannot read is the set of failures that are individually surprising and jointly the difference between a working game and a plausible-looking broken one. Three of them, and the rest at /llms.txt:

  • An animated color is an allocator. a color that moves continuously misses the ramp cache every frame and takes every other caller’s entry down with it. Snap it to eight levels; keep position and timing continuous.
  • Tile lookup floors, never rounds. and once ground has elevation the projection stops being invertible, so a tap has to be resolved against the terrain. The naive version misses by 1,400 px at the top of a hill.
  • readonly is not a barrier. TypeScript ignores property readonly when checking assignability, so a frozen vector flows into a parameter that writes to it. The failure is a TypeError on the one frame that path runs.

The whole kit, without the prose

atwhat it holds
/llms.txtthe kit as plain text: the rules, all nine packages with entry points and invariants, every exhibit with its source path, the traps, and a program that compiles.
/api.jsonthe same as JSON, plus every measured figure with the command behind it, the cross-package contracts, and what is and is not stable.
/kit.jsonthe repository's own .lattice/kit.json, verbatim — the file the build fails over if a package exports a symbol it does not list.

Those three are live right now, and an agent pointed at them needs nothing else from this page. The plugin above is what saves you from having to point it.

The nine underneath

core depends on nothing and every other package depends only on the ones below it. All nine are 83.02 kB gzipped and a game imports four or five.

packagelayerwhat it is forgzip
@latticekit/core0Deterministic primitives. Seeded randomness, noise, math, easing, typed events, pools, formatting.7.40 kB
@latticekit/audio1Sound without assets: WebAudio synthesis from declarative sound definitions, with voice limiting, buses and a music sequencer.7.76 kB
@latticekit/iso1Isometric space: the projection, the camera, depth sorting, tile maps, footprints, hit-testing, and grid pathfinding.11.47 kB
@latticekit/loop1Time. A wall-clock game loop with fixed-step simulation and interpolated rendering, plus scheduling, tweens and frame statistics.6.57 kB
@latticekit/persist1Saves that survive: versioned state, an explicit migration chain, pluggable storage, debounced writes and integrity checks.5.79 kB
@latticekit/sim1Idle-economy mathematics in closed form: cost curves, the flow integrator, offline accrual, and capacity gating.7.58 kB
@latticekit/draw2The rendering layer: a Surface interface with a Canvas2D backend, color derivation, and the isometric solid kit that makes procedural art read as designed.12.33 kB
@latticekit/input2Normalized input: pointer, touch and keyboard into one per-tick sample stream, plus gestures, an action map, a camera controller, and the recorded log a replay is driven from.15.39 kB
@latticekit/ui3DOM overlay primitives — a declarative element builder, panels, toasts, number rolls, and thumbnails rendered from the draw kit. Deliberately not a framework.8.72 kB

What

One command, 12 skills, 9 libraries under them.

The libraries are the tech. The product is the plugin: the part that knows which of them to reach for, in what order, and what not to do.

what you getwhat it does
/latticethe parent skill, and the whole entry point. Everything after it is the game — no flags, no subcommands, no questions with a right answer it could have worked out. It picks the shape, scaffolds, installs, wires, gets to a running screen, then opens it in a browser and looks at it.
eleven specialistsstarting art world economy input sound saving hud determinism performance traps — organized by what somebody is trying to do, never by package. Nobody sits down to use @latticekit/iso; they sit down to put a building where someone tapped.
9 librariescore audio iso loop persist sim draw input ui — 83.02 kB gzipped for all of them, no dependencies, and a game imports four or five. They are what the skills drive.

Written down in docs/SKILLS.md, which also holds the bar this is held to and the one test that decides whether it shipped: somebody who has never seen this repository installs the plugin, types one sentence about a game, touches nothing else, and ends up looking at that game in a browser. Three of those runs are at the top of this page. What is untested is a stranger doing it, on a machine that is not ours.

Getting started

Getting started.

A whole Lattice program in 10 lines, and the world it draws, running out of that same file.

import { createCamera } from '@latticekit/iso';
import { BASE_SLOTS, beginFrame, createCanvas2dSurface, createPalette, endFrame, isoBox } from '@latticekit/draw';
import { browserFrames, createLoop } from '@latticekit/loop';

const surface = createCanvas2dSurface(document.body.appendChild(document.createElement('canvas')));
const camera = createCamera(innerWidth, innerHeight, { zoom: 0.62 }), palette = createPalette(BASE_SLOTS);

createLoop({ clock: { now: () => performance.now() }, frames: browserFrames(), render: (_alpha, t) => {
  const pen = beginFrame({ surface, camera, palette, t, clear: 'sky' });   // erase, then paint the sky
  // Back to front is just the loop order in a 2:1 projection, so this city needs no depth sort.
  for (let gy = -7; gy < 7; gy++) for (let gx = -7; gx < 7; gx++) isoBox(pen, gx, gy, 1, 1, { color: 'metal', h: 2 + 5 * Math.sin(t + (gx + gy) * 0.4) ** 2 });
  endFrame(pen);
} }).start();

10 code lines by the gallery's own line rule, typechecked against the built packages before this page is generated. It is a real file: site/example/hello.ts, and this is it running on a page of its own. Everything past this — terrain, a depth sort, pathfinding, sound, saves — is what the skills know and you do not have to.

Install it into the agent you already use.

One plugin, 12 skills, three environments. Then a sentence about a game.

>/plugin marketplace add C-Aniruddh/lattice
>/plugin install lattice@lattice

Two slash commands inside a Claude Code session. Then /lattice a game where…

$codex plugin marketplace add C-Aniruddh/lattice
$codex plugin add lattice@lattice

Then start a new session; /plugins in the TUI shows what is loaded.

$grok plugin install C-Aniruddh/lattice

Grok Build reads the same plugin manifest with no configuration. Confirm the trust prompt, then run /plugins