Building Shark Thief: Part 1
What a building a game taught me about AI
Published on September 20th, 2026
The idea
Shark Thief started as a prompt from my son. We were in the family room on a lazy Sunday, and I asked him to write up a game idea so I could run it through Claude. He was specific. He wanted a 30×30 grid, with yellow squares on 5% of it and a 1-in-1000 chance of a new one appearing on each square every move. He also wanted a bad guy that moves one step for every two of yours, and a new bad guy every time you grab a yellow square. That last rule is still the heart of the game.
Claude turned that into a playable browser game in one shot. It had a leaderboard, and for a couple of weeks he and his friends were obsessed with beating each other’s high scores. That was enough for our family to start talking about making it a real game.
Getting from there to a ten-depth game headed for the App Store took much longer, and every step taught me something about working with AI.
Plan first
The prototype was one endless board. To turn it into a game, I broke it into levels I call depths. You earn 100 points, you descend, and each depth adds one new idea. Some depths came together in an afternoon. Others took weeks of tweaking to get right. What saved me the most time and tokens was starting every depth in plan mode.
Early on, I didn’t have a consistent way of prompting. Sometimes I’d give Claude a rough idea for a depth without many specifics, and it would go straight to building. It often missed the point and built something far from what I had in mind. At my worst, I’d go back and forth for ages while it made small edits each round.
So I started using plan mode for every new depth. I’d describe the depth in detail, and Claude would ask questions and propose a plan. It clarified the vague parts of my idea, caught edge cases before they became bugs, and suggested improvements. By the time any code was written, we had a full spec. The back-and-forth still happened, but as a conversation up front instead of a loop of rebuilds.
Me
New depth: the Arctic. Ice patches on the board. Step on ice and you slide until you hit a wall or a non-ice tile. Frozen fish are the pickup, and collecting one turns its tile to ice.
Claude
A few questions before I plan this:
- Do enemies slide on ice too, or only the shark?
- If a slide carries the shark over a coin, does it collect it?
- Can a frozen fish spawn on a tile that’s already ice?
Me
Enemies slide too. Yes, collect on the way. No spawning on ice.
Claude
Plan:
-
level-config.tsadd an Arctic block: ice patches, frozen fish counts -
slide.tsone slide routine shared by the shark and enemies spawn.tskeep frozen fish off ice-
renderers.tsdraw ice under pickups and enemies
Approve plan?
This is how good engineering teams already work. Before anyone writes code, the ticket gets talked through, questions get asked, and edge cases come up early. Plan mode does the same thing with Claude. My team now uses it by default. Each engineer starts a ticket in plan mode, reviews the plan with Claude, and only then lets it start building.
Keep it in one place
I wanted every depth defined in one place, not with numbers scattered all over the code. Each depth has dozens of small numbers that decide how it plays. How many pickups start on the board. How often new ones spawn. How fast each fish moves. How big a toxic cloud gets when it expands. How close to the center a pickup is allowed to appear. If those values are spread across a dozen files, no one can see the full picture of a depth, not me and not Claude.
This isn’t a new idea. It’s how good software teams already work. Engineers call it a single source of truth. Product teams keep settings like pricing and feature flags in config instead of burying them in code, so they can change behavior without touching logic. Design systems work the same way: a team defines its brand colors and spacing once, and every screen pulls from that list instead of someone typing the same color code by hand in forty places.
It matters even more with AI. When you ask Claude to make a depth harder and the numbers are scattered, it has to guess where they live. Sometimes it changes one and misses another. Sometimes it adds a brand-new hardcoded value somewhere else, and now the same setting lives in two places. Every change leaves the code a little messier than before.
So all the tuning lives in a single file, level-config.ts.
Each depth has its own section, and every setting has a comment explaining
what it does. The rest of the game just reads from it. That keeps the code
cleaner and keeps Claude focused. When I want the Busy Pacific depth to
feel more crowded, I don’t need a long prompt. The fish counts and speeds
are right there. I can change them myself in a minute or ask Claude to,
and nothing else moves. The same habits that make a codebase easy for a
new engineer to work in make it easy for AI to work in too.
Write it down
Every AI session starts from zero. Claude doesn’t remember yesterday’s conversation, the decision we made last week, or why the baby shark follows one cell behind you. Unless you write those things down, you end up re-explaining your game every time you sit down to work.
So I wrote them down. The game has a design doc that covers the vision,
the core loop, the design principles, the player experience I’m going for,
and every depth’s rules. Alongside it is CLAUDE.md, a project
file Claude reads automatically at the start of every session. It explains
how the code is organized, which file to touch for what, and the game’s
vocabulary. An ammonite is the purple shell in the Shallows. A garibaldi
is the fast orange fish in the Busy Pacific. When I say “coral shell,”
Claude knows exactly what I mean.
### Terminology
- Ammonite
- purple round shell pickup (Depth 1). Spawns a big enemy.
- Baby shark
- follows 1 cell behind player. Enemy contact = −5 pts + blood cell.
- Ice patch
- slippery tile; shark and enemies slide until hitting a wall or non-ice tile.
- Garibaldi
- vivid orange, size 1×1, moves every player turn (fastest). Always reliably blocks movement.
This is the same reason good teams write things down. A new engineer shouldn’t have to interrupt five people to learn how the system works, and decisions shouldn’t live only in someone’s head. Design docs, onboarding guides, and decision logs exist so a team’s knowledge outlasts any one conversation. Claude is like a new teammate who shows up every morning with no memory, so the docs matter even more.
My team does the same thing at work. Every repo has a CLAUDE.md, checked in alongside the code. It covers how the project is set up, the
conventions we follow, and the mistakes we don’t want repeated. Because it
lives in the repo, everyone’s Claude starts with the same context, not
just whoever wrote the prompt. When someone figures out a better way to do
something, they add it to the file, and the whole team gets it on their
next session. It also helps new engineers, since the doc that tells Claude
how the project works tells them too.
The payoff is consistency. Ten depths in, the rules still hang together, and I spend my prompts on the new idea instead of rebuilding context.
What’s next
Plan mode, one source of truth, and good docs got me through the first few depths. As the game grew, one Claude session doing everything stopped being enough. In the next post, I’ll cover how I split the work across a small team of AI agents (one designs, one reviews, one builds), how I turned repeat mistakes into checklists, and how I set up AI playtesters so new depths don’t break old ones.