← Blog

Give Codex an iOS Simulator without a Mac

OpenAI's Build iOS Apps plugin drives the Simulator through XcodeBuildMCP, which needs macOS and Xcode. On Windows, Linux or in Codex cloud, give Codex a cloud iPhone Simulator over MCP instead.

· 6 min read

Need an iPhone for this? NoMac Simulator gives your agent a cloud iPhone in seconds for $0.90 an hour, billed per minute. See NoMac Simulator →


OpenAI's Debug in iOS simulator use case has Codex own the whole loop: pick a scheme and a simulator, launch the app, read the UI tree, tap, type and swipe, capture logs and screenshots, attach LLDB, fix the bug and run the same path again. It does that through the Build iOS Apps plugin, whose .mcp.json starts XcodeBuildMCP with npx -y xcodebuildmcp@latest mcp on the machine Codex runs on.

XcodeBuildMCP, now MobileBuildMCP, lists macOS 14.5 or later and Xcode 16 or later as its requirements. So the plugin's Simulator loop runs on a Mac with Xcode. With Codex on Windows or Linux, in a dev container or in a Codex cloud task, there is no Simulator for it to drive.

The same loop over the network: a NoMac phone is an iPhone 17 Pro Simulator on iOS 27, with Xcode 27.1 building your app on the same cloud Mac. Codex drives it with MCP tools from any OS, and you watch it in a browser. $0.90 an hour, billed per minute, with no subscription.

The plugin and a cloud phone, side by side

Build iOS Apps pluginNoMac phone
SimulatorOn your Mac, with XcodeOn a cloud Mac, with Xcode 27.1
Build and launchXcodeBuildMCPphone_app_run, from git, a local folder or an upload
Read the screenAccessibility hierarchy with coordinatesphone_ui_look: one line per element, with label, #id and position
Tap and typeBy label, ID or coordinatesphone_ui_act: steps by #id, label or point
LogsSimulator logsphone_app_logs, with crash reports
DebuggerLLDB: breakpoints, stack frames, variablesNone. LLDB needs a NoMac Mac
WatchingThe Simulator on your screen, or mirrored into Codex's browserA view link in any browser

If you have a Mac, the plugin is the shorter loop: no network between Codex and the Simulator, and a debugger. The phone is for when the Mac is the part you are missing.

Connect NoMac to Codex

Codex CLI

From the project folder, sign in once and add NoMac's MCP server. It runs from the NoMac CLI, which needs Node 20 or newer.

npx @nomac/cli login
codex mcp add nomac -- npx @nomac/cli mcp
codex mcp list

Because this server runs on your machine, phone_app_run takes local_path and sends the project folder in the same call, only the files the phone does not have yet. To install nothing, add the hosted server instead:

codex mcp add nomac --url https://mcp.nomac.app/mcp
codex mcp login nomac

codex mcp login runs the OAuth sign-in in your browser, and OpenAI's MCP documentation covers --no-browser for a terminal without one. The hosted tools have no local_path: a folder on your machine goes up through phone_upload_link, which answers one POSIX shell command (Linux, WSL, macOS or Git Bash) that packs the folder and sends it.

The IDE extension and the ChatGPT desktop app

OpenAI's documentation says the ChatGPT desktop app, the Codex CLI and the IDE extension share one MCP configuration, ~/.codex/config.toml, so a server added with codex mcp add is already there. To add it in the extension instead, open the gear menu, then MCP servers and Add server. Choose Streamable HTTP with https://mcp.nomac.app/mcp, save, select Restart extension, then Authenticate.

Give phone calls more than 60 seconds

Codex waits 60 seconds for a tool by default (tool_timeout_sec). A phone call that first fetches a large repository can take longer before it answers. The hosted server answers each call within two minutes and hands a longer build back as a job, so 120 is enough:

[mcp_servers.nomac]
url = "https://mcp.nomac.app/mcp"
tool_timeout_sec = 120

With the CLI's server, put the same line in the entry codex mcp add wrote. The first local_path send of a large project can take longer still, so raise it if that first call times out.

Reproduce a bug on the phone

OpenAI's starter prompt for the plugin carries over almost unchanged. Its advice holds here too: prefer accessibility labels or IDs over raw coordinates, and re-read the screen after the layout changes.

Use the NoMac phone tools to reproduce this bug on a cloud iPhone.
Bug: [expected behavior, actual bug, screen or account setup]

- Start a phone and give me links.view.
- Build and run the app with phone_app_run (local_path: this repository).
- Read the screen with phone_ui_look before each action. Tap by #id
  or label, not by coordinates.
