How to set up Claude Code and Codex CLI for iOS development

Claude Code or Codex can build your iOS app. They call xcodebuild, pass the scheme, pick a simulator, compile. On a good run, it works.

Then it doesn’t. xcodebuild dumps 2,000 lines into one stream. The agent burns context looking for the error on line 847, misreads a linker error as a warning, retries with the wrong flag, grabs a simctl UDID that doesn’t exist on this machine. Two bad iterations and you’re back in the terminal doing it yourself.

The raw tools work often enough to be promising. They fail often enough to be unusable for autonomous work.

Where it breaks down

Apple’s CLI surface is four tools with nothing in common.

xcodebuild mixes errors, warnings, and progress into unstructured text. The agent parses this with regex that breaks silently between Xcode versions. xcrun simctl needs UDIDs that change per machine. xcrun devicectl has a completely different syntax. log stream shows every process on the system.

Orchestrating all four is where it falls apart. Not on the first build. On the fifth, when the simulator didn’t boot, the UDID was stale, and the agent is three tool calls deep into a dead end.

And none of them give the agent eyes. Claude Code/Codex can’t see the simulator screen, tap a button, or verify that the login form appeared. They write UI code blind and hope you’ll check.

There are open source wrappers that try to solve this. They expose Apple’s tools as 60 to 76 individual MCP operations, run on Node.js with a background daemon, and route every call through the MCP protocol before it reaches xcodebuild. Some ship with telemetry enabled by default. The approach works for experimentation. For production development where you need reliability, privacy, and a tool you can leave running unattended, the overhead adds up.

What you need is a professional tool: one interface, structured output, no telemetry, no runtime dependencies, and the ability to see what’s on screen.

The setup

FlowDeck is a native Swift CLI built for exactly this. No Node.js. No MCP server. No daemon. No telemetry. Eight commands, structured JSON on everything, and built-in UI automation. Here’s how to wire it to Claude Code/Codex.

Install.

curl -sSL https://flowdeck.studio/install.sh | sh
flowdeck license activate [YOUR_LICENSE_KEY]

Activate with the license key from your purchase email.

Install the skill pack.

flowdeck -i

Press A, select Install Skills, choose Claude Code, then Global or Project. This drops a SKILL.md that Claude Code reads on startup. Every command, every workflow pattern, one rule: use FlowDeck, not xcodebuild. The skill gives Claude Code full project context. No additional configuration.

FlowDeck ships skill packs for Claude Code, Codex CLI, OpenCode, and Gemini CLI. The CLI is identical. The skill file is what changes. Claude Code reads SKILL.md. Codex reads AGENTS.md. Both get the same commands, the same workflow patterns, the same rule: use FlowDeck, not xcodebuild. If you use multiple agents on the same project, install both. They don’t conflict.

Two steps. Under two minutes.

What the agent loop looks like

Claude Code/Codex discover the project, build, launch, observe. The whole cycle.

flowdeck context --json
flowdeck build -w App.xcworkspace -s MyApp -S "iPhone 16"
flowdeck run -w App.xcworkspace -s MyApp -S "iPhone 16"

Build output is NDJSON. Errors are typed events with file paths and line numbers. Build fails, agent reads the error, fixes the code, rebuilds. No regex. No guessing. No 2,000 lines of noise.

Building and running is table stakes. The part that changes the workflow is visual verification.

flowdeck ui simulator screen --json

Screenshot and full accessibility tree, returned as JSON. Claude Code/Codex see the UI. Find elements by label. Decide what to do next.

flowdeck ui simulator tap "Log In"
flowdeck ui simulator type "user@test.com"
flowdeck ui simulator assert visible "Welcome"

Tap, type, assert, scroll, swipe. The agent drives the app the way a QA engineer would, then verifies the result before moving on.

flowdeck apps
flowdeck logs <app-id>

Runtime logs. print() and OSLog output streamed from the running app. The agent sees behavior, not just compiler output.

Build, launch, screenshot, verify. Under 60 seconds. No human. No Xcode.

Common first-week workflows

Once the setup runs end to end, three workflows tend to dominate the first week of using FlowDeck with an AI agent.

1. Build, test, and fix in one loop. Give the agent a failing test and let it iterate. The pattern: flowdeck test --only LoginTests/testValidLogin, read the structured failure, fix the source, rerun. Tests don’t require a full build first; AST-based discovery returns instantly.

2. UI verification on a new screen. After the agent writes a new view, have it screenshot the simulator, read the accessibility tree, and assert what’s on screen. flowdeck ui simulator screen --json followed by flowdeck ui simulator assert visible "Welcome". This catches layout regressions, missing accessibility labels, and broken navigation before they hit production.

3. Debugging a runtime issue from logs alone. Many bugs only show up after the app launches. flowdeck run then flowdeck logs <app-id> lets the agent reproduce, observe live OSLog output, and reason about state without you ever opening Console.app. Pair with flowdeck ui simulator tap to drive the app to the broken state automatically.

These three workflows replace most of what an iOS engineer used to do in Xcode and Console.app during day-to-day development. The agent runs them; you review the result.

What this is and isn’t

FlowDeck is the build and observation layer. Claude Code/Codex write the code. FlowDeck handles everything between writing code and knowing whether it worked.

Code signing and provisioning still need Xcode’s one-time setup. After that, Xcode stays closed.

Native Swift. Runs locally. No data leaves your machine. No telemetry, no usage tracking, no background analytics. License validation is the only network call FlowDeck makes.

Works with Claude Code, Codex CLI, OpenCode, and Gemini CLI.

Q&A

Do I need to modify my Xcode project to use Claude Code?

No. Claude Code reads your project as-is.

FlowDeck calls xcodebuild against your existing workspace, scheme, and signing setup. Nothing in your .xcodeproj or Package.swift changes.

Can I use Claude Code and Codex CLI on the same iOS project?

Yes. They don’t conflict.

Claude Code reads SKILL.md. Codex CLI reads AGENTS.md. The FlowDeck skill pack installs both side by side.

The CLI commands are identical, so each agent uses the same underlying tooling.

How do I know if my Claude Code iOS setup is working?

Run a smoke test: ask Claude Code to show you the current iOS project context.

It should call flowdeck context --json and respond with the parsed workspace, schemes, and simulators.

If it falls back to xcodebuild -list or asks you for UDIDs, the skill pack isn’t loaded. Restart Claude Code after running flowdeck -i and selecting Install Skills.

Why does my AI agent ignore the FlowDeck commands?

Most often the skill file isn’t loaded into the agent’s context.

Skill packs install per-project (.claude/skills/) or globally (~/.claude/skills/). If you installed globally but opened the project before restarting the agent, the skill won’t be picked up.

Restart the agent and verify it sees the skill.

Do I still need Xcode installed?

Yes. FlowDeck calls xcodebuild under the hood and requires the Xcode toolchain.

macOS 13+ and Xcode 15+ are supported. Xcode 16+ is recommended.

You won’t open the Xcode app, but the install is required for the build toolchain, signing, and provisioning.

Troubleshooting

Why does the agent ignore `flowdeck` and fall back to `xcodebuild`?

The skill file isn’t loaded into the agent’s context.

Restart Claude Code or Codex after running flowdeck -i and selecting Install Skills. Skill packs are picked up on session start, not mid-session.

Why does `flowdeck context` return "No workspace found"?

You’re not in a directory that contains an .xcodeproj or .xcworkspace.

cd into the project root before running the command. FlowDeck doesn’t search upward.

Why isn't a specific simulator available?

Run flowdeck simulator list --json to see what’s actually installed.

Names are matched case-insensitively but must include the full device name (iPhone 16 Pro, not Pro).

If the runtime is missing, install it through Xcode: Settings → Platforms.

Why does the build succeed but the app fail to launch?

A previous run is still registered.

flowdeck apps lists running apps. flowdeck stop <app-id> clears it before relaunching.

FlowDeck refuses to silently replace a running app to avoid stealing focus from the user.

Why don't logs show anything?

The app launched, but the logging filter is off by default for non-debug builds.

Make sure the build configuration is Debug, or rebuild with --configuration Debug.

What does "trial expired" mean and how do I fix it?

Either start the trial (flowdeck -iActivate Trial) or set FLOWDECK_LICENSE_KEY in your shell environment for CI runs.