CLAUDE LABJP
FORK — Claude Code 2.1.212 changes what /fork does: it copies your conversation into a new background session with its own row in claude agents, so you can keep working. The old in-session subagent is now /subtaskLIMITS — WebSearch calls are now capped at 200 per session by default, and subagent spawns get the same 200 ceiling, so a runaway search or delegation loop stops on its ownMCPBG — MCP tool calls running past two minutes now move to the background automatically, keeping the session usable. Tune the threshold with CLAUDE_CODE_MCP_AUTO_BACKGROUND_MSPLANFIX — Fixed plan mode auto-running file-modifying Bash commands such as touch and rm without a permission prompt or an SDK canUseTool callbackSONNET5 — Claude Sonnet 5 is running on introductory pricing of $2 per million input tokens and $10 per million output. After August 31 it moves to $3 and $15IPO — Bankers are reportedly lining up investor meetings for Anthropic ahead of a possible public listing as soon as OctoberFORK — Claude Code 2.1.212 changes what /fork does: it copies your conversation into a new background session with its own row in claude agents, so you can keep working. The old in-session subagent is now /subtaskLIMITS — WebSearch calls are now capped at 200 per session by default, and subagent spawns get the same 200 ceiling, so a runaway search or delegation loop stops on its ownMCPBG — MCP tool calls running past two minutes now move to the background automatically, keeping the session usable. Tune the threshold with CLAUDE_CODE_MCP_AUTO_BACKGROUND_MSPLANFIX — Fixed plan mode auto-running file-modifying Bash commands such as touch and rm without a permission prompt or an SDK canUseTool callbackSONNET5 — Claude Sonnet 5 is running on introductory pricing of $2 per million input tokens and $10 per million output. After August 31 it moves to $3 and $15IPO — Bankers are reportedly lining up investor meetings for Anthropic ahead of a possible public listing as soon as October
Articles/Claude Code
Claude Code/2026-05-26Intermediate

Four Weeks With Claude Code: Driving Xcode Warnings to Zero in an Indie iOS Codebase

An indie iOS developer behind 50M+ downloads pairs with Claude Code for four weeks to clear hundreds of accumulated Xcode warnings. Notes on weekly scope, what to delegate, and the boundary where human judgment still wins.

Claude Code197Xcode3iOS24Refactoring3Indie Development8

I'm Masaki Hirokawa, an artist and indie developer running a small collection of wallpaper and wellbeing iOS apps. Once cumulative downloads crossed 50 million, the warnings piling up in my Xcode build logs started to bother me in a quiet but persistent way. None of them were serious enough to crash the apps, but watching 300+ warnings stream past during every build felt like the kind of misalignment a craftsman would notice before anyone else.

Both of my grandfathers were temple carpenters in Japan, and one of the things I absorbed from them is that something built well shouldn't drift over decades. Compiler warnings carry that same signal for me: small misalignments that hint at where the joints have shifted. So this spring I gave myself a four-week sprint with Claude Code as a partner, aimed at getting Xcode warnings to zero. This article is the field report.

Setting the Scope Before Touching Any Code

The framing I committed to up front was not "achieve zero warnings" but "switch to a workflow that can keep warnings at zero." No new features during the sprint, no major library upgrades, no chasing of stretch refactors. The only objective was reducing the addressable warnings that showed up in the build log.

A tight scope made the context I handed to Claude Code naturally narrow. I limited the work to three production apps, captured the xcodebuild output without -quiet, and saved it as a plain text log inside the Claude Code working tree. In the first session I asked Claude to read the log and group the warnings by intent, then sort each group by the cost of fixing it.

The result was a four-bucket map: Deprecation warnings, Unused symbol warnings, places where type inference had gone fuzzy, and @available bounds that had aged out. That single step gave me more clarity in thirty minutes than I'd had by squinting at the log alone for months.

Week-by-Week: Start With the Mechanical Wins

Week 1 was nothing but Unused warnings and stale import statements. I asked Claude Code to "propose deletions for Unused Variable warnings only, without changing observable behavior," and I accepted the diffs one feature branch at a time. The rule I learned to follow: never try to clear multiple warning categories in a single commit. One category, one region, one PR. If a test failed later, rollbacks stayed cheap.

Week 2 was the Deprecation backlog. I had more leftover UIApplication.shared.statusBarOrientation calls and pre-UIScene lifecycle paths than I'd realized — APIs deprecated as far back as iOS 13 that quietly survived. Claude Code drafted the replacement strategy per API, and I personally verified iPad orientation behavior by hand because that's something a static analyzer can't feel.

Week 3 targeted fuzzy type inference and missing @MainActor annotations. This is the area where Claude Code can over-correct if you let it. I switched modes: have it propose the smallest possible change that compiles cleanly, accept only that. Treat it as scaffolding for the eventual Swift 6 strict concurrency turn-on, not the turn-on itself.

