All articles

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

People ask me which AI tool I used to build my game. It is not really the one that matters, because no single tool was the answer. I did not use one.

I built Tropic Tumble, a tropical match-3 game now live on Android and iOS, by giving a handful of AI tools different jobs, the way a small studio gives different people different roles, and by writing them an operating manual so they would stop making the same mistakes.

I directed. They built. I decided what shipped.

I built it under the name JPott Studios. The scale a single person can ship this way is its own story, and I tell it in how I built a mobile game with AI agents.

What matters here is that no single AI did it. A system did. I want to show you the system, because the tool you pick will keep changing and the system is what lasts.

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. One person, a few AI tools with clear jobs, and a lot of saying no. The agents wrote most of the code behind this screen. None of them could tell me whether it looked right.

The tool matters far less than how you direct it. A team of brilliant contractors with no brief, no definition of done, and no review will hand you a mess very quickly. The same team with a clear brief, clear ownership, and a human who checks the work will hand you a product.

With AI it is exactly the same, except they work faster, so an unclear brief produces a mess faster too. So this is less about ChatGPT, Cursor, Codex, and Claude than about the system around them.

The cast, and the job each one had

I did not plan this division on day one. It settled over the project as I noticed each tool was better at a different shape of work, and then I leaned into it deliberately.

ChatGPT · the designerproduct, flow, powers, screensCursorbuilds the bulk; leave it running on a milestoneCodexrepo-aware, overnight, the sharper deep workClaudereviews; is this actually done?Me, the human ownerI see what AI cannot, and I decide what shipsHermes: autonomy I tried and dropped

  • ChatGPT is the designer. Before a line of code, I work the product out loud with it. It has the best sense of product, user flow, and production quality, so it is where the game gets designed, not coded. The questions we worked through:
    • What should the powers be, and I landed on elemental ones like water and solar.
    • How should combos and obstacles behave.
    • What is on each screen, and how a player moves from the island map into a level and back out.
    • What the activities and the leaderboards should reward.
    • What makes an island feel like the Caribbean I am from rather than a generic beach.
  • Cursor is the builder I leave running. Give it a milestone and a plan and it does the bulk of the daily implementation, the feature work and the big refactors, including breaking up board_manager.gd after it had become the oversized file carrying too much of the board’s behaviour. Its real weakness is that it cannot reliably see its own work, which I come back to below.
  • Codex is the repo-aware specialist. It is an app I install and sign into with my ChatGPT account, and because it can see my actual repository it is the sharper one for reasoning across the whole codebase and for work I set running overnight.
    • It is also where I generate art now, and the repo access changes the whole loop. With ChatGPT I had to prompt, generate, check, correct, download, save to a folder, then tell something else to implement it. Codex generates the asset and wires it straight into the project.
    • Its one gap was clean transparent backgrounds: at first it chroma-keyed and removed them badly, so I finished the cutouts by hand in Canva, which is excellent at it. Once Codex had reliable Chrome control, I let it drive Canva itself, generate, remove the background there, save it back, implement it, so the lifecycle kept tightening as the tools improved.
  • Claude is the reviewer. Architecture critiques and honest “is this actually done” passes. A Claude review of a messy file would often become the very next task I handed to Cursor.

The one instruction I gave Cursor more than any other, and the one that did the most work, was simple:

Implement the plan as specified. Do not edit the plan. Mark the to-dos as you go. And do not stop until they are all done.

I also tried real autonomy. I ran an agent called Hermes for hands-off overnight work, hoping to wake up to finished features. It would start a task on a heartbeat and never actually finish it.

Nothing I could ship came out of it, so I dropped it. Autonomy that does not finish is not autonomy, it is a process that needs a babysitter, and at that point I would rather drive Cursor myself.

The manual matters more than the model

Here is the part people skip, and it is the part that actually made this work. Every one of those agents reads a written operating manual that lives in the repository.

Without it, they all make the same mistakes, repeatedly, because a model has no memory of the correction you gave it yesterday. The manual is how yesterday’s correction survives into tomorrow’s session.

There are three kinds of instruction file doing this work, and they are not interchangeable.

Instruction fileWho reads itWhat it is for
AGENTS.mdCodex and most agentsThe cross-tool standard. Build and test commands, conventions, and hard rules in the repo root.
CLAUDE.mdClaudeClaude’s own memory file. It reads this, not AGENTS.md, unless you import or link it.
.cursor/rules/*.mdcCursorScoped rules that attach to specific files or always apply, pulled into the model’s context.

AGENTS.md is now an open standard rather than one vendor’s idea, and a long list of tools read it. One detail trips people up: Claude reads CLAUDE.md, not AGENTS.md by default, so if you want one source of truth you import the other into it. Cursor’s rules are .mdc files in .cursor/rules that can always apply or attach only to the files they are relevant to. 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 point is not the file names. The agents share a written brief, the same way a team shares one.

Here is one of those Cursor rule files from my project, trimmed. The front matter is the whole trick: alwaysApply: true means it rides along in every Cursor session, so the rule cannot quietly be forgotten the next time:

---
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.

My rules are scar tissue

If you read my project’s operating manual, you would notice that almost none of it is aspirational. It is a list of mistakes the agents made, written down so they cannot make them again.

I think of it as scar tissue, and it is the most honest documentation in the whole project.

Here is a slice of the actual AGENTS.md, lightly trimmed, so you can see the shape of it:

## 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.

Every block in there exists because an agent did the opposite once. A few of those rules, and the failure behind each one:

  • Never check out the main branch to “clean up.” An agent, having pushed a branch, would helpfully switch back to main and start committing there. So the rule is explicit: do all work on feature branches, never end a session on main, never commit or push to it.
  • Never delete asset files. Agents love to “tidy up” by removing art they have decided is unused. One wrong guess and a piece of the game is gone. So the rule is: if an asset should be retired, stop using it in code, keep the file.
  • Pick the right layer before you finish. Agents reach for the lazy fix, which is usually ten more lines on the biggest file in the project. My manual names the files that are already too big, progress_store.gd and game_hud.gd among them, and says they get wiring and persisted fields, never new behavior. New behavior goes to a real owner.
  • Examples are never the whole list. This is my favourite, because it fixes the most slippery behaviour. An agent will follow a rule to the letter and dodge its spirit, saying “the rule only mentioned X” when the same problem clearly applies to Y. So the manual says, in writing, to treat every example as one instance of a larger principle and to go find the others.
  • Repo truth before reassurance. Do not tell me a feature is done because the code compiles or a screenshot looks right. Check the live code, the data, the build, and the backend, because done means present in the real build, not sitting on a branch.
  • Encode risk as a test, not a checklist. The riskiest things, player state and performance, do not get a paragraph of intentions; they get an audit contract registered in the docs and backed by quick regressions, so the promise runs and fails loudly instead of being something I have to remember. The rule also says tighten it on the next pass, because the first version of a contract usually checks that something happened, not that it happened correctly.
  • Use the evidence you already have. An agent will offer to reproduce a failure from scratch when the logs from the failed run are sitting right there. If a log exists, filter it; do not burn an hour recreating a crash you already captured. Reproduction is for when you have nothing, not for when you have a saved log with the answer in it.

None of that is exotic. It is what you do when you onboard a new team member: you write down the conventions, the boundaries, and the things that have bitten people before.

Agents just need it written more explicitly, and they need it every single session.

Separate the planning from the building

The single most useful habit I formed was splitting planning from execution and giving them to different stages. ChatGPT and I interrogate the problem and shape what to build. Then, in a fresh session, a coding agent executes that plan and is told not to change it.

The reason it matters is simple: it catches the expensive mistake cheaply. When you let an agent plan and build in one breath, it commits to an approach early and then spends real effort making that approach work, even when the approach was wrong.

Splitting the two gives you a place to catch the wrong idea before code exists.

Codex showed me the two modes clearly, and they pull in opposite directions. Give it a plan and it moves fast, but it tends to stop at “I did the steps” rather than “this is genuinely complete.” Give it a goal and it will get to genuinely complete, but it can overreach to get there, spending hours trying to prove something it cannot really prove right now.

If it needs a real device and none is attached, instead of just saying so and moving on, it will try to connect, try to grab a screenshot or a video, decide it will come back to it later, and go in circles, so a task that should take an hour eats most of a day.

What I actually want is the merge of the two: the pace of a plan with the completeness standard of a goal, finishing the real work without chasing proof it does not need.

This is also where I lean on ChatGPT a second time. After a coding agent hands me a plan, I take it back to ChatGPT and ask it to find the holes, the way you would ask a senior engineer to red-team a design before anyone writes code.

And when something is broken, I show it the actual screen and ask for the real cause and the fix, which becomes the prompt I hand to Cursor or Codex.

Me → ChatGPT
Thoughts on this plan? [pasted a coding agent's plan to split the giant GameHUD: keep GameHUD as the facade and pull the overlays out one at a time.]
ChatGPT
Yes, this is a strong plan. The biggest thing it gets right is that it does not rewrite GameHUD from scratch; it preserves the external contract and splits the internal responsibility, which is the safe approach for this codebase. Keeping GameHUD as the facade is right, because BoardManager and the tests already target its contract. I agree with the extraction order too: the shuffling overlay first because it is low-risk and isolated, then pause, then fail and win, and the play strip last, because that is where the layout contracts and the tests live.
Me → ChatGPT
[shared the fail screen] How would I fix this? It scrolls when it should just be a popover. And what buttons belong on it?
ChatGPT
You're right, it should not scroll at all. Right now it reads like a full-screen layer instead of a modal fail state, which breaks the contained-moment feeling. The root cause is that the fail UI is sitting inside a scroll container, or it is part of the main game layout instead of being isolated. Pull it into its own modal and keep it to the two buttons that matter: Retry and Exit to Hub.

This is ChatGPT as my reviewer, not my builder. It red-teams a plan a coding agent gave me before any of it gets built, and it diagnoses a broken screen so the fix becomes the next prompt I hand a coding agent. The judgment stays mine; it just makes the thinking faster.

The human is the gate, on purpose

I ran this project the way a studio runs, with named roles and approval gates, and I built the gates so that the agents could not make the decisions that were mine to make: a designer that only shapes specs, a builder that only implements them, and a reviewer that reports and does not change gameplay on its own.

Concretely, every change passed through a few templates:

  • A pull request came with a plain-English summary, written so that someone who does not read code could tell what changed, whether it affects how the game plays, whether it changes anything visual, and whether it has been tested.
  • A bug was written the way a player would describe it, with steps, expected result, actual result, and severity.
  • A release had to clear a checklist that ends, deliberately, with a line about whether I am genuinely proud to put the build in front of players.

The agents fill these in. I approve.

The pull-request template is itself a rule file, so the agents cannot skip the parts I care about. Trimmed, it looks like this:

---
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 most important line is the last one. Every release routes back to a human decision, on a real device, that an agent is not allowed to make for me.

I decidewhat to buildAgent buildspatches the codeChecks runtests, reviewReal deviceI look at itI approvethen it shipsI own both ends, what gets built and what ships. The agents own the middle.
The loop every change ran through. The agents own the build-and-check middle; I own the two decisions that are mine, what to build and whether it is ready, and nothing reaches players without the real-device look and my yes.
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

The agents built the screens. I decided whether the reward felt earned, whether the difficulty was fair, and whether any of it was good enough to ship. That part never moved off the human side of the gate.

The single most important thing the human catches is the thing AI is worst at: seeing. AI cannot reliably tell that a UI is off-centre, that a button is too big, or that two things overlap, and on a mobile game running across dozens of screen sizes those visual misses are most of the work.

Cursor could not do visual regression at all, which was a real block. Codex could, but even then I would get a screenshot back with the work called done, look at it, and see an obvious layout bug staring out of the same image, and have to ask whether it had actually looked.

More than once I gave up on having the AI position things and went into the files to set the x and y coordinates by hand, just to get something centred properly.

And the bugs it does cause are quiet ones. The hardest ones I chased in Cursor and Codex, reading the real evidence rather than guessing, and they were almost never wrong math:

  • A fairness bug a screenshot will never show you. The board once shuffled and quietly morphed fruit to fabricate matches the player never made.
  • A booster tray “did nothing” because a renamed handler left a parse error that detached the entire heads-up display script.
  • A purchase was slow to grant because the grant waited on a fixed number of frames instead of a timer, so on a slow device it crawled.
  • A badge lit up when there was nothing to claim, because read messages were being counted as needing attention.
  • A leaderboard showed placeholder data instead of a real rank, because the fallback returned the wrong snapshot when the backend was down.

Every one of those looked fine in a quick glance and was wrong underneath. I found each one, fixed it, and where it mattered added a test so it could not slip back, which is the whole reason the game holds together now.

Why all this scaffolding exists

If you take one thing from this, let it be why the scaffolding is there. The headline weakness of these tools is not that they write bad code. It is that they confidently report work as finished when it is not.

That was the pattern I kept seeing in the game: a screen reported as done while the button was off-centre, a feature marked complete while the backend state was wrong, a purchase fix that handled the symptom but not the real chain.

So you do not build your quality on the model behaving. You build it on a brief the agents read, a plan you approve, named roles, and a human gate.

Those turn “the agent said it was done” into “the work passed the checks and a person confirmed it.” That is the difference between using AI to go fast and using AI to ship something real.

Where to start

You do not need four tools to begin. You need a brief and a gate. Take the one agent you already use, and before you ask it to build anything, do two small things:

  • Write an AGENTS.md in your repository root with your build and test commands and three rules you care about, even if two of them are corrections from mistakes it made this week.
  • Make it plan before it builds. For the next real task, have it write a short plan first, read the plan yourself, and only then let it build.

That is the whole system in miniature: a written brief so the agent knows your rules, a plan you approve before code exists, and a human who decides what ships. Add the design partner and the second and third coding agent later, when you can clearly say what job each one is for.

The model you choose will keep changing, and it will have bad weeks. The brief, the plan, and the gate are what make any of them trustworthy. And if you want to see what that system actually shipped, Tropic Tumble is live on Android and iOS.

Treat your AGENTS.md like a test plan, not a wish list. Every line should be something you can check, and the most valuable lines are the ones you only thought to write after an agent got it wrong. A manual full of yesterday’s scars is worth more than one full of good intentions.

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…