About
Systems developer
I write systems software — emulators, engines, simulation — and I use AI coding agents to do it. Not as a novelty, and not as a shortcut. As a genuine engineering practice that needs the same rigour as anything else, and mostly is not getting it.
What I do
Low-level code. Not web apps or glue between APIs — the layer underneath, where you own the memory, the timing and the correctness.
- Fluid simulation
- Has to stay stable across thousands of ticks.
- Light propagation
- Runs every frame, without dropping one.
- CPU emulation
- One cycle out and the game boots to a black screen, telling you nothing.
Why this kind of work
It is unforgiving in a useful way. There is no arguing with a failing test ROM — either the timing is right or it is not, and the distance between "looks fine" and "is correct" is measurable rather than a matter of opinion.
That is rarer in software than it should be.
Why native code, specifically
One number explains the whole project.
That is the GSO benchmark. The gap is not a mystery once you have worked in it — there are three specific reasons.
- Hostile output
- A template instantiation error runs to hundreds of lines, almost all noise. Compilers were built to talk to humans who can skim. An agent reads every token and burns its context on it.
- Broken loop
- Change a file in web work and see the result instantly. Here it compiles for minutes — then still cannot press play and notice the water is flowing upwards.
- No prior art
- Vastly more public code is Python and JavaScript than cycle-accurate C++. The model has read far less of what you are asking it to write.
And yet nearly everything written about agentic development covers React components and Python scripts. The place these tools measurably struggle most is the place almost nobody is documenting.
How I work
Spec first
Every feature starts as a written spec — what it does, what it does not do, how we would know it failed. Then a plan, broken into tasks small enough that a reviewer could reject one without rejecting the rest.
The agent implements against that document, not against a vague prompt. Specs and plans get committed next to the code, so six months later the reasoning is still there and not lost in a chat log.
Tests are the contract
Write the failing test. Run it. Watch it fail for the reason you expect. Then implement, watch it pass, and commit.
That middle step is the one people skip and the one that matters most. Agents produce code that looks right and does not work, and reading it will not reliably tell you which is which. A test you have watched fail for the correct reason is the only evidence worth anything.
Review everything
Every task gets read by something other than whatever wrote it, and the review has to point at file and line. Reports are treated as claims to verify, not as facts.
Reviews find real defects, and they also raise false alarms with total confidence. Both happen often enough that checking the finding against the actual artefact is not optional.
In public, failures included
Every claim ships with its artefact: the spec, the diff, the commit, the test output. If a number goes down, it gets published going down.
The failures are the useful part. Anyone can write a post about how the agent one-shot a feature. Far fewer will show you the three hours it spent confidently fixing the wrong file.
What I'm building
FourShades
A yardstick, not a product. The Game Boy is a solved problem — hundreds of emulators exist and several are far better than mine will be. That is exactly why it works.
- Known answers
- 1,300 public test ROMs already say what correct looks like.
- Respected difficulty
- Cycle-accurate timing is hard, and C++ developers know it.
- A real number
- The pass count is not an opinion. It goes up or it does not.
Litharia
Written from scratch, with no framework handling the hard parts. The structural decision I am most pleased with is a dull one.
- Simulation
- Cellular fluid with surface tracking, propagating light on a day/night cycle, physics and collision.
- World
- Sparse chunked tile storage, procedural terrain, machines, inventory, enemy AI.
- Headless core
- The simulation links no graphics code at all, so the whole world steps inside a test in about a second.
Almost every hard bug I have fixed there was found by a test that only exists because of that split.
How I got here
Scratch
Rebuilt games like Cookie Clicker and Idle Eleven, piece by piece, to work out how they were put together. Reverse-engineering something that already works turns out to be one of the fastest ways to learn.
Lua and Roblox
Founded a studio and shipped multiplayer games to real players. Different discipline entirely: a game with players has bug reports, edge cases, and people doing things you never anticipated.
C++ and systems work
Started Litharia, a 2D engine written from scratch. No framework handling the hard parts — my own fluid simulation, my own lighting, my own spatial data structures, and my own bugs.
Agentic development, in public
Began FourShades, building a Game Boy emulator with AI coding agents and publishing every result against the public test ROMs. Including the ones that go backwards.
Stack
Systems
C++20 · SFML 3 · CMake · MSVC and clang · doctest
Web
TypeScript · Astro · Cloudflare Pages · D1 · Vitest
Tooling
Claude Code · Git · GitHub Actions · Lua
Elsewhere
Everything I build is on GitHub, including the specs and plans behind it. If you are working on native code with agents and hitting the same walls, I would genuinely like to hear about it.