runcloud xcode build uploads a bounded snapshot of your source, builds it on
macOS, streams a sanitized xcodebuild log, and keeps the build record and
artifact available through the authenticated API. You do not need an active
simulator session.
Build a simulator app
Authenticate once, then run the command from a directory that contains an Xcode project or workspace:iphonesimulator. Native projects default to Debug;
detected React Native and Expo projects default to Release. If --scheme is
omitted, run.cloud uses the first shared scheme reported by the selected
workspace or project.
The output for an iOS simulator build is a gzip-compressed .app bundle. An
unsigned iphoneos build returns an app bundle, signed iOS builds return an
IPA, and watchOS builds return a compressed watch app.
Observe a detached build
Every accepted build has a durable ID. A detached client can reconnect, inspect state, resume reading the sanitized log, download an artifact, or cancel work:uploading, queued, running, succeeded, failed,
and cancelled. Terminal records include an exit code. Failed records also
include the stage, a specific reason extracted from the retained log, a failure
category, and a suggested next action. The artifact endpoint requires the same
organization access as the build; any storage redirect it returns is short
lived.
Use --idempotency-key in CI. Repeating the same key with the same source and
options returns the original build. Reusing it with different input fails with
409 instead of starting ambiguous duplicate work.
Reuse the output as an Asset
Every verified build output has an immutable, organization-scoped Asset ID inartifact.assetId. The same output can be installed into several sessions
without downloading and uploading it again:
mobile launch is one retry-safe operation: it selects the output, creates a
session, installs the app, and returns the launch ID, session ID, current state,
or retained failure. Repeating the same key and request returns the same
operation and never allocates a second simulator. A changed request with the
same key returns 409.
The Asset ID is the authorization boundary, not a storage URL. run.cloud checks
that the build output and target session belong to the same organization, then
creates a short-lived, read-only download for the selected simulator host. The
Mac that built the app and the host running the simulator do not exchange
credentials and do not presign for each other.
Rebuild only JavaScript
An Expo simulator build records a fingerprint of its native shell. When only JavaScript and bundled assets change, reuse that shell:iphonesimulator outputs. run.cloud installs dependencies,
calculates the current native fingerprint, and stops with a compatibility
failure when native inputs differ from the basis. That failure includes the
action to run a full build and use the new build as the next basis. The original
Asset is never modified; the rebundle creates a new Asset whose
parentAssetId identifies its native-shell basis.
Replay build events
Organization event sequences are ordered and replayable. SavenextCursor
only after processing the returned page:
--build-id to select one build. Events contain product-visible state,
stage, output Asset metadata, and sanitized failure details without requiring
access to the build worker.
Delegate one launch safely
An organization member can mint an opaque capability for a worker that should read and launch one output, without sharing the organization API key:capability create; list commands
show metadata, never the token.
Project preparation
The builder supports these source preparation modes:- Existing
.xcworkspaceor.xcodeproj: select one with--workspaceor--project. They are mutually exclusive. - XcodeGen: pass
--xcodegen-spec, plus optional--xcodegen-projectand--xcodegen-project-rootpaths. - React Native or Expo: package installation and native project generation are
detected from
package.json; select a monorepo app with--expo-app-dir. - Git-dependent generation: pass
--git-initto initialize the uploaded snapshot before project preparation.
--dev-server-url preserves the launch URL in
the build request. Because this service does not pair a simulator, it does not
open the URL automatically. It is rejected for Release builds.
Dependency preparation recognizes npm, pnpm, Yarn, CocoaPods, Swift Package
Manager through Xcode, and Carthage project files. Source packaging omits VCS
data and common Xcode/dependency output directories. The root .gitignore is
honored, while .xcconfig files are preserved.
Use repeatable source controls when the defaults do not fit:
--ignore and --include accept regular expressions. Additional destinations
must stay inside the uploaded workspace or ~/; symbolic links are rejected.
The compressed source limit is 100 MiB.
Build settings
Use a repeatable--build-setting KEY=VALUE for
SWIFT_ACTIVE_COMPILATION_CONDITIONS or an APP_CONFIG_ key:
APP_CONFIG_ keys are stored and logged as redacted secret inputs.
Arbitrary Xcode settings are rejected so a request cannot alter the runner or
signing environment.
Signing and App Store upload
For manual signing, provide one PKCS#12 certificate and one or more provisioning profiles. Device builds are selected automatically when signing is configured:app-store-connect, release-testing, or
debugging as its export method:
--auto-build-number finds the highest numeric build number for the app in App
Store Connect and uses the next value. An App Store upload happens after the
IPA is retained by run.cloud, so a failed upload can still leave a downloadable
artifact. Certificate material, private keys, passwords, profiles, and signed
upload URLs are not returned in build records.
Use --upload <filename> to choose the retained artifact filename, or
--signed-upload-url <https-url> to also upload the output to your own
short-lived destination. Those options are mutually exclusive.
TypeScript
The public SDK packages the same source snapshot and follows the same lifecycle:cloud.xcode.rebundle(process.cwd(), completed.id, options). Consume ordered
events with cloud.xcode.events({ after: cursor }) and persist the returned
nextCursor after handling the page.
See the TypeScript SDK reference for all option
and response types.
Intentional differences
The service intentionally keeps the following boundaries around remote builds:- Each request uses an immutable uploaded snapshot. It does not expose a persistent Mac instance, incremental source sync, DerivedData reuse, or a customer-managed cache toggle.
- Native-shell reuse is limited to compatible Expo Release simulator builds. Native changes require a full build; device signing and App Store uploads do not use the rebundle path.
- A successful build remains independent of simulator capacity. Use the
explicit, idempotent
mobile launchoperation when a simulator should be created and the output installed. --no-waitand--detachuse the durable build ID for reconnection. There is no per-build callback URL option. Consumers replay ordered organization events instead of registering an outbound webhook.- Live command, stdout, and stderr events are combined into one ordered, sanitized log that can be resumed by byte offset.
- Every verified output is an immutable organization Asset.
--uploadchooses its filename; it does not return a durable bearer download URL or make a build output independently deletable. - Source symlinks are rejected instead of dereferenced or recreated.
--asc-wait-timeoutis accepted for command compatibility, but run.cloud reports successful upload acceptance and leaves App Store processing asynchronous.