Technology
How a game gets made that almost nobody codes by hand: the shift system, the review teams, the art and audio pipelines – and the graveyard of approaches that didn't work.
Who does what
Jens doesn't write code. On 6 October he put a starter kit into the repository – concept, rules, roles, around 110 work packages – and since then he steers through a single document, the control panel. It holds the mode, the weekly budget, the allowed shifts and his notes. On top of that there are five gates where he tests the game himself on his iPhone, and the approvals for expensive art runs.
Everything else is Claude: planning, coding, testing, reviewing, generating art and sound, hunting bugs, documenting decisions. Of 2,285 commits, 2,240 come from the AI. Jens' 45 are almost all checkboxes and notes.
The shift system
A scheduled cloud routine starts a new Claude Code session every hour. Its first command decides whether any work happens at all: if the control panel says pause, a shift is already running or the weekly limit is reached, the session ends immediately without a commit.
If it may work, it becomes the lead. It reads the state, picks packages, reserves them and sends out build teams – sub-agents with their own working copy and their own branch. Every team pushes after every commit. A package only counts as done once another agent has reviewed it, the tests are green and someone has looked at the screenshot in phone format. Only the lead integrates into main. From minute 170 it starts nothing new.
Memory made of files
No session remembers the one before. Whatever matters lives in the repository: the status with every open item for Jens, the shift log, the package list with 395 entries whose titles and acceptance criteria nobody may change, and the decision log with 198 entries by now. A new shift reads all that and then knows as much as the last one.
Sixteen roles
Architect, engine, combat, world, interface, server, art, audio, balancing – plus the review teams tester, bug hunter, playability, architecture review and security, and two small helpers for searching and reading logs. Since 20 October the core teams run on Opus, art, audio and balancing on Sonnet, the helpers on Haiku.
Budget as a rule
Every budget has a ledger and a hard stop inside the tooling: the Claude quota through the number of shifts allowed per week, image generation through a cap plus approval per request, ElevenLabs through a monthly limit with a brake per run. A shift measurably uses about 2 to 3 percent of the weekly quota.
How things get checked
Tests first, then code, and tests are never weakened to turn green. About half of all code lines in the project are tests. Build teams only check what they touched; only the lead runs the full integration suite. Click tests run in phone landscape format for iPhone 16 and Pixel 7.
Small reviews and all security checks run through a separate path using the API credit. The very first trial run found a serious save-game bug that the regular review had missed. After every phase that ends in a gate there's a review wave with five review teams.
Honest numbers
Of 3,356 recorded test runs, about a quarter were red. On average a shift hits 33 tool errors. It's here because it belongs here: autonomous development isn't a straight line but lots of small correction loops.
When the machine gets in its own way
On 17 October up to four build teams ran at once on a container with four cores. Load sat between 15 and 30, tests went red purely from timeouts, and one shift needed 254 minutes for a single integrated package. The performance test, running in a container without a GPU, mostly measured the machine: the same code came in at 8 one time and 119 milliseconds per frame the next.
Jens had the AI analyse 15 shifts and research externally. That became rebuild H1 to H10: performance is now measured on four levels instead of with a stopwatch, heavy runs need a free compute slot, click tests run one at a time, two teams is the default. A different software renderer in the container cut the test scene's frame time from 150 to 17 milliseconds.
Art without an artist
All images come from OpenAI image models. Every request starts with the same verbatim style prefix: hand-painted, warm greens and golds, thick dark outline, a view from roughly 55 degrees above, light from the upper left. Game names and brands are banned from prompts; the tool rejects them.
Drafts are cheap and run without asking. Final images cost more and need a request with a contact sheet that Jens approves with a checkbox. After that Claude Sonnet checks every single cell against a reference and sorts it into ok, fix, discard. So far: 718 image requests, 279 of them final.


The walking problem
Characters and movement are everything to Jens. This is exactly where the project failed most often. Five painted walk tests in a row had the same flaw: the image model copies the leg position of the reference and never swaps the front leg. It doesn't know it's painting frame seven of a cycle.
Then came a leg rig in code (clean, but prancing), legs via mask correction (the figure jumps), a dedicated walk-cycle research package and a run sheet. On 12 October path D won: upper body painted, legs in code with motion curves borrowed from animation craft, the cape as its own swinging mesh.
The jitter wasn't in the images
With every walking approach the figure jittered. The cause was the interpolation: if the simulation in the background hadn't answered yet, the figure stood still for one frame and then jumped twice as far. On a desktop at exactly 16.667 milliseconds per frame that was invisible; on the iPhone it wasn't.
Two U-turns in one evening
After gate 2 it was clear: enemies with painted frame sequences feel more alive than heroes with code legs. So on 21 October at 18:50 every approach was to be tested, including 3D with Meshy and Blender and video via fal.ai. A Blender test was already running. At 20:40 Jens took it back: 3D would only work for human-like figures, and then heroes would look different from every other creature. At 21:11 the improved paper doll was cut too. From 24 October heroes get painted frame by frame.



Voices, sounds, music
The first voice test with OpenAI voices was unusable except for a single recording. The switch to ElevenLabs was decided the same morning. Since then a dedicated pipeline generates speech with stage directions, sound effects and music from a composition plan.
For choosing there's a casting page behind the game's login: three to five candidates per character to tap through. A first attempt as a Claude artifact loaded unreliably on the phone and was replaced. By the evening of 18 October, 13 voices, 129 sounds and 8 music tracks had been picked.

One simulation, three places
Game logic runs at a fixed 20 ticks per second, drawing happens at 60 frames with interpolation in between. The same simulation runs in a web worker on the phone, in a Durable Object on the server and in Node for tests, bots and balancing. An architecture test forbids it any import from rendering, the DOM or Cloudflare.
An early measurement: sine and arctangent don't compute bit-identically in V8 and JavaScriptCore. Instead of custom maths the rule is: deterministic per engine, reconciled only through rounded server state. In co-op the server is authoritative; the phone only predicts your own movement.
The foundation
TypeScript, Vite and PixiJS v8 in the browser, HUD and menus as plain DOM. A Cloudflare Worker serves the game and talks to one Durable Object per world; accounts and heroes live in D1, login goes through Cloudflare Access. Every push to main is built and shipped automatically – the AI itself may never deploy directly.
The stack comes from Star Slayer, the previous project. Claude's first plan used Phaser. When Jens asked for the Star Slayer setup, Claude itself proposed the switch, to reuse the proven iPhone building blocks: joystick, audio, art pipeline, fixes for the installed app.
Graveyard
Approaches that were built, tested and buried again. Each one left something behind.
- The grid nobody kept to 10 Oct 2026
Animation sheets as 4×4 grids with the cheapest image model.
Why it failed: Figures bigger than their cell, neighbours poking in; for the hero 73 of 80 cells were cut off.
What remained: Smaller grids, reference images and cropping per figure instead of rigid cells.
- The lost shift 11 Oct 2026
Build teams only committed locally in their working copy.
Why it failed: The container was discarded after the shift. Four finished packages, half of a fifth and an art request were gone.
What remained: Push after every commit – a mandatory line in every assignment ever since.
- Final images that never arrived 11 Oct 2026
Requesting high-quality images synchronously through the cloud environment.
Why it failed: All ten requests failed after about 30 seconds with HTTP 502 – and were probably billed anyway.
What remained: Streaming with partial images, stop after two errors, reconciling the ledger with the dashboard.
- Five walk tests, one flaw 11 Oct 2026
Having the hero's walk cycle painted in full, with ever better pose references.
Why it failed: In all five tests the image model copied the leg position of the reference. The front leg never switched.
What remained: Image models don't know they're painting frame seven of a cycle. Movement has to come from elsewhere.
- Legs via mask 12 Oct 2026
Repainting only the legs in every walk frame.
Why it failed: The figure visibly jumps from frame to frame.
What remained: Painting over afterwards doesn't hold a consistent line over time.
- The prancing leg rig 12 Oct 2026
Legs as moving parts in code, the rest painted.
Why it failed: Technically clean, but it looked like the hero was prancing.
What remained: Without proper motion curves code animation looks mechanical – which led to path D.
- Jitter on every walk path 12 Oct 2026
Rendering waited for the simulation in the background to answer.
Why it failed: If the answer came one frame late, the figure froze and then jumped twice as far. Invisible on a desktop, obvious on the iPhone.
What remained: Rendering now keeps going at the last known speed. And: only real devices tell the truth.
- Locked out by its own filter 17 Oct 2026
Adjusting test values to new budget limits Jens had set.
Why it failed: The safety filter read it as removing security tests and then blocked every command. Two shifts aborted,
mainstayed red.What remained: Budget tests now read their limits from the control panel. When the filter refuses, the shift doesn't abort but asks Jens.
- Four teams, four cores 17 Oct 2026
As many parallel build teams as possible.
Why it failed: Load up to 30, tests red purely from timeouts. One shift: 254 minutes, one package.
What remained: Three teams at most, two by default; locks for compute and click-test slots.
- The empty side shift 17 Oct 2026
A second shift running parallel to the main one.
Why it failed: It often found no free package but still counted against the weekly limit. Both shifts fought over the same package list.
What remained: A separate backlog for slot B, its own reservation file – and only one shift for now.
- The stopwatch in the container 18 Oct 2026
Frame time inside the container as a hard acceptance limit.
Why it failed: Without a GPU the test measured machine load: same code, 8 to 119 milliseconds, 14 of 57 runs green.
What remained: Four measurement levels instead of a stopwatch, real devices for the real frame rate.
- Off-the-shelf voices 18 Oct 2026
Voice samples for three classes and a narrator with OpenAI voices.
Why it failed: Unusable except for a single recording.
What remained: Switch to ElevenLabs for voice, sound and music – the same morning.
- Two tills, one account 18 Oct 2026
Several audio teams in parallel, each with its own ledger.
Why it failed: Each team only saw its own spending; music was booked at more than twice what it really cost.
What remained: Paid runs only one after another, ledgers are merged on integration.
- The giant cloud 20 Oct 2026
Area spells as big painted effect clouds.
Why it failed: At gate 2 too dominant and without elegance. Projectiles weren't visible at all – hits landed without anything flying.
What remained: Layered effects: core, trail, ring wave, sparks, ground mark. Every shot visibly flies, meteors fall as individual rocks.
- The helpers nobody called 20 Oct 2026
Small, cheap agents for searching and reading logs.
Why it failed: Practically never called – they accounted for 0.1 percent of tokens.
What remained: A mandatory line in every assignment. Recommendations alone aren't enough for AI agents.
- 3D and video 21 Oct 2026
Animation via 3D models (Meshy and Blender) or via video models.
Why it failed: Withdrawn after two hours: 3D would only work for human-like figures and split the painted look. Along the way it turned out OpenAI had shut down its video API at the end of September.
What remained: A consistent painted style outweighs technical elegance.