Week 4 closed out remaining @available ranges and the warnings I couldn't fix because they came from third-party SDKs. For that last category I asked Claude Code to "document every unfixable warning with the reason it must remain." The output became _docs/known-warnings.md, which now acts as the basis for any build-setting suppressions I decide to add.

What I Delegated, What I Kept

By the end of the sprint, a clean line had emerged between work I happily handed off and work I refused to. Claude Code handled the local, diff-reviewable changes well: deleting unused variables, swapping API signatures, normalizing @available ranges. These are the chores I personally don't enjoy doing, and the speed and accuracy I got back were genuinely a win.

What I kept in human hands was anything that touches felt experience — widget background rendering, scroll inertia, haptic intensity, image-loading timing. For apps that long-time users have a muscle memory for, a refactor that's logically correct can still erode the "usual feel." This is something I've learned the hard way across twelve years of indie iOS development. Zero warnings is never worth a regression that loyal users perceive but can't articulate.

The other piece I kept was the decision to intentionally retain certain warnings: ones from third-party SDKs, ones from compatibility shims I want to keep, ones from A/B-test code paths running in parallel on purpose. Claude Code wants to remove these, and I instead annotate them with a // MARK: comment that records the reason. I avoid // swiftlint:disable precisely because future-me needs the rationale, not the silence.

Friction and How I Dialed It Down

The first source of friction was Claude Code's tendency to fix too much per turn. The cure was instruction granularity. Every prompt I sent included three constraints: target a single file, target a single warning category, and keep the commit under roughly 200 lines of diff. With those guardrails, the proposals stayed reviewable.

The second was making Claude Code self-verify the build. Running xcodebuild through Claude Code produced logs too long to digest in one round. I switched to xcodebuild ... | tee build.log and told Claude Code to "read only the last 500 lines of build.log" when checking the result. Latency dropped, and review pacing improved noticeably.

The third was my own review fatigue. Claude Code was fast enough that I became the bottleneck. Mid-sprint I set a daily ceiling on how many diffs I would merge, on the theory that approving fixes faster than I could read them was the same as creating new debt with a different name.

Numbers From the Sprint

Starting warning count across the three apps: 312. Final count after four weeks: 6. The remaining six are all third-party SDK warnings logged with reasons in known-warnings.md. Total commits: about 90, of which roughly 75 were Claude-drafted diffs that I reviewed and accepted.

The biggest unexpected payoff was psychological: the resistance I used to feel when opening the build log was gone. With 300 warnings on the badge, I had unconsciously closed the log before reading it. That habit was quietly degrading the quality of every other debugging decision I made — AdMob latency, Firebase init ordering, anything that lived in build output became easier to triage once the noise was gone.

Zero new warnings were introduced during the sprint. Writing "do not introduce new warnings" into Claude Code's standing constraints turned out to be surprisingly effective. For an indie developer with a long-running codebase, the lesson I keep coming back to is that "achieve zero" matters less than "switch to a workflow that holds zero."

What's Next

The next four-week block will gradually flip on Swift 6 strict concurrency and work through Sendable violations with Claude Code. Turning the flag on across the whole codebase at once would resurrect hundreds of warnings, so I'm planning to enable it target-by-target with @preconcurrency boundaries drawn deliberately.

In parallel I want to wire up an automation where release-time xcodebuild logs flow into Claude Code, get summarized, and update _docs/known-warnings.md without my input. If I can codify "holds zero" into the build pipeline itself, I free up time for the parts of indie development I actually want to spend hours on. The self-taught programming I started in 1997 was once the goal; today it works best when it gives me back time for everything else. I hope these notes are useful to others maintaining long-lived codebases.

Share

Thank You for Reading

Claude 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

Claude Code2026-07-08
Auditing Your Own Code for Required Reason API Declarations with Claude Code
Required reason codes in PrivacyInfo.xcprivacy apply to your own code, not just third-party SDKs. After a wallpaper app of mine was rejected, here is the Claude Code workflow I use to scan Swift sources and match APIs to reason codes before submission.
Claude Code2026-05-23
A Daily Revenue Pipeline for 4 Wallpaper Apps: 8 Weeks Running App Store Connect API + AdMob With Claude Code
An 8-week record of running App Store Connect API and AdMob Reporting API through a Python pipeline for 4 iOS wallpaper apps, with Claude Code helping absorb JWT auth quirks, gzip TSV edge cases, timezone misalignment, and Slack alerting thresholds — written from an indie developer's perspective.
Claude Code2026-04-12
Claude Code × Swift/iOS Production Guide — From Xcode Integration to App Store Launch
A practical guide to building production-quality iOS apps with Claude Code and Xcode. Covers CLAUDE.md design, SwiftUI implementation, Clean Architecture, automated testing, Fastlane CI/CD, and App Store submission.
📚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 →