eas-simulator
FreeNo executable scriptsNot checkedRun and control a user's app on a remote iOS/Android simulator hosted on EAS cloud. Always read before executing any `eas simulator:*` commands — it has the cur
About this skill
EAS Simulator
EAS Simulator runs a remote iOS simulator or Android emulator on EAS infrastructure that you drive from your machine — from the CLI, from an AI agent (via agent-device), and from a browser preview. It's the unlock for environments that can't run a simulator locally (Linux boxes, cloud/background agents like Cursor Cloud), and for letting an agent verify a change on a real device instead of only reasoning about code.
The simulator:* commands are experimental and hidden, and need a recent eas-cli (≥ 20.3.0 as of writing) — which is why this skill runs everything via npx --yes eas-cli@latest. Flags and verbs may change; if a command fails, <cmd> --help is authoritative.
When to use
The frontmatter description carries the trigger phrases. In short: use this to get a user's app onto a cloud simulator and interact with it — especially from a Mac-less or cloud/sandbox agent. Not for local sims (expo run:ios, Xcode, Android Studio), store builds/signing (that's EAS Build), or physical devices. For the macOS case, see Cloud vs local next.
Cloud vs local: decide this first
- Non-macOS (Linux / CI / cloud sandbox like Cursor Cloud, detect via
uname -s≠Darwin): the only way to get a sim — just proceed. - macOS: local sims exist and a cloud session costs money + latency, so ask first ("a remote cloud sim — to share a live preview, offload, or test an iOS version you lack — or just run locally?") unless the user explicitly said cloud/remote/shareable.
- Always honor an explicit choice; for "run it locally" hand off to
expo run:ios/ Xcode.
# Programmatic detection — run this to decide before doing anything else:
if [ "$(uname -s)" != "Darwin" ] || ! xcrun --find simctl &>/dev/null 2>&1; then
echo "no local sim — proceed with EAS Simulator"
else
echo "local sim available — ask the user (cloud or local?)"
fi
Prerequisites
- Run every
eascommand vianpx --yes eas-cli@latest …— guarantees a CLI new enough to havesimulator:*(a globaleasis often too old), and--yesskips npx's prompt. (Bareeasis fine ifeas --versionis current.) - Authenticated. Interactive machine →
npx --yes eas-cli@latest login. Cloud sandbox / CI / headless agent has no browser login — setEXPO_TOKEN(expo.dev → Account → Access Tokens) in the env instead. Verify either way withnpx --yes eas-cli@latest whoami. - Run from an Expo project directory. A fresh app needs one-time setup:
npx --yes eas-cli@latest initto create/link the project (when there's noprojectId), and setios.bundleIdentifierin app config if it's missing — a freshcreate-expo-appoften has none, andprebuild/eas buildneed it (they prompt or fail without it; e.g.dev.<owner>.<slug>). Read current config withnpx expo config --json(it may live inapp.config.js). The first Mode-C run is slow (native build); later runs reuse it. - A controller to drive the device. This skill uses agent-device (open source, MIT), run on demand via
npx agent-device@latest— nothing globally installed. argent is an alternative (--type argentinsimulator:start); see references/controllers.md. .env.eas-simulatoris written/managed by eas-cli (not this skill): it holds the session id (EAS_SIMULATOR_SESSION_ID) + the daemon URL/token, soget/stop/execdefault to that session (usually omit--id; pass--id <id>to target another). It carries a token → keep it gitignored (eas-cli marks it "do not commit" but may not add the ignore rule, and a fresh app's.gitignorewon't cover it — add.env.eas-simulatorif missing).--max-duration-minutesis paid-plan only; otherwise a default applies.
The core loop (always the same)
A session is: start → (install your app) → drive → stop. eas-cli owns the session; the device verbs (open/tap/screenshot) come from the controller, which npx --yes eas-cli@latest simulator:exec runs for you with the session's connection env loaded.
# 1. Start a session (boots the remote sim + agent-device daemon; writes .env.eas-simulator).
printf '# managed by eas-cli\n' > .env.eas-simulator # clear any stale session first
npx --yes eas-cli@latest simulator:start --platform ios --type agent-device --non-interactive
# Then confirm it's live: simulator:get --json → status IN_PROGRESS (bounded poll in run-your-app.md).
# 2. Drive it through `exec` (loads the session env, then runs the command you give it).
# agent-device runs on demand via npx — nothing installed globally.
npx --yes eas-cli@latest simulator:exec npx agent-device@latest open <app-or-url> --platform ios
npx --yes eas-cli@latest simulator:exec npx agent-device@latest snapshot -i # interactive UI tree → @e1, @e2 refs
npx --yes eas-cli@latest simulator:exec npx agent-device@latest press @e2 # tap a ref (NOTE: 'press', not 'tap')
npx --yes eas-cli@latest simulator:exec npx agent-device@latest screenshot ./shot.png
# 3. Stop (ends billing; tears down the VM) and reset the dotenv. Omit --id to target the dotenv session.
npx --yes eas-cli@latest simulator:stop
printf '# managed by eas-cli\n' > .env.eas-simulator
To watch it live, hand the user the webPreviewUrl that start prints (an --type agent-device iOS session runs serve-sim alongside the daemon, so it emits one — agent control and a browser preview in one session; Android has no preview, and --type serve-sim is preview-only). This URL is for the user's browser — you cannot open it for them, and it must never touch the sim:
- "Open it here" (Cursor/VS Code) → print the URL on its own line and tell the user to open Simple Browser (
Cmd/Ctrl+Shift+P→ "Simple Browser: Show") and paste it. Then stop: do not shell out to a system browser or a Cursor/VS Code URL handler, and do not ask "did a tab appear?" — you can't confirm it, the handoff is done. - Never
openthewebPreviewUrlon the sim. It's a browser preview, not a deep link and not anagent-device openargument; routing it to the device renders a browser-in-a-browser (a real past failure). - Headless agent (no display) → just return the URL as the deliverable.
- Keeping it alive for the user to drive → bound it: start with
--max-duration-minutes Nso it auto-stops; tell them it bills until stopped and when it auto-stops; offer to reopen/extend when it ends. (This is the one case where "stop right away" doesn't apply; one-shotscreenshot/getruns still stop immediately.)
start also prints a job-run URL.
Commands at a glance
| Command | Purpose |
|---|---|
npx --yes eas-cli@latest simulator:start --platform ios|android [--type agent-device|argent|serve-sim] [--package-version X] [--max-duration-minutes N] [--non-interactive] [--json] |
Create a session; boot the sim + controller; write .env.eas-simulator; print webPreviewUrl + job-run URL |
npx --yes eas-cli@latest simulator:exec <cmd> [args…] |
Load .env.eas-simulator, then run <cmd> with that env. The bridge to the controller. |
npx --yes eas-cli@latest simulator:get [--id] [--json] |
Session status + connection details. Use this to confirm readiness (see Operating principles). |
npx --yes eas-cli@latest simulator:list [--status …] [--type …] [--platform …] |
List an app's sessions |
npx --yes eas-cli@latest simulator:stop [--id] |
Stop a session (idempotent) |
Running the user's app — pick a mode
The remote sim boots blank — no Expo Go, no apps. Install a build, then drive it — but match the build type to the goal first (the box below); that's where live-session runs derail. Full sequences: references/run-your-app.md — read before running a mode.
Match the build to the goal before installing anything — this is where live-session runs derail. Two traps, same root
Install eas-simulator in Claude Code & Claude Desktop
Sign up to install this skill
Create a free account to reveal the install command and save the skill to your library.
- Reveal the one-line install command
- Save skills to your synced library
- Get notified when skills update
Allowed tools
Tools this skill is permitted to call.
Bash(npx *eas-cli@*)Bash(npx *agent-device@*)Bash(npx expo *)Bash(eas *)Bash(expo *)Bash(xcodebuild*)Bash(pod*)Bundled files
FAQ
What does the eas-simulator skill do?
Run and control a user's app on a remote iOS/Android simulator hosted on EAS cloud. Always read before executing any `eas simulator:*` commands — it has the current syntax for this experimental API. Use whenever the user needs a simulator they can't run locally — 'run my app on a cloud simulator', 'use eas simulator to run/install/screenshot my app', 'I'm on Linux/Cursor and need an iOS device', 'no sim on this box / headless CI', 'let an agent click through my app and screenshot it', 'test my dev build on a remote sim with live reload', 'stream a sim's screen to my browser' — even when they don't say 'EAS Simulator' or 'cloud'. On a host WITHOUT a local simulator (Linux, CI, cloud sandbox) it's the default — just use it; on macOS, do NOT auto-trigger for a plain 'run on the simulator' — use it only for a cloud/remote/shareable sim, an iOS version they lack, or an agent-driven session. NOT for local sims (expo run:ios, Xcode, Android Studio), EAS Build/Update, web preview, or physical devices.
How do I install the eas-simulator skill?
Copy the skill folder into ~/.claude/skills (the Claude Code tab above does this in one command), or install it as a plugin.
Does the eas-simulator skill run scripts?
No, this skill is instructions only (SKILL.md) with no executable scripts.
Related skills
MCP Builder
Scaffold a Model Context Protocol server
by AnthropicCommit Helper
Write clean, conventional git commit messages
by Unylyalgorithmic-art
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generati
by Anthropicclaude-api
|-
by Anthropic