NoMacSign in
← Blog

Why cloud coding agents can't build your iOS app

Hosted coding agents run in Linux sandboxes, so xcodebuild is missing. How to hand the Apple steps to a Mac the agent can reach over HTTPS.

· 7 min read

Need a Mac for this? NoMac gives your agent full macOS with Xcode, from $9.99 a month, billed by the second. Start now →


You give a cloud coding agent an iOS task. It reads the Swift, writes a clean change, and then tries to prove it compiles:

$ xcodebuild -scheme MyApp build
bash: xcodebuild: command not found

The agent is not broken. Hosted coding agents run in Linux sandboxes, and Xcode only runs on macOS. The agent can edit Swift all day, but it cannot compile SwiftUI, run XCTest, boot a simulator or sign an archive. Without those, “done” means “looks right,” which is not the same thing.

The fix is not a different agent. Keep the agent where it is and give it a Mac it can reach over HTTPS. The code stays in the sandbox; only the Apple steps travel.

What works in a Linux sandbox and what does not

  • ·Works: reading and editing Swift, Git, portable Swift packages with the Linux toolchain, tests for pure logic, JSON and plist edits, most scripting.
  • ·Does not work: anything that imports SwiftUI or UIKit, Xcode project builds, XCTest for app targets, the iOS simulator, code signing, archives, uploads to App Store Connect.

See what actually needs a Mac for the full list. The short version: anything Apple-flavoured beyond plain Swift.

Three ways to give a cloud agent a Mac

1. Push and let CI answer

The agent commits, pushes and waits for a macOS CI job. This works and needs no new tools, but each attempt is a commit and a queue. An agent fixing a stubborn build error can spend an hour producing a pile of “try again” commits. It is best as a final check, not as the development loop.

2. A hosted MCP server that runs commands on a Mac

The agent calls tools over HTTPS: start a Mac, run a command, read its output, stop. No SSH client or key is needed inside the sandbox, which matters because many sandboxes restrict outbound connections to web traffic. NoMac exposes this at https://mcp.nomac.app/mcp with a bearer API key.

3. SSH to a Mac, if the sandbox allows it

Where outbound SSH is allowed, the agent can install the NoMac CLI, run nomac start, nomac sync . and nomac ssh -- xcodebuild .... This is the most flexible option for long builds.

The loop, over MCP

With the hosted MCP server connected, the tools an agent uses are few and predictable:

get_mac_credits   → check this week's remaining hours
start_mac         → request a Mac with a stable request_key
get_mac_session   → poll until ready (about a minute)
exec_mac          → start a job, e.g. ["/bin/bash","-lc","xcodebuild ..."]
get_mac_job       → check whether it finished
read_mac_output   → read stdout and stderr from a cursor
stop_mac          → delete the Mac when done

Over MCP, source gets onto the Mac the way it gets onto any fresh machine: the agent pushes a branch and the first job clones it. For a private repository, use a short-lived, read-only token scoped to that one repository; the VM and everything on it is deleted at stop. If the sandbox allows SSH, the CLI's nomac sync . uploads the working tree directly instead.

A prompt that works

You have NoMac MCP tools for a remote macOS machine with Xcode.
1. Check credits, then start one Mac with request_key "fix-build-001".
2. Clone this branch on the Mac and run:
   xcodebuild -scheme MyApp -destination 'generic/platform=iOS Simulator' build
3. Read the full error output. Fix the source here, push, pull on the Mac, rebuild.
4. Repeat until the build succeeds, then run the unit tests.
5. Stop the Mac and confirm cleanup before you finish.
Reuse the same request_key if a response is lost. Never start a second Mac.

Things that trip agents up

  • ·Network allowlists. Some hosted sandboxes block outbound traffic by default. The NoMac endpoints must be allowed. We do not assume every sandbox can reach them, so check your environment's network settings first.
  • ·Timeouts. Managed commands default to 300 seconds and cap at 600. A first simulator boot takes about 90 seconds; a large first build can take longer than ten minutes, so split it or use SSH.
  • ·Retries. If a response is lost, retry with the same request key and arguments. A new key means a new job.
  • ·Forgetting to stop. Idle and session limits protect you, but a finished agent should always call stop_mac and wait for cleanup.

Setup for Claude Code specifically is in give Claude Code a Mac in five minutes. The machine-readable version of all of this is at nomac.app/llms.txt.

Give your agent a Mac in a minute.

Full macOS with Xcode and root, over MCP, CLI, API or SSH. Billed by the second, deleted when you stop. No Apple account needed to start.

Get started for $9.99

7-day money-back guarantee on your first purchase. Cancel anytime.

Connect your agent →