How I Learned to Vibe Code
I wanted to understand building with AI from the inside, so I learned to vibe code on a real app of my own: what I expected, what the machine turned out to be good and bad at, and how I kept changing the way I worked until the app went to the App Store.

The app came from real problems
My partner and I have two apartments and a large basement. We keep losing track of where a thing is. A friend of mine has a similar problem: he decorates for every season and holiday, keeps it all in a storage unit, and swaps boxes back and forth all year.
I needed a general purpose home inventory app that understood multiple primary locations, infinitely nest-able to match your mental model, and no item limits. Most things out there require a sub after they get you hooked, or they specialize use cases, e.g. for fashionistas who want to detail their wardrobe and plan looks. I also plan to add multi-user household sharing, but I pulled out of that after getting into CloudKit complexity and the burden of keeping folks' data safe on an externally hosted system... plus it gives me a paid feature to tack on later!
Picking a tool, then interviewing it
I looked at several AI tools and picked Claude, based on Reddit reviews and my own frustration with ChatGPT's limits and its seeming inability to learn from its mistakes.
Before any code, I spent about a week working with Claude the way I'd work with a strong consultant on a product team. We built the documents a team like that works from: a competitive analysis, a requirements doc, a feature list ranked against my wishlist, a roadmap and a pitch deck.
Writing things down, then making it write things down
My first fix was to keep my own log of product ideas, so that when a feature drifted I had a record of what I'd meant and could put it back. Then I realized Claude could keep it for me, as long as the record lived outside the chat. Whenever I typed "insight:" followed by a thought, Claude wrote it up and pushed it to GitHub, where I could track how it changed.
That habit grew into a full set of files kept next to the code: a backlog, a bug list, a changelog, a progress log, and strategy docs on pricing, onboarding, activation and engagement. One of them, the handoff doc, has a single job: getting a new session moving again quickly. Every conversation with Claude starts with no memory of the last one, so instead of re-explaining the app, I'd paste in that one page and we'd be back to work in minutes.
The tools changed three times: a chat window where I pasted code into Xcode by hand, then Cowork, then Claude Code working directly in a GitHub repository on my computer. Each move happened when the process outgrew the tool, and the files are why the moves cost me nothing. Xcode was new to me, and Swift was entirely new.
So I built a team
At some point Claude got one of its infamous updates and became very agreeable. Every idea I had was a good one, and when I asked for alternatives, it ranked mine as the strongest. That isn't a second opinion. I realized I missed my team. Working with people is messy, but something better usually comes out the other side, and nothing was doing that job.
I asked Claude to set up a product team. They share one constitution, the rules for how the team works, and each has its own charter: what it cares about, what it's good at, and when it should push its own opinion. Each also has its own memory file outside Claude, plus a shared memory for the team.
On a decision, the bot-workers go back and forth for a couple of rounds, then bring me a recommendation, and I make the call. After a stretch of work, the team wraps up: each bot-worker tells me what it learned, I steer, and they write their lessons into their memory files. Each file is capped at roughly forty lines, so adding a lesson means merging or retiring another.
- SparkNavigatorfind the truth
- ShapeArtisangive it a feeling
- SliceNavigator + Architectcut the thinnest version
- BuildArchitectone feature a turn
- CritiqueAdvocate + Artisanhold the bar
- CanonizeChroniclercarry it forward
I built the setup in one day. Before trusting it, I copied the plan into a second Claude window and asked it to find the problems. It found a setup mistake that would have loaded none of the team, with no error. I'd have spent weeks thinking I had a team when I had the same single assistant.
Then I taught the team to argue
On returning from a summer break, I had fresh perspective that I just needed to ship my 1.0, gather some real world feedback, and decide what's next.
I'd been wrestling with multi-user shared home inventory (and privacy) all summer, and it still wasn't done. Every change had to be tested on two phones signed in to two different iCloud accounts, and each round turned up another edge case. Meanwhile the bot-workers kept agreeing with each other and with me, so nobody said the hard thing: sharing wasn't going to make the first release.
I didn't need more ideas. I needed a team that could make brutal decisions and show me why. So I rewrote each bot-worker with a position: what it argues for, what it argues against, and what would change its mind. For hard calls we "convene."
The first two convenes did what I needed. One decided that 1.0 would ship single-user, with sharing built but hidden until I could test it properly. The next cut privacy back to one simple rule, after it had eaten weeks of work no tester had touched. With the reasons and the dissent on record, I could stop second-guessing and get the product out the door.
The assigned dissenter caught real problems. It showed that one review's top finding came from how we'd taken the screenshots. It goes the other way too. The team cut most of the options for a card on the home screen as redundant. I argued that the home screen looked like a bare-assed database and needed something on top, and the second convene reversed the cuts.
What it's good at
It will give me as many options as I have credits. Of course, few of them are desirable and feasible. But even (and sometimes especially) absurd ideas can nudge ideas in a better direction.
It's decent at manufacturing perspectives: a dissenter's case, a competitor's approach, the argument against my favorite idea. Again, most don't land, and some are plain wrong, but a few do, and that's handy when part of the work feels stuck.
What it's bad at
It confidently names a cause without double checking. It reads the code, forms a theory and states it with total confidence. Then I tap the button and the theory is wrong. E.g. for several weeks it insisted that a massive delay in activating the device keyboard was "it is what it is." We worked through five theories, each disproved by a single measurement. It turned out the debugger we had added in a previous round was the culprit, discovered almost by accident.
It takes shortcuts without saying so. Every output needs checking, often more than once. The worst case: the app had been "syncing to iCloud" for weeks, and when we finally looked in Apple's console, 16 of my 411 items had ever made it there. The app looked fine the whole time. Now nothing counts as done until I've checked where it was supposed to land.
It fights the platform. A design decision resulting in hand-baked screen titles kept drifting out of alignment, with each fix added more math. It got particularly bad when I ran through the app with VoiceOver. Claude did acrobatics to try to stay true to my design, when it finally admitted that using a stock component could have saved us hours of frustrated testing.
The drift, in every aspect. I keep a list of words, phrases, and grammatical quirks I would never use in my own writing. It can sort of follow along, but it can only evaluate itself AFTER it's written something, so for a few hours I was getting the first response (written terribly), then an apology and explanation of how it didn't follow the rules, then a second response that did follow the rules. At another point I asked it to render my app icon to App Store standards: it gave me three entirely new and unrelated icon options, and was unable to explain why it did that.
Keeping score
When 1.0 went into review, we ran the wrap-up across the whole release, and I asked for a scorecard, because I wanted to know whether the team was arguing or only looked like it was.
The convenes earned their keep. They changed almost every decision they touched, and the assigned dissenters made most of the catches. Even so, the biggest single source of corrections was still me. The team and I each changed the other's mind a few times, and a wrong call that used to linger for weeks now gets revised within a day or two.
The weak spot is memory. Mistakes kept coming back after a lesson about them had been written down, and the most stubborn was "check before you state it as fact." Writing a rule down didn't stop the mistake. It did let me count it, and the count tells me which rules need a check built in.
Where it landed
TuckBuddy 1.0 went to App Review on October 2, about three and a half working months after the first commit, and it's now live on the App Store. It syncs across devices, works at the largest text sizes and has other deep accessibility baked in, and it's nearly ready to go with multi-user sharing when I have time to run tests on multiple accounts. The institutional knowledge brain has about 40 decisions / principles that will be carried over to my next project.
My part turned out to be the job I've always done, at a faster pace. I set direction, I judge what's good, and I build a system around the team (this time, a machine) so the work stays reliable when I'm not watching every step. The machine writes the code. Deciding what's worth building, and whether an answer is right, is still on me. Tuning the team members and the process has a lot of parallels to working with a human team: some frustrating, some delightful.
What's next
The real test is my next product. The point of the team's memory is that it keeps learning, so the next build doesn't start with me and the machine teaching each other how to do it right all over again.
Over three months I kept correcting the same kinds of things, so before closing out 1.0 I wrote them down as six principles that now load on every product: start from a real person and the job they need done; accessibility is the floor; use what people already know; never lose their stuff; fit the person, not the system; respect the person. The scorecard will show whether the next product needs fewer corrections to get there.
What I'd tell someone starting:
- Start loose so you learn how it feels, then add process before it hurts.
- Keep your notes in files outside the AI, with the reason next to every decision. The next conversation starts with nothing.
- Make it measure before it tells you what's wrong. When it opens with a cause, ask how it knows.
- Assume it agrees with you too much, and give something the job of disagreeing.