The first time I read code that Antigravity had written, I had a specific feeling: correct, but not mine.
No bugs. It ran. But something was off.
I've been building apps independently for over a decade. Writing code almost every day for that long means you develop a rhythm, a set of unspoken rules, a feel for what belongs in a codebase. I didn't expect that instinct to conflict with an AI coding tool. It did.
Why Antigravity's Code Felt Like a Stranger's
Antigravity's generated code is generally good. Well-named variables, appropriate comments, clear logic. But when I looked at it through years of indie development, it had a quality I can only describe as "textbook." It was right in a way that felt detached from any real decision-making.
Take error handling. My codebase handles errors based on hard-won judgment: "this error theoretically can't happen, but if it does, I want it logged this way." Antigravity, following best practices, treats all error cases with equal weight. The result is verbose code that, when dropped into my project, looked like it came from somewhere else.
The strangeness had a name: missing context. The code did the same thing, but there was no trace of why it was done that way.
What It Means for Judgment to Live in Code
The same operation, written with an understanding of why this design, reads differently months later — the intention comes through. That happens because the author's judgment is embedded in the code itself. When I look back at something I wrote six months ago and can still reconstruct the decision, it's because the reasoning was baked in at the moment of writing.
Antigravity doesn't have that. More precisely: I hadn't given it my context. That realization came later. A generative model will guess at design intent, but guesses tend to miss. Context, I came to believe, is something you hand over — not something you make the tool infer.
The First Wall — Right Code That Wasn't Mine
For the first few weeks, my prompts told Antigravity what to do and nothing else.
"Add validation to the favorites feature in the wallpaper app."
The code that came back worked. But my project has a UserPreferences class where persistence logic lives — that was a design decision made after a painful refactor years ago. Antigravity, without knowing that, wrote the validation somewhere else.
// Generated by Antigravity (no context provided)
func validateFavorite(item: WallpaperItem) -> Bool {
guard !item.id.isEmpty else { return false }
guard item.category != nil else { return false }
return true
}
// In my actual codebase, validation lives in UserPreferences
// This standalone function will get lost in the next refactorThe mismatch wasn't Antigravity's fault. I told it what to do, not where, not why. The context I'd accumulated over years was locked inside my head.
Three Prompting Patterns That Changed Things
After enough friction, I landed on three habits that made the generated code start to feel like mine.
1. Lead with design intent, not just the task
Before describing what I want, I describe why the codebase is built the way it is.
"In this project, all persistence logic is centralized in the
UserPreferences class — a decision made after scattered code
created a maintenance problem in an earlier version. Please
implement this validation feature within that existing structure."
With the why in place, Antigravity's where becomes accurate. It stops treating my project as a blank canvas.
2. State what this project deliberately doesn't do
My code has intentional absences — things I've chosen not to implement for specific reasons. Without saying so explicitly, Antigravity treats them as gaps to fill.
"This app deliberately holds AdMob SDK at version 21.x.
We're not pursuing a version upgrade at this time.
Please don't include upgrade suggestions."
When constraints come with reasons, Antigravity stops working around them.
3. Add your own context comment to every generated function
I stopped committing Antigravity's output as-is. After generation, I add one line of my own — the reason this code exists and where it's headed.
// TODO(masaki): Revisit after ASO redesign planned for mid-2026
// AdMob placement held intentionally — review post-UI refresh
func setupBannerAd() { ... }Code without a why is a liability six months later. That single line changes what the code means to whoever reads it next — even when that reader is me, and even when the code was written by an AI.
Where It Still Didn't Fit
Even with all three habits in place, there were times I couldn't hand over enough context. I'll be honest about them.
The hardest was design decisions that span multiple files. A policy like "should screen-transition state live in per-screen ViewModels, or be managed centrally across the app?" can't be read from any single file. Handed to Antigravity as one isolated task, the result was locally reasonable but drifted from the app's overall direction.
// A policy a single-file prompt couldn't capture
// "This app treats not sharing state between screens as a principle"
// → one line in AGENTS.md rarely reaches the context of an individual task
My workaround: write cross-cutting policies in AGENTS.md, but for high-impact changes, add a step where I check the generated output against the broader principle myself. Handing over context and having a human confirm alignment at the end are, for now, both necessary.
The second case was my own past "whims." Code I once wrote as an exception, under a deadline or a passing mood, has no rational reason I can reconstruct after the fact. I only notice this when I try to explain such code to Antigravity and realize I can't say why I wrote it that way. Ironically, the act of explaining my code to an AI became an audit of it.
The Balance I've Found
With these three habits, the estrangement mostly faded. When generated code still feels off, I recognize it as a signal: I haven't given Antigravity enough context yet.
In indie development, a codebase is an accumulation of decisions. Once you learn to verbalize those decisions and hand them to Antigravity upfront, the tool stops generating code at you and starts working with you. Letting it move the hands frees me to focus on why something is built the way it is.
If the AI's output feels like someone else's code, the answer isn't to edit more aggressively after the fact — it's to give more of yourself before generation starts.
For thoughts on where delegation breaks down entirely, I Delegated to AI and Regretted It — The Boundary an Indie Developer Found covers the harder lessons.