Subscribe Watch on YouTube
All articles

How I Run AI Coding Agents Like a One-Person Studio

People ask me which AI tool built my game, and the honest answer is that none of them did.

I built Tropic Tumble, my match-3 game now live on Android and iOS under JPott Studios, with a handful of AI agents doing the implementation. They typed a lot of it. I owned whether any of it was true.

That distinction is the whole story, because agents are fast and they share one dangerous habit: they report work as finished when it is not. The worst part was never that they made mistakes. It was that the mistakes so often arrived wrapped in confidence. A screen that looked right. A test suite that was green. A “done” that meant the files existed, not that a player could use the thing.

So the part that actually made this game shippable was never a tool. It was the system I built around the tools to stop fast work from becoming fake done.

A rules file is where yesterday’s correction survives into tomorrow’s session.

That sentence is the whole trick, and the system is five parts, each one a place I chose to write something down so I would never have to say it twice:

  • Roles: who does which kind of work.
  • Rules: the manual every agent reads first.
  • Architecture: where new work is allowed to live.
  • Tests: the bar the work has to clear.
  • Human gates: where I stand, look, and decide.
The current Tropic Tumble home hub on iPhone: avatar, pet, island scene, player balances, event buttons, and a large Play button for level 3000

The home hub today. Agents wrote most of the code behind this screen. None of them could tell me whether it looked right, and the system exists because of gaps exactly like that.

Choose your read:

Why more than one agent

Because they are good at different shapes of work, the same way people are. I did not plan the division on day one; it settled as I watched each tool earn its seat, and then I leaned into it deliberately.

ToolRoleWhat it owns
ChatGPTProduct designerThe thinking: what to build, why, and the written plan. It never codes.
CursorBuilderThe bulk of implementation. I hand it a milestone and a plan and leave it running.
CodexRepo-aware specialistWhole-codebase reasoning, overnight runs, and generating art in bulk against real gaps.
ClaudeReviewerArchitecture critiques and the honest “is this actually done” pass.

The day-to-day of those roles, the eight-step loop every feature ran through, and the short unhappy story of Hermes, the hands-off overnight agent I tried and dropped because it started work on schedule and finished none of it, are all in the build log. This article is about the rails that loop runs on.

Why they all read a manual

Because a model has no memory of the correction you gave it yesterday. Correct an agent in chat and you have fixed one session. Correct it in a rules file and you have fixed every session that follows.

I learned that the expensive way. Early on I left an agent running on a milestone branch, and when it finished, it decided to be helpful and checked out main to clean up. I did not think much of it. Two hours later it had committed three unrelated changes straight to main. That is when the rule was born, and it has ridden along in every session since:

---
description: Do all work on feature branches; never end a session on main or commit/push to main.
alwaysApply: true
---

# Git: stay off `main`

1. Create or use a feature/milestone branch. Do not use `main` as the working branch.
2. After git operations, do not run `git checkout main` to "clean up." Stay on the feature branch.
3. Commit and push only to the current feature branch unless I explicitly ask otherwise.

The front matter is the important part: alwaysApply: true means the rule cannot quietly be forgotten next time.

These files live in three places, and they are not interchangeable:

  • AGENTS.md sits in the repository root. It is an open standard that Codex and most agents read: build and test commands, conventions, and the hard rules.
  • CLAUDE.md is Claude’s own memory file. Claude reads it, not AGENTS.md, so if you want one source of truth, import one into the other.
  • .cursor/rules/*.mdc are Cursor’s scoped rules, like the git rule above, that attach to specific files or apply always.

I walk through building one of these files for a real test suite in how to write a CLAUDE.md and AGENTS.md for test automation. The file names matter less than the fact that every agent opens the same brief, the way a team shares one.

What actually goes in the manual

Almost nothing in mine is aspirational. It is scar tissue: a record of things that went wrong, written down so they have a harder time happening twice. Here is a slice of the real AGENTS.md, lightly trimmed. Even the section heading tells you where the rules come from:

## Recurring Corrections To Preserve
These are repo-level lessons from past Julia corrections.

### Examples Are Never Exhaustive
- Treat every example in this file as a concrete instance of a larger
  principle, not the full list of cases to check.
- When a new bug resembles one of these patterns, generalize the rule to the
  new system. Do not say "the rule only mentioned X" if the same failure
  shape applies to Y.

### Repo Truth Before Reassurance
- Check live code, data, exports, builds, and backend probes before answering
  product-status questions. Do not answer from memory, screenshots, or compile
  success when the user is asking what actually ships.

### Find The Real Owner Before Patching
- Locate the state owner: save hydration, progression store, unlock manager,
  reward ledger, backend route, or UI view model. Do not patch the presenter
  when the data owner is wrong.

The headings in that file read like a log of corrections, because that is what they are. Every one exists because an agent did the opposite once:

  • Repo truth before reassurance. Born the day I asked what had actually shipped and got an answer from memory. Now the rule says to check the live code, the data, the exports, and the builds before answering any product-status question.
  • Definition of done is production or beta truth. Born the day an agent treated a local fix as complete while the beta build on my phone still had the bug. If the work is not in production or the active beta lane, it is progress, not done.
  • Find the real owner before patching. An agent once fixed a broken screen by patching the code that displays the state, while the broken state itself lived in the save system. The screen looked right, and the bug was fully intact underneath it.
  • Exact player path beats isolated components. Bugs get reproduced through the path a player actually takes, map into level, tap, cascade, fail, retry, not through a helper harness that proves one component in a vacuum.
  • Never delete asset files. Agents love to tidy up by removing art they have decided is unused, and one wrong guess deletes a piece of the game. If an asset should retire, stop using it in code and keep the file.
  • Fresh visual evidence is mandatory. After any visual change, the screenshot in the handoff must be captured after that change. A stale capture presented as current is the visual version of answering from memory.
  • No silent red suites. Work is not done while a related regression driver is failing, hanging, or quietly skipped. Fix it or stop and report the blocker.

None of this is exotic. It is what you write down when you onboard a new team member. Agents just need it more explicitly, and they need it every single session.

A useful agent manual is not a wish list. It is a record of what went wrong, written clearly enough that the same mistake has a harder time happening twice.

The architecture gate

Rules about behaviour were not enough, because speed has a structural failure mode too: the lazy fix is always ten more lines on the biggest file in the project. That is how progress_store.gd, the file that owned save and progression, grew past seven thousand lines before I forced a refactor, one convenient shortcut at a time.

So my repo now has a mandatory gate rule, always on, that an agent must clear before finishing any new work. The first step is naming the layer the work belongs to:

LayerWhat lives there
Core playfieldThe grid, matches, powers, obstacles, and how a board resolves. Board scripts and level data only.
ShellThe hub, the map, overlays, and level routing. The shell observes the core; it never owns board rules.
Persistence and metaProgress, missions, journal state, and unlocks, each in its own domain folder with one clear owner.

The gate then names the three god files, progress_store.gd, game_hud.gd, and board_manager.gd, and says they get wiring only: persisted fields and one-line forwards, never new business rules. New behaviour goes to a real owner, and the new owner gets registered in the project’s component map in the same change, so the next agent does not have to guess where anything lives. The rule’s anti-pattern list treats “just ten lines” on a god file as a review failure, because ten lines at a time is exactly how a monolith comes back.

The test I apply is blunt: if the agent cannot name the file that owns the state it is changing, it is not ready to code.

The test bar

After any substantive change, the default bar in my repo is one command:

bash game/tests/run_critical_regressions.sh --quick

That is a curated battery of headless test drivers, chosen because they guard the systems agents touch most, with a quick set that finishes in a minute or two. Behind it sit more than five hundred drivers under game/tests/, and two of the manual’s rules do the heaviest lifting here:

  • A headless parse pass is not visual proof. “It compiles and the suite is green” says nothing about what a player sees. Visual work needs a renderer-enabled capture, saved fresh, after the latest change.
  • Encode risk as a test, not a checklist. The riskiest promises in the game, player state and performance, do not get a paragraph of good intentions in a document. They get a contract backed by quick regressions, so the promise runs on every change and fails loudly instead of relying on anyone’s memory.

And when an agent tells me something is done, I want three things in writing: which drivers ran, what passed, and what it could not prove. That third item is the one that matters most. An agent that says “I could not verify this on a real device” is telling me the truth about the edges of its evidence, and that report is worth more than a confident everything-is-fine.

Plan before build

I never let an agent build from a conversation. The design talk happens with ChatGPT and ends in a written markdown plan saved into the repository, and then a coding agent, in a fresh session, executes that plan and is told not to change it. The point is to catch the expensive mistake while it is still cheap: an agent that plans and builds in one breath commits to an approach early and then spends real effort making a wrong approach work.

The plan itself gets reviewed before anyone builds it, by me first and then by a second AI asked to find the holes:

PLAN BEFORE BUILD1 · Design talk with ChatGPTWork out what to build and why. No code yet.2 · A written plan, saved in the repoSteps and to-dos, not a chat window.3 · I review it firstQA brain: risk, order, what breaks.4 · A second AI red-teams itFind the holes while it is still just words.5 · A fresh session builds itExecute the plan. Do not change the plan.Two reviews before a line is written. Words are cheap to change; code is not.

Every feature ran this gauntlet before a line of it was built. On the refactor that split the game’s oversized HUD, a wrong extraction order would have cost me a weekend. Two reviews caught it while the plan was still words, and words are cheap to change.

Codex taught me why the plan needs a definition of done attached. Give it a plan alone and it moves fast but stops at “I did the steps.” Give it a goal alone and it chases genuine completeness but can overreach, spending hours trying to prove something it cannot prove right now, like hunting for a device that is not attached instead of simply saying so. A reviewed plan with a clear definition of done gets the pace of the first mode with the standard of the second, and none of the spiral.

The human gates

Everything above is scaffolding the agents run inside. The gates are where I stand.

Every change arrives as a pull request whose description the agent is not allowed to skimp on, because the description format is itself a rule file:

---
description: PR descriptions must include a milestone checklist and an Owner approver block.
alwaysApply: true
---

# Pull requests: checklist + approver

1. Short summary, in plain English: what milestone or goal.
2. Milestone checklist: one line per item; mark N/A when it belongs to a later milestone.
3. What changed / how to test.
4. For approver (Owner): gameplay change? visual change? QA status? known issues?
   Decision: Approve / Request changes / Reject. One line on what to check on device.

The last line is the whole point. Every change routes back to a human decision, made while looking at a real device, that no agent is allowed to make for me.

The gate earns its keep on the quiet bugs, the ones where the screen looks fine and the truth underneath is wrong. Three real ones from this project, each caught at a human gate, each now guarded so it cannot slip back:

What the screen showedWhat was actually trueWhat guards it now
The booster tray did nothing when tappedA renamed handler left a parse error that silently detached the entire HUD scriptParse and scene-load safety checks, plus booster flow tests that run after any tray change
A badge lit up with nothing to claimMail the player had already read was being counted as needing attentionNotification-rules drivers that assert a badge means something actionable
The leaderboard showed a rank that was not realThe fallback served the wrong snapshot when the backend was downLeaderboard hub drivers that check what the backend says, not what the label says

Notice the pattern: a human caught each one by looking, and then the catch was converted into a test, which is the scar-tissue rule and the test bar shaking hands.

The last gate is the visual and product call, and it is the one I never even tried to delegate:

The level-complete screen with three stars, score, unused moves, and coins earnedThe level-failed screen with retry choices and a clear next action for the player

Whether that win feels earned and that fail feels fair is a judgment no agent can make, for reasons I unpack in why AI cannot see your UI.

And at release time, the gate becomes a language rule. When I ask where a feature stands, the answer must separate four different facts instead of blurring them into “done”:

  1. Complete in the repo. The code exists and its tests pass.
  2. Present in the active beta. A build containing it is on a real phone in a real hand.
  3. Live in production. A player can get it from the store today.
  4. Blocked by a store or a real device. Named explicitly, with the missing evidence spelled out.

The manual backs that with specifics, because the details blur easily: an Android version code and an iOS build number are different things, a successful upload is not an approved release, and a local build is not a beta in someone’s hand.

The Tropic Tumble listing on Google Play with icon, screenshots, and install buttonThe Tropic Tumble listing on the Apple App Store with icon, screenshots, and get button

The only status that counts as done. Everything before these two screens is one of the other three buckets, and my agents have to say which one.

Start tonight

You do not need four tools to begin. You need one agent, one file, and one habit. Create an AGENTS.md in your repository root tonight:

# AGENTS.md

## Commands
- Build: <your build command>
- Test: <your test command>

## Hard rules
1. Work on a feature branch. Never commit to main.
2. Never delete asset or data files. Retire them in code, keep the file.
3. Before coding, name the file that owns the state you are changing.
   If you cannot name it, stop and ask.

## Definition of done
- The change is present in a build I can actually run, not just on a branch.
- Tests relevant to the touched area ran and passed.

## Handoff (required every time you say "done")
- What ran: the exact test commands.
- What passed, what failed, what was skipped.
- What this does NOT prove yet (device, visuals, backend state).

## Recurring corrections
- (Add the first one the next time the agent gets something wrong.
  This section becomes the most valuable file in your repo.)

Then the habit: for your next real task, make the agent write a short plan first, read the plan yourself, and only then let it build. That is the whole system in miniature. The rest, the roles, the gate, the test bar, grew one correction at a time, and yours will too.

Whose product it is

Somewhere in this project my job stopped being writing lines of code and became designing the system the agents work inside: the manual they read, the layers they respect, the bar their work has to clear, and the gates where I stand and look. That is not a smaller job than programming. On this project it was the job.

Agents implement. I own the product.

And under all of it sits the question I have asked on every QA project I have ever worked, now aimed at every confident “done” an agent hands me: what does this actually prove?

Found it useful? Share it.
Julia Pottinger

Written by

Julia Pottinger

Hi, I'm Julia. I've been in QA for over a decade. I spend my days testing software and my own time building apps and games, and I write here to share what I learn, the practical, honest lessons you can actually use.

Comments 0

Share your thoughts, ask questions, or add to the conversation.

Be kind and constructive. Stay on topic. No spam or self-promotion.
Loading comments…