Building iOS apps with Claude Code
Claude Code writes good Swift. It just cannot open Xcode, register the file it wrote, read a build error properly, or tap a button in the simulator. Here is exactly what breaks, what the workarounds cost, and what it looks like when the gap is closed.
If you have tried this, you already know the shape of the problem. The Swift is fine. Ask Claude Code for a SwiftUI view, a view model, a networking layer, and what comes back is usually reasonable — often better than reasonable.
Then you switch to Xcode and the file is not in the target. The build fails on something the agent cannot see. A Preview does not render and there is no way for the agent to know. You paste an error back into the terminal, get a fix, paste the next error, and forty minutes later you are doing manual labour in service of your assistant.
The problem is not the model's Swift. It is that a terminal agent and an Xcode project are separated by a boundary that neither side can cross on its own.
The six things that actually break
These recur across every practitioner guide worth reading, and they are structural rather than model limitations. A better model does not fix any of them.
1. The agent writes a file, and it does not compile. Adding a Swift file to disk is not the same as adding it to an Xcode target. Target membership lives in project.pbxproj, and agents cannot safely edit it. So the file exists, looks correct, and is invisible to the build.
2. `project.pbxproj` is genuinely dangerous to edit. In Tuist's description, it is "a property list file that was not designed to be edited directly." That fragility long predates AI — it is why XcodeGen and Tuist exist at all. Practitioner guidance for AI-assisted iOS work converges on treating it as off-limits: "NEVER let an agent modify .pbxproj. This is the single most important rule," because "a single misplaced character corrupts the entire project file." The failure mode is not a bad build, it is a project Xcode refuses to open and an hour in your git history.
3. No SwiftUI Previews, no simulator. The agent cannot render a Preview or tap anything in the simulator. Every visual change is verified by you, by hand, by looking at it.
4. No signing, no device deploy. Code signing, provisioning profiles and device registration all run through Xcode and an Apple Developer account. The agent cannot get you onto a physical phone.
5. Build errors arrive as noise. Without a structured bridge, the agent sees whatever you paste. Xcode build logs are verbose and largely irrelevant, so you end up triaging output manually to find the eight lines that matter.
6. Context saturates, and architecture drifts. On a real project the codebase outgrows the window. You start running /compact and /clear, and every clear costs the agent its memory of how the app is structured. Feature ten gets built to a different plan than feature one, because by then nothing remembers what feature one's plan was.
What people do about it
Two schools have emerged, and it is worth understanding both before picking.
School one: give up on Xcode. The highest-ranking guide for this exact query is titled "The Complete Guide to Building an iOS App with Claude Code (No Xcode Required)." Its reasoning is fair — Xcode is a GUI the agent cannot see into, build failures are opaque, and it chains you to macOS. Its solution is to not build a native app at all: Expo and React Native, cloud builds, QR code onto the device.
That works. It is also worth naming plainly: the most popular answer to "how do I build iOS apps with Claude Code" is to stop writing Swift. If cross-platform JavaScript suits your app, take it — it is a legitimate choice. If you wanted a native app, the question is still open.
School two: keep Xcode, fence the agent off. Give the agent business logic, view models, services, unit tests and Swift packages. Reserve UI verification, target configuration and deployment for yourself. Register new files by dragging them into Xcode manually, or move project generation to XcodeGen and a project.yml so nobody hand-edits pbxproj at all. Bridge builds through something like XcodeBuildMCP so errors return structured rather than as raw logs. Keep a CLAUDE.md at the root and per-feature, write a PRD before each feature, and break work into task files so the plan survives a /clear.
This also works, and it produces good native apps. It is a real amount of scaffolding to build and maintain yourself, and every project starts from scratch.
Where those workarounds converge
Read enough of these guides and the same three ingredients appear in all of them: a spec written before the code, an architecture the agent is held to, and a structured loop between the agent and Xcode.
That convergence is not a coincidence, and it is not a marketing claim — the people who wrote those guides had no product to sell. They arrived there because those are the three things that a terminal agent pointed at an Xcode project is missing.
That is also, precisely, the product Modaal sells. We would rather say that plainly than pretend we invented the insight.
What Modaal does with the same agent
Modaal is a macOS app that sits between you, your coding agent, and Xcode. You keep Claude Code. It does not replace your agent — it orchestrates it.
Your agent, your subscription. Connect Claude Code and authenticate with the Claude plan you already pay for. Modaal adds no per-token or API charge. Twelve others are supported too — Codex, Cursor, OpenCode, Gemini CLI, GitHub Copilot, Auggie, Cline, Goose, Kilo Code, Mistral Vibe, OpenHands and Qwen Code — and you can switch between them — useful when you hit a usage limit mid-feature. Every new project also starts on a built-in free preview agent, so you can try it before connecting anything.
The project file is handled, not hand-edited. Modaal scaffolds targets, modules, build settings, app icon and a passing test suite, and manages project structure as part of the build. Neither you nor your agent is editing pbxproj by hand at midnight.
A real build-and-fix loop. After each step, Modaal builds through Xcode, reads the result, and feeds failures back to the agent to fix — then builds again. You are not the message bus between a terminal and a build log any more.
An architecture that outlives the context window. New projects scaffold to a chosen template. The production template lays down a RIBs module tree: explicit modules, protocol boundaries between them, and a navigation tree that is explicit in the router hierarchy. The quick-prototype template uses MVVM, deliberately smaller, with view models that stay unit-testable. Because the structure is on disk rather than in the conversation, a /clear does not lose it.
One thing to decide up front: migrating from MVVM to RIBs is a full rewrite, not a refactor. Pick the production template if the app might become real.
PRD before code, when you want it. Turn Plan on and the agent produces a structured feature spec without writing anything. For a new project it goes further — researches the architectural approach, confirms the key decisions with you, writes a PRD covering what the app does and what it is explicitly deferring, then scaffolds and writes the first feature spec. Turn Plan off and it implements against that spec. That loop is what "PRD-driven" means here, and it exists because it is the thing that stops feature ten contradicting feature one.
What Modaal does not do
It needs a Mac. Modaal builds through Xcode, and Xcode is macOS-only. You will want Xcode 26 or newer, roughly 50 GB free for Xcode and simulators, and Apple silicon if you care about build times. If you are on Windows, this is not the tool — a cloud builder like Rork is.
It does not submit to the App Store for you. You publish through Xcode and App Store Connect with your own Apple Developer account. Some competitors run managed submission and it is genuinely convenient; this is not that.
It does not replace your agent, or your judgement. The Swift is still written by the model you connected. Modaal changes the structure it writes into and closes the loop around it. It does not make an agent understand your product better than you do.
If you would rather do it yourself
Entirely reasonable, and the ingredients are public. A working setup looks roughly like this:
- Take `pbxproj` off the table. Adopt XcodeGen or Tuist with a declarative project spec, so the project file is generated rather than edited. This single change removes the worst failure mode.
- Bridge the build. Wire up XcodeBuildMCP or an equivalent so the agent gets structured build results and simulator control instead of pasted logs.
- Write the architecture down. A root
CLAUDE.mdplus per-feature files, stating the module boundaries and where things go. Specificity beats length. - Spec before code. A short PRD per feature, kept in
docs/, so a context clear does not erase the plan. - Manage context deliberately.
/compactas the window fills,/clearbetween unrelated tasks — and re-anchor the agent on the architecture file afterwards. - Accept the manual parts. Previews, simulator interaction, signing and device deployment stay yours.
That setup works. Modaal is what it looks like when someone has already built and maintained it for you.
Frequently asked questions
It can write the Swift. It cannot register files in an Xcode target, render SwiftUI Previews, interact with the simulator, or handle code signing and device deployment — those run through Xcode and an Apple Developer account. In practice you get good code and then do the integration work by hand, unless you build or adopt tooling that bridges the gap.
Almost certainly target membership. Writing a file to disk does not add it to the Xcode target — that lives in project.pbxproj, which agents should not edit. Fix it by dragging the file into the target in Xcode, or remove the problem entirely by generating the project with XcodeGen or Tuist from a declarative spec.
The consensus among developers doing this work is to never let an agent edit project.pbxproj, on the grounds that a single misplaced character can corrupt the file and leave you with a project Xcode will not open. The underlying fragility is not an AI problem — Tuist describes pbxproj as a file that was never designed to be edited directly, and tools like XcodeGen exist specifically so humans do not touch it either. There is no reliable statistic on how often it happens; treat it as a rule of thumb with real consequences rather than a measured risk.
No. Modaal orchestrates the agent you already use. You connect Claude Code and authenticate with your existing Claude subscription, and Modaal handles project structure, the build-and-fix loop through Xcode, and the architecture the agent writes into. You can switch to Codex, Gemini, Copilot, Cursor or others at any time.
No. Modaal has a free plan with unlimited prompts, and Pro is a flat €9 per month billed annually (€15 monthly). Either way it adds no per-token or API cost — inference runs on the AI subscription you already have. If you have no AI subscription, Modaal includes a free preview agent to start with.
Yes. Thirteen agents are supported: Claude Code, Codex, Cursor, OpenCode, Gemini CLI, GitHub Copilot, Auggie, Cline, Goose, Kilo Code, Mistral Vibe, OpenHands and Qwen Code. You install the agent’s CLI, authenticate with your existing credentials, and switch whenever you like.
Yes, and that is deliberate. Modaal builds and runs your app through Xcode, which is what makes the output a real native project rather than something approximating one. You need Xcode 26 or newer and around 50 GB of free space. You will not spend much time in it, but it has to be there.
Nothing. The project is a standard Xcode project on your own disk, and it was from the first build — there is no export step because there is nothing to export from. Open it in Xcode, keep building by hand, point your own CI at it, hand it to someone else.
Keep your agent. Close the loop around it.
Free, no countdown, no prompt cap. Connect Claude Code and build against a real Xcode project.