- Capture evidence: phone_app_logs around the failure, crashes if it
  crashes, a screenshot for visual state.
- Make the smallest fix, run the same steps again, then phone_tests_run.
- Stop the phone when you are done.

Here is what Codex does with it.

  • ·phone with action start answers once the phone is ready, usually in about 4 seconds, or waits in line for free, up to 5 minutes, when every phone is in use. The answer has links.view to watch the phone and links.control to use it, in any browser with no sign-in.
  • ·phone_app_run builds the Xcode project for the Simulator, installs it, launches it and answers with the first screen as text. Instead of local_path, it takes git, an https link, with ref for a branch or commit; a private repository needs a token kept as a NoMac secret, which request_secret asks you for through a link. Errors come back as file:line. A build past 40 seconds answers with a job for phone_job_status. The workspace is kept between phones, so the next build is incremental.
  • ·phone_ui_look answers one line per element, such as button "Sign In" #signIn @201,350. screenshot adds a JPEG sized to points when Codex needs pixels.
  • ·phone_ui_act takes steps in the same words, such as fill #email test@example.com and tap #signIn, and answers with what changed. A tap that changes nothing is reported, and the first failing step stops the rest.
  • ·phone_app_logs returns what the app printed and logged since launch, with grep, wait_for and crashes. phone_tests_run runs XCTest and XCUITest and reports each failure as file:line; “0 tests ran” counts as an error.
  • ·phone_app_control opens deep links, grants permissions, sets the locale and appearance, and launches the app with arguments such as -Onboarding 3, read as UserDefaults, so a screen your app can open that way needs no tapping.

While Codex works, open the view link. After the phone stops, links.replay shows the session as a video beside every tool call, with typed text left out, for 7 days.

Codex cloud tasks

Codex cloud runs each task in its own VM in OpenAI's cloud. OpenAI's MCP page covers the desktop app, the CLI and the IDE extension, not cloud tasks. A task can still use a phone from its shell, through the free, MIT-licensed simulator-use CLI. One command starts a phone, builds, runs and tests the project, saves a screenshot and a recording, and stops the phone:

npx -y simulator-use cloud run . --tests

It signs in with NOMAC_API_KEY, a key from nomac.app/dash/keys. In the environment settings, add the key under Environment variables, turn on the package manager domains for npx, and add NoMac's domains under Additional allowed domains: nomac.app, *.nomac.app and *.r2.cloudflarestorage.com, where project uploads go.

Not tested end to end: we have not run this command inside Codex cloud. It follows OpenAI's environment settings and NoMac's own network requirements. Codex Cloud iOS builds walks through the same settings for a whole Mac.

What it costs

A phone costs $0.90 an hour, billed per minute from prepaid credit, with a one-minute minimum. The build is included, and waiting in line is free. A 12-minute session costs 18¢. Credit comes in $10 packs, each 11.1 hours of phone time, and never expires. There is no subscription. A phone stops after 10 idle minutes and at 2 hours by default; phone with action extend adds time, up to 8 hours in all.

What a phone cannot do

  • ·Be a physical device. Apple says simulators “don't replicate the performance or features of a physical device.” For hardware, use a TestFlight build on your own iPhone.
  • ·Build Flutter, React Native, Expo or Capacitor apps. phone_app_run builds Xcode projects. Build those Simulator .app bundles with their own tools on a Mac, then install them with phone_app_control action install.
  • ·Run a shell, a debugger, signing or TestFlight. Those need a NoMac Mac (start_mac, on the same server) and, for signing and TestFlight, NoMac App Store at https://mcp.nomac.app/appstore. Codex to TestFlight covers that path.

Tell Codex once, in AGENTS.md

## iOS Simulator
- There is no iOS Simulator here. Use the NoMac phone tools.
- One phone per task. Give me links.view when it starts.
- phone_ui_look before acting; tap by #id or label, not coordinates.
- phone_tests_run before saying a change works.
- Stop the phone (phone, action stop) when you are done.

OpenAI's AGENTS.md guide says Codex reads these files before doing any work, so the rules travel with the repository.

Give your agent an iPhone in seconds.

A cloud iPhone Simulator that builds your Xcode project, reads the screen as text and taps by label, over MCP. You watch it in a browser tab. $0.90 an hour, billed per minute from prepaid credit, with no subscription.

Get started from $10

7-day money-back guarantee on your first purchase. Credit never expires.

Connect your agent →