Skip to main content

Iframe Integration

run-cloud ios create returns a signed url that can be opened directly or embedded in an iframe.
<iframe
  title="run.cloud iOS simulator"
  src={session.url}
  allow="clipboard-read; clipboard-write"
  style={{ width: 390, height: 844, border: 0 }}
/>
Treat the URL as a secret. It is scoped to one user and one run.cloud session.

Session timeout

Run.cloud sessions do not auto-close on inactivity unless requested:
run-cloud ios create --inactivity-timeout 60s --json
run-cloud ios create --inactivity-timeout none --json
When enabled, the inactivity clock starts after the simulator is ready. Pointer, touch, wheel, and keyboard input inside the iframe reset the timer. Watching the stream without interacting does not reset it. The last 10 seconds are shown as an overlay inside the iframe. When the timer expires, the iOS simulator releases the lease and the iframe posts:
{
  type: "ios-simulator:session-ended",
  device: string,
  reason: "inactive-timeout"
}

Parent window messages

Listen for messages from the iframe and verify event.source before acting on them.
const iframe = document.querySelector<HTMLIFrameElement>("#run-cloud-ios");

window.addEventListener("message", (event) => {
  if (event.source !== iframe?.contentWindow) return;
  const data = event.data;
  if (!data || typeof data !== "object") return;

  if (data.type === "ios-simulator:status") {
    console.log({
      streaming: data.streaming === true,
      appLaunched: data.appLaunched === true,
      reactNative: data.reactNative === true,
      bundleId: typeof data.bundleId === "string" ? data.bundleId : null,
    });
  }

  if (data.type === "ios-simulator:auth-error") {
    // The signed URL or iframe cookie is invalid or expired.
  }

  if (
    data.type === "ios-simulator:session-ended" ||
    data.type === "ios-simulator:session-restart-requested"
  ) {
    // Hide the old iframe and create a fresh run.cloud session.
  }
});

Message reference

MessageDirectionMeaning
ios-simulator:statusiframe to parentStream and app readiness changed.
ios-simulator:auth-erroriframe to parentThe embed token or session cookie was rejected.
ios-simulator:session-endediframe to parentThe session ended, usually due to inactivity or explicit release.
ios-simulator:session-restart-requestediframe to parentUser clicked Start app again; create a new run.cloud session.
ios-simulator:commandparent to iframeOptional command channel for supported controls.

Commands

Send commands with postMessage to the iframe content window:
iframe.contentWindow?.postMessage(
  { type: "ios-simulator:command", command: "reload" },
  "*",
);
Supported commands:
CommandEffect
reloadReload the React Native app.
homePress the simulator Home button.
rotateRotate the simulator. Pass direction: "left" or "right".
screenshotAsk the iframe to take a screenshot.
toggleAccessibilityToggle the accessibility inspector.
For control outside the browser, prefer CLI/API commands such as run-cloud ios open-url.