ANTIGRAVITY LABJP
Articles/App Development
App Development/2026-05-14Intermediate

I Let Antigravity Take Over My 10-Year-Old Wallpaper App — What Happened Next Surprised Me

A real case study of handing a wallpaper app's Swift codebase — built since 2014 — to Antigravity's Background Agent. What it got right, what it missed, and what that taught me about AI-assisted refactoring.

antigravity435app-dev49background-agent8refactoring8ios36indie-developer5

A Conversation with Ten Years of Code

I've been developing iOS apps independently since 2014. My wallpaper and healing apps have accumulated over 50 million downloads across that time — and along with those downloads, an equally layered codebase.

Recently, I used Antigravity's Background Agent to refactor the Swift code of a wallpaper app I've maintained for over a decade. The honest conclusion: it wasn't that "the AI was smart." It's that the way AI reads code is fundamentally different from how another developer would.

The First Thing Background Agent Noticed

The moment I loaded the repository into Antigravity, Background Agent started detecting and reporting issues automatically. I expected it to flag deprecated APIs or outdated Swift syntax. Instead, the first report looked like this:

⚠️ Detected: 47 instances of inconsistent patterns
UICollectionView data source implementations show mixed architectural styles.
Patterns written between 2016 and 2024 differ significantly across files.

That's exactly right. Ten years of development means ten years of evolving Swift best practices layered on top of each other. Code from 2016 was written during the Objective-C migration period. The 2020 code was mid-transition to SwiftUI. The 2024 code uses Swift Concurrency throughout.

A human reviewer would say, "This old file can wait — let's handle it later." Antigravity didn't think in terms of time. It thought in patterns. That was a perspective I hadn't expected, and it genuinely surprised me.

Where the AI Fell Short: The "Why Behind the Code"

The most interesting part was discovering the agent's limits. I asked it to "clean up" a particular implementation without explaining my intent. This is the change it proposed:

// Before (what the agent wanted to change)
func downloadWallpaper(id: String) async throws -> UIImage {
    // Retry up to 3 times for a specific CDN endpoint
    for attempt in 1...3 {
        do {
            return try await fetchFromCDN(id: id, endpoint: .primary)
        } catch {
            if attempt == 3 { throw error }
            try await Task.sleep(nanoseconds: 500_000_000)
        }
    }
    fatalError("unreachable")
}
// After (the agent's suggestion)
func downloadWallpaper(id: String) async throws -> UIImage {
    // Simplified to a single call
    try await fetchFromCDN(id: id, endpoint: .primary)
}

From the agent's perspective, this was a clear improvement — removing redundant retry logic. But in reality, this CDN has a known instability issue for requests coming from outside Japan (roughly 30% of my users). The retries weren't accidental; they were load-tested. The code had comments, but the reasoning — why 3 retries, why 0.5 seconds — wasn't readable from the code itself.

Once I added the context to AGENTS.md and asked again, the agent responded accurately.

# Notes on Download Implementation
 
CDN instability for international requests (approx. 30% of traffic) is well-documented.
The 0.5s retry interval was determined from real latency measurements.
3 retries represents the upper bound of what users will tolerate waiting.
Do not change these values without cross-referencing CDN error rate logs.

For more on structuring your AGENTS.md, see How to write AGENTS.md for effective agent guidance.

The Unexpected Part: How Well It Read Old Swift

Honestly, the most surprising thing was the agent's accuracy in reading legacy Swift code.

For files from 2016–2018 that mixed Objective-C conventions (heavy @objc annotations, NSArray usage), the agent noted: "These patterns carry Objective-C conventions that may conflict with Swift 6's strict concurrency model in the following locations." It was correct.

There were parts of my own app that I'd half-forgotten the origins of. Having an AI take an outside view and catalog what was there — and when it was likely written — felt like something genuinely new. Even a developer who's been on a project for over a decade doesn't retain everything.

What Actually Improved — and What I Couldn't Let Go

After three days of work through Background Agent, total line count dropped by about 15%. But the numbers weren't the most interesting part.

Some of what the agent flagged as "deprecated API usage" was actually intentional — code kept specifically to preserve behavior on older iOS versions. The agent replaced three of those instances, confident they were bugs.

If I'd merged those changes directly, the layout would have broken on iOS 15 and earlier. Background Agent runs in a branch and proposes changes rather than applying them directly, which is the only reason I caught it.

The takeaway: it's not that "the AI decides, so I don't need to check." It's that "the AI handles 80% of the work so I can focus my human judgment on the remaining 20%." For a practical guide to setting up the workflow, see Background Agent: Getting Started.

What to Prepare Before Handing Over a Legacy Codebase

Based on this experience, here's what I'd put in AGENTS.md before starting a large refactor:

# AGENTS.md for Legacy Codebases
 
## Intentional Design Decisions
- Why certain deprecated APIs are kept
- Why specific implementations appear complex (not technical debt)
- Files and functions that must not be changed (e.g., payment flows, security logic)
 
## OS Version Support Rationale
- Minimum deployment target and the reason it hasn't been raised
- Why certain old APIs remain active
 
## External Service Characteristics
- Known unstable CDNs or third-party APIs
- Retry counts and wait intervals derived from real measurements

A codebase built over a decade contains accumulated judgment — decisions made under constraints that may no longer be visible in the code itself. Antigravity can read the code; it can't read the history unless you share it. The good news is that once you do share it, the accuracy is remarkable.

My grandfather was a traditional Japanese carpenter. He used to say that working with your hands is itself a form of devotion. Delegating work to AI doesn't feel like stepping back from that — it feels like clearing space for the decisions that actually need a human. Start with a small utility file or a test module. There's a good chance something unexpected will come up.

Share

Thank You for Reading

Antigravity Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

App Dev2026-06-15
Stop Adding a Ternary Every Time a New iPhone Ships: A Table-Driven Resolution Design
Every time a new resolution arrived—iPhone Air, 17 Pro—I was bolting another screen-size ternary onto a 29-branch pile. Here is how I reshaped that into a table-driven design where adding the next device is a one-line data change, with the actual Swift from my wallpaper apps.
App Dev2026-07-03
Catching Download Size Regressions Before Submission Day — A Weekly Agent Gate for AAB/IPA Size Budgets
Mediation SDKs and bundled assets quietly inflate download size. A design for size ledgers, budget gates, and agent-driven delta attribution using bundletool and App Thinning reports.
App Dev2026-06-28
Adding Mediation Partners Quietly Starved My iOS Attribution — Reconciling SKAdNetwork IDs Across Four Apps
I added mediation partners but iOS revenue barely moved — the cause was missing SKAdNetwork IDs in Info.plist. Here is how I reconciled SKAdNetworkItems across four apps, using an Antigravity agent as the matcher while keeping the revenue decisions by hand.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →