Limrun Xcode
superset-sh/superset
Build an iOS / Apple app on remote Xcode with lim xcode build instead of local xcodebuild, run project commands with lim xcode run, or run its XCTest suites with lim xcode test, from any environment…
Run and control a user's app on a remote iOS/Android simulator hosted on EAS cloud.
$ npx skills add expo/skills --skill eas-simulator -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install expo/skills eas-simulator --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/expo/skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/plugins/expo/skills/eas-simulator .claude/skills/eas-simulator && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "eas-simulator" agent skill from https://github.com/expo/skills/tree/main/plugins/expo/skills/eas-simulator into .claude/skills/eas-simulator/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "eas-simulator", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/expo/skills/tree/main/plugins/expo/skills/eas-simulatorType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add expo/skills --skill eas-simulator -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install expo/skills eas-simulator --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/expo/skills.git skills-src && mkdir -p .agents/skills && cp -r skills-src/plugins/expo/skills/eas-simulator .agents/skills/eas-simulator && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "eas-simulator" agent skill from https://github.com/expo/skills/tree/main/plugins/expo/skills/eas-simulator into .agents/skills/eas-simulator/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "eas-simulator", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add expo/skills --skill eas-simulator -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install expo/skills eas-simulator --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/expo/skills.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/plugins/expo/skills/eas-simulator .cursor/skills/eas-simulator && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "eas-simulator" agent skill from https://github.com/expo/skills/tree/main/plugins/expo/skills/eas-simulator into .cursor/skills/eas-simulator/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "eas-simulator", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/expo/skills.git --path plugins/expo/skills/eas-simulator--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add expo/skills --skill eas-simulator -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install expo/skills eas-simulator --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/expo/skills.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/plugins/expo/skills/eas-simulator .gemini/skills/eas-simulator && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "eas-simulator" agent skill from https://github.com/expo/skills/tree/main/plugins/expo/skills/eas-simulator into .gemini/skills/eas-simulator/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "eas-simulator", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install expo/skills eas-simulatorInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add expo/skills --skill eas-simulator -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/expo/skills.git skills-src && mkdir -p .github/skills && cp -r skills-src/plugins/expo/skills/eas-simulator .github/skills/eas-simulator && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "eas-simulator" agent skill from https://github.com/expo/skills/tree/main/plugins/expo/skills/eas-simulator into .github/skills/eas-simulator/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "eas-simulator", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add expo/skills --skill eas-simulator -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install expo/skills eas-simulator --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/expo/skills.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/plugins/expo/skills/eas-simulator .opencode/skills/eas-simulator && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "eas-simulator" agent skill from https://github.com/expo/skills/tree/main/plugins/expo/skills/eas-simulator into .opencode/skills/eas-simulator/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "eas-simulator", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
eas-simulatorRun and control a user's app on a remote iOS/Android simulator hosted on EAS cloud.
Eas Simulator is an agent skill from expo/skills, published by the product's own GitHub organization. Run and control a user's app on a remote iOS/Android simulator hosted on EAS cloud. Read before running 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…
Its SKILL.md is about 6.6k tokens, which your agent loads only when the skill is triggered. The skill folder holds 7 other files, including reference files (for example `agents/openai.yaml`, `references/controllers.md` and `references/logs-and-crashes.md`).
It sits in Mobile, covering Cross-platform mobile apps, iOS development and Android development. It works with Expo, iOS, Linux and Xcode. The repository describes itself as: A collection of AI agent skills for working with Expo projects and Expo Application Services. The licence is MIT.
5 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit d4f4840. It shows what the files ask for, not the result of running them.
Pre-approves these tools, so the agent can use them without asking each time:
Bash(npx *eas-cli@*)Bash(npx *agent-device@*)Bash(npx expo *)Bash(eas *)Bash(expo *)Bash(xcodebuild*)Bash(pod*)Bash(argent *)Bash(ffmpeg*)From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
npxeasexpoFrom the folder's file list and the shell code blocks in SKILL.md.
Links to these hosts (documentation or services it may open):
expo.devFrom URLs in SKILL.md, links to its own repository left out.
Names these keys or tokens, usually read from environment variables:
EXPO_TOKENFrom names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Eas Simulator loads about 6.6k tokens when it runs, and up to ~21k if it reads all its reference files. Until then it costs about 248 tokens; SKILL.md has 3,250 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check noted patterns worth knowing about, such as sudo or a known installer.
- **`.env.eas-simulator`** is written/managed by eas-cli (not this skill): it holds the session id (`EAS_SIMULATOR_SESSIremote sim + agent-device daemon; writes .env.eas-simulator).printf '# managed by eas-cli\n' > .env.eas-simulator # clear only after resolving any live sessionprintf '# managed by eas-cli\n' > .env.eas-simulatoroot the sim + selected interface; write `.env.eas-simulator` by default; print the preview + job-run URLs. **Always passst simulator:exec <cmd> [args…]` | Load `.env.eas-simulator`, then run `<cmd>` with that env. The bridge to the controllessions the *wrong app* + drops a stray `.env.eas-simulator`; `pwd` / check `app.json`).not a driver.** `simulator:exec` loads `.env.eas-simulator` and spawns the command you pass; the device verbs come fromprintf '# managed by eas-cli\n' > .env.eas-simulator # clear the stale session id so it isn't reusedAutomated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from expo/skills at commit d4f4840, republished under its MIT licence (© expo). 3,250 words, ~6,626 tokens.
.claude/skills/eas-simulator/SKILL.md (or your agent's skills folder). This skill also uses 5 other files; get the full folder from GitHub.EAS service - costs apply. Sessions count toward your account's pricing and limits and stop at their maximum duration. Stop a session with
eas simulator:stopwhen the task is done. See https://expo.dev/pricing for current terms.
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; the relevant subcommand's --help output is authoritative.
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.
expo run:ios / Xcode / Android Studio as appropriate. Clarify only when the requested environment remains ambiguous and affects the task.When the user asks for EAS Simulator or a cloud simulator, start the session and do the requested work without asking again. Stop the session when the work is done. Only check in if the user set a limit you would go past, or if the work grows beyond what they asked for.
eas command via npx --yes eas-cli@latest … — guarantees a CLI new enough to have simulator:* (a global eas is often too old), and --yes skips npx's prompt. (Bare eas is fine if eas --version is current.)npx --yes eas-cli@latest login. Cloud sandbox / CI / headless agent has no browser login — set EXPO_TOKEN (expo.dev → Account → Access Tokens) in the env instead. Verify either way with npx --yes eas-cli@latest whoami.npx --yes eas-cli@latest init to create/link the project (when there's no projectId), and set ios.bundleIdentifier in app config if it's missing — a fresh create-expo-app often has none, and prebuild/eas build need it (they prompt or fail without it; e.g. dev.<owner>.<slug>). Read current config with npx expo config --json (it may live in app.config.js). The first Mode-C run is slow (native build); later runs reuse it.npx agent-device@latest — nothing globally installed. Appium and argent are alternative automation interfaces; web-preview-only has no automation interface. See references/controllers.md..env.eas-simulator is written/managed by eas-cli (not this skill): it holds the session id (EAS_SIMULATOR_SESSION_ID) + the daemon URL/token, so get/stop/exec default 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 .gitignore won't cover it — add .env.eas-simulator if missing).printf, lsof, $(seq …) loops won't run in cmd/PowerShell. On Windows, run them in WSL or Git Bash, or translate as you go (the eas-cli/agent-device invocations themselves are cross-platform).--max-duration-minutes N is the hard automatic-stop deadline. Any plan can set it, up to the plan limit (40 minutes on Free, 115 on paid plans). The timer starts when the session is ready.--max-idle-time-minutes N stops a session after that many inactive minutes. Omitted means no idle timeout: the session runs until its maximum duration or an explicit stop.agent-device, argent, and Appium commands, which are recorded as session events with producer appium). Browser-preview activity does not reset it. For a user-driven browser preview, rely on the maximum duration, not idle time, to bound the session.EAS Simulator is a limited-access EAS feature that is still rolling out, so it isn't enabled on every account. Check access before starting a session; this read-only command does not create a session.
npx --yes eas-cli@latest simulator:availability --json
# → {"available": true, ...} enabled → continue to the core loop
# → {"available": false, ...} not enabled → do NOT start a sessionIf it's not available, don't call simulator:start (it will fail). Instead, hand off gracefully so you keep making progress without this skill:
expo run:ios / Xcode / Android Studio for a local sim/emulator, an EAS Build, or whatever else fits. Don't dead-end on the cloud sim; the request was almost never "use EAS Simulator specifically."(If simulator:availability isn't recognized, the CLI is too old — upgrade, or treat a not enabled for this account error from simulator:start the same way: stop and fall back.)
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).
# If the dotenv names a session, inspect it with simulator:get --json first. Reuse it when it
# belongs to this run; stop it only when it is in scope and no longer needed. An IN_PROGRESS
# session may be intentionally concurrent, so preserve its id/config before resetting the dotenv.
# Continue below only after choosing how to handle that existing session.
printf '# managed by eas-cli\n' > .env.eas-simulator # clear only after resolving any live session
npx --yes eas-cli@latest simulator:start --platform ios --type agent-device --non-interactive \
--name "Checkout flow screenshots" # always name it — see 'Always name the session'
# 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 (use 'press' or 'click')
npx --yes eas-cli@latest simulator:exec npx agent-device@latest screenshot ./shot.png
# 3. Stop the session 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-simulatorTo watch it live, hand the user the webPreviewUrl that start prints (in --json, remoteConfig.webPreviewUrl; for web-preview-only sessions, remoteConfig.previewUrl). All current session types include a browser preview, on iOS and Android; agent-device, appium, and argent also provide automation, while web-preview-only provides no automation interface. On Android, the expo.dev session page does not show the preview inline yet: Open preview opens it in a new tab. Android support is in development, so some iOS features may not work there. This URL is for the user's browser — you cannot open it for them, and it must never touch the sim:
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.open the webPreviewUrl on the sim. It's a browser preview, not a deep link and not an agent-device open argument; routing it to the device renders a browser-in-a-browser (a real past failure).--max-duration-minutes N (up to the plan limit). Browser-preview activity does not reset --max-idle-time-minutes, so idle timeout is not a reliable lifetime bound for this case. Tell the user when the session expires, using the CLI's reported duration or expiry. Keep it running for the requested preview; stop sessions created for one-shot tasks when the task finishes.start also prints a job-run URL.
Pass --name "<description>" on every simulator:start. The name appears in simulator:list, simulator:get, and on the Simulator sessions page on expo.dev, where it replaces the generic title on each row. Unnamed, every row reads "Simulator session" over a random id — a wall of identical entries nobody can navigate. Write the name for a human scanning that list days later, not for yourself during this run.
Write what the session is for, in a few plain words:
--name "Checkout flow screenshots" # what you did
--name "Dev build — dark mode fix" # what you were testing
--name "Login repro for issue 412" # why it existsRules:
Mode C session, agent-device ios, and test say nothing.Dev build for expo-router v4, Repro for EXPO-1234). It's a row title, so no Title Case, no all-lowercase, and no trailing period.iOS, no dates, no your-own-name. Spend the whole budget on what those columns can't say: the purpose.--name is newer than simulator:start itself, so an older installed eas-cli can reject it. If that happens, run via npx --yes eas-cli@latest or upgrade; as a last resort, retry once without --name (the session starts unnamed). See references/troubleshooting.md.
Query the installed CLI for the complete current flag set before using non-default start flags, machine-readable/config output, list filters, or session events:
# Replace `start` with the simulator subcommand you are about to run.
npx --yes eas-cli@latest simulator:start --helpThe examples below cover the common workflow; they are intentionally not an exhaustive
copy of the CLI surface. Keep non-obvious behavioral guidance from this skill—especially
Session lifetime—even when constructing the command from --help.
| Command | Purpose |
|---|---|
npx --yes eas-cli@latest simulator:availability [--json] [--non-interactive] | Check access without creating a session. |
npx --yes eas-cli@latest simulator:start --platform ios|android --name "<description>" [flags] | Create a session; boot the sim + selected interface; write .env.eas-simulator by default; print the preview + job-run URLs. Always pass --name. --json does not suppress the dotenv; use --out-config-type env when no file should be written (it prints only the controller export lines, without EAS_SIMULATOR_SESSION_ID, so pass --id to get/stop/events). |
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 <id>] [--json] [--non-interactive] | Session status + connection details, including the session name. Use this to confirm readiness (see Operating principles). |
npx --yes eas-cli@latest simulator:list [filters] [--limit N] [--after <cursor>] [--json] | List and paginate project sessions; filter by status, type, platform, name prefix, and tags. |
npx --yes eas-cli@latest simulator:events [--id <id>] [--follow|--json] | Show recorded activity events; --follow watches until the session ends. |
npx --yes eas-cli@latest simulator:stop [--id <id>] [--json] [--non-interactive] | Stop a session (idempotent). |
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 (grabbing a build that doesn't fit the request):
- Wrong type. Live edits (Mode C) require a dev build. A static build — a local Release (A), the default EAS sim build (B), or any build left on the sim from an earlier screenshot run — freezes its JS at build time and can never hot-reload. For a live request, ignore existing builds entirely and install a dev build (local Debug, or an EAS build with
developmentClient: true). Never reconnect Metro to a static build hoping it'll reload — it won't.- Stale. A static look must match current source — reuse only a fingerprint-matched build, else build fresh; reuse is explicit-only.
So a leftover EAS/release build is not a shortcut for "iterate live" — it's the wrong binary. The fact that a build exists never makes it the right one.
| Mode | What it is | Choose when | Live edits? |
|---|---|---|---|
| A — Local release build | Build a Release .app locally, agent-device install it (uploads) | User has a Mac toolchain and wants a quick "run my current code on a cloud device" | No (rebuild to see changes) |
| B — EAS build (rare, explicit-only) | eas build a simulator build, agent-device install-from-source <url> (the VM downloads it) | Only when explicitly asked — the user names an existing/EAS build, or wants a static EAS artifact for CI/sharing. Not for "show me"/"iterate" (use C). Sim builds need no credentials. | No |
| C — Local dev build + tunnel | Dev (Debug) build + EXPO_UNSTABLE_TUNNEL_V2=1 expo start --tunnel + connect the dev client to Metro | The agentic edit-and-see loop — change code and see it live (Fast Refresh) | Yes |
Quick decision — default to C; A and B are explicit-only:
developmentClient: true). Unsure → C.Before starting a Mode C tunnel or connecting the dev client, read Tunnel scope and approvals. Carry existing authorization for this project's remote development transport through tunnel creation, connection, and live edits; include its source and the concrete data flow in any approval request.
If a controller fails to download a recording, retrieve it from EAS session artifacts.
agent-device is the controller. Common verbs (run each as npx --yes eas-cli@latest simulator:exec npx agent-device@latest <verb>):
| Verb | Does |
|---|---|
apps --platform ios | List user-installed apps (the blank sim shows none); add --all to include system apps |
install <appId> <path> --platform ios | Install a local .app (uploads it) |
install-from-source <url> --platform ios | Install from a URL — the VM downloads it (use for EAS artifacts) |
open <appId|deep-link> --platform ios | Launch an app (bundle id) or follow an app deep link (exp+slug://…). A first-time deep link raises a system "Open in '<app>'?" dialog — expect it (don't burn a snapshot discovering it) and press 'label="Open"' to hand off; it can be slow, so bound it with agent-device's own --timeout (e.g. press 'label="Open"' --timeout 120000) — not a shell timeout wrapper (macOS has no timeout binary). (Mode C sidesteps this dialog for the Metro-connect link via "Enter URL manually" — see run-your-app.md.) Not for the webPreviewUrl — that's a browser preview for the user, never the device. |
snapshot -i | Interactive accessibility tree → @e1-style refs |
press <ref|selector> | Tap (e.g. press @e2 or press 'label="Open"'). click <target> also works. Use press or click: tap is a hidden alias that older versions reject |
fill <ref> "text" | Type into a field |
screenshot <path> | Capture the screen to a local PNG (downloaded from the daemon) — requires an app to be open (open first). On iOS the default is 1x logical points (402x874 on iPhone 17); add --pixel-density 3 for full resolution |
record start [path] / record stop | Record the screen to a video at the record start path (record stop takes no path) — use this for motion (animations, gestures, transitions, timing), which a single screenshot can't capture |
metro prepare / metro reload | Point a dev client at Metro / reload (Mode C) |
Screenshots vs. video. Default to screenshot for static state, but for anything that moves — an animation, a transition, a gesture, a timing/jank question — record a video and inspect the frames instead; a still can't prove motion. Both controllers record (agent-device record start/stop, argent screen-recording-start/stop). Recordings sample at ~30fps — enough to see visible jank, not to prove sub-frame 60/120Hz hitches. For timing specifically, argent drops static frames by default (turn trimStatic off) — that plus other per-controller gotchas are in references/controllers.md.
For the full verb set and the argent controller alternative, see references/controllers.md.
When the app crashes or closes on launch, read the iOS session's crash reports and device log before guessing from screenshots. Read them from the preview API URL in simulator:get --json. That URL carries the session token, so never print it.
Hold the device log before you reproduce the crash. Without the hold, the crash gets a report but an empty log tail. Commands, fields, and fallbacks are in references/logs-and-crashes.md.
The non-obvious mental model worth internalizing. Specific error→fix lookups (hung verbs, tap rejected, --platform, --json, pod install locale, orphaned sessions, boot variability) live in references/troubleshooting.md.
Establish ground truth, then reset — don't patch-loop. Never assume an existing session or Metro is yours or healthy. Before driving, confirm:
start/exec sessions the wrong app + drops a stray .env.eas-simulator; pwd / check app.json).IN_PROGRESS via simulator:get --json (a stopped session keeps its id + remoteConfig, so the dotenv alone isn't proof).--port <N>, e.g. 8082), don't kill another server to reclaim :8081 (run-your-app.md).If current code isn't rendering after your first connect, stop poking live state: reset to baseline (stop session → clear dotenv → kill your Metro) and redo the mode once; a second failure → stop and report. Never restart Metro in place, reconnect more than once, rebuild the native client to fix a JS/connection problem, or surface a preview URL while state is unknown. (A daemon drop — ERR_NGROK_3200 / Remote daemon is unavailable — is the same: reset, don't retry.)
exec is a wrapper, not a driver. simulator:exec loads .env.eas-simulator and spawns the command you pass; the device verbs come from the controller (npx agent-device@latest). There is no simulator:tap.
Act immediately; don't park an idle session. Sessions are short-lived — install and drive right after start. Leaving one idle drops the tunnel/daemon (→ reset, per #1).
Stop sessions you created on completion or failure and reset the dotenv. --non-interactive does not stop a session when your task ends. For a requested live preview, follow the duration guidance above. Poll the existing session during a slow boot; starting another creates an extra session and overwrites the dotenv's session id.
Screenshot only the correct, fresh build. Mode C only after the dev client connects to Metro; A/B only from a build matching current source — reusing a pre-existing build is the #1 "my edits don't show" cause (see the build caveat above). (9:41 in the status bar is the sim default, not staleness.)
After the task, stop the session you created and reset the dotenv so a later run doesn't try to reuse the dead session. For a requested live preview, keep it available for the agreed duration instead:
npx --yes eas-cli@latest simulator:stop # omit --id → stops the dotenv session (or pass --id <id>)
printf '# managed by eas-cli\n' > .env.eas-simulator # clear the stale session id so it isn't reused
# if you started Metro for Mode C, stop it too (Ctrl+C in its terminal, or kill the expo process)argent alternative.Source of truth: Expo docs and the eas / agent-device CLIs (npx --yes eas-cli@latest simulator:* --help, npx --yes eas-cli@latest simulator:exec npx agent-device@latest help [topic]; --help after simulator:exec shows the EAS CLI help instead). This skill teaches how to apply them; it doesn't replace them.
If you encounter errors, misleading or outdated information in this skill, report it so Expo can improve:
npx --yes submit-expo-feedback@latest --category skills --subject "eas-simulator" "<actionable feedback>"Only submit when you have something specific and actionable to report. Include as much relevant context as possible. If an AI agent repeatedly failed or the user had to take over an Expo task, load the expo-skill-feedback skill and follow its eval-candidate flow instead of reusing the command above.
© expo, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 5 other files (references) in plugins/expo/skills/eas-simulator of expo/skills.
Open the folder on GitHubat commit d4f4840
Eas Simulator next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Eas Simulator this skillexpo/skills | 2.7k | — | ~6.6k | Automated safety check: Notes | MIT | |
| Limrun Xcodesuperset-sh/superset | 15k | — | ~6.5k | Automated safety check: Notes | Custom licence | |
| Expo Brownfield Integrationmweinbach/agent-coworker | 156 | 2 repos | ~900 | Automated safety check: Notes | Custom licence | |
| OdevioOdevio/Odevio-CLI | 423 | — | ~7.6k | Automated safety check: Pass | MIT | |
| Expo UIarcboxlabs/linkcode | 155 | — | ~1.2k | Automated safety check: Pass | MIT | |
| Ksafeioannisa/KSafe | 332 | — | ~17k | Automated safety check: Pass | Apache-2.0 |
superset-sh/superset
Build an iOS / Apple app on remote Xcode with lim xcode build instead of local xcodebuild, run project commands with lim xcode run, or run its XCTest suites with lim xcode test, from any environment…
mweinbach/agent-coworker
Helps add Expo and React Native to an existing native iOS or Android app, and choose between a prebuilt AAR or XCFramework and a fully integrated build.
Odevio/Odevio-CLI
Take a Flutter project to an iPhone or the App Store with Odevio - build, sign and publish iOS apps from Windows, Linux or macOS with no Mac and no Xcode.
arcboxlabs/linkcode
Framework (OSS). An agent skill from arcboxlabs/linkcode.
ioannisa/KSafe
Required before any reply that touches KSafe (by ksafe(...), ksafe.get/put, :ksafe-compose, :ksafe-biometrics), even a 'can KSafe do X?' question or a one-line change that looks like plain Kotlin.
suntay44/web-to-mobile-magic-plugin
Orchestrate website or web app conversion into a mobile app.
expo/skills
Check the health of published EAS Update: crash rates, install/launch counts, unique users, payload size, and the split between embedded and OTA users per channel.
expo/skills
Helps understand and write EAS workflow YAML files for Expo projects.
expo/skills
Add an iOS App Clip target to an Expo app. An agent skill from expo/skills.
expo/skills
Evaluate Expo skills in this repo end-to-end - trigger accuracy, generated code quality, and runtime screenshots on iOS simulator and Android emulator via Expo Go (web optional).
expo/skills
Submit feedback on an Expo skill—or Expo itself—and control bundled anonymous usage telemetry (off by default / opt-in).
expo/skills
Guide for creating and writing Expo native modules and views using the Expo Modules API (Swift, Kotlin, TypeScript).
Categories
Run and control a user's app on a remote iOS/Android simulator hosted on EAS cloud. Eas Simulator is an agent skill from expo/skills, published by the product's own GitHub organization. Run and control a user's app on a remote iOS/Android simulator hosted on EAS cloud.
Eas Simulator fits situations like: the user needs a simulator they cant run locally - run my app on a cloud simulator; use eas simulator to run/install/screenshot my app; im on Linux/Cursor and need an iOS device; no sim on this box / headless CI.
Run `npx skills add expo/skills --skill eas-simulator -a claude-code`. Or copy the skill folder (plugins/expo/skills/eas-simulator in expo/skills) into .claude/skills/eas-simulator in your project. Claude Code loads it when a task matches its description.
Run `npx skills add expo/skills --skill eas-simulator -a codex`. Or copy the skill folder (plugins/expo/skills/eas-simulator in expo/skills) into .agents/skills/eas-simulator in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add expo/skills --skill eas-simulator -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/eas-simulator, .gemini/skills/eas-simulator, .github/skills/eas-simulator and .opencode/skills/eas-simulator in your project.
Going by SKILL.md and its folder, Eas Simulator needs the command-line tools its instructions call (npx, eas and expo) and credentials named EXPO_TOKEN. Our summary lists: Node.js; A credential in EXPO_TOKEN. Its frontmatter pre-approves these tools: Bash(npx *eas-cli@*), Bash(npx *agent-device@*), Bash(npx expo *), Bash(eas *), Bash(expo *), Bash(xcodebuild*), Bash(pod*), Bash(argent *), Bash(ffmpeg*).
SKILL.md names 1 domain. As links in the text: expo.dev. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found notes only (mentions a .env file), nothing it rates as a warning. It is not a guarantee. Review the folder before installing.
Eas Simulator is published under the MIT licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.
About 6.6k tokens (SKILL.md is roughly 27k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 15k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Eas Simulator: Limrun Xcode (superset-sh/superset, 15k stars), Expo Brownfield Integration (mweinbach/agent-coworker, 156 stars), Odevio (Odevio/Odevio-CLI, 423 stars) and Expo UI (arcboxlabs/linkcode, 155 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
expo (a GitHub organization, an official publisher) maintains it in expo/skills, which has 2,661 GitHub stars. The repository holds 26 skills in this directory. The repository was last updated on October 6, 2026.
Source: expo/skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.