Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
c322784
[docs][ios][expo-location] Add `motionUsagePermission` configurable p…
cornejobarraza Sep 1, 2026
39aee7e
[router] Remove redundant processing logic for menu icon (#49584)
Ubax Sep 1, 2026
e2e9640
[observe] Remove pending metrics db table (#49547)
Ubax Sep 1, 2026
2172304
[observe] dispatch native crashes as logs (#49489)
Ubax Sep 1, 2026
756a18b
[ui][router][docs] Add missing screenshots for `cornerRadius` and oth…
amandeepmittal Sep 1, 2026
03fd6b2
[web-browser] Fix Android `toolbarColor` being applied as the seconda…
MUSE-CODE-SPACE Sep 1, 2026
49e89cd
[ios][autolinking] Add prebuilt-metadata command emitting the identit…
chrfalch Sep 1, 2026
a00cda2
[docs] Improve AI agent section and plugins info in create a project …
amandeepmittal Sep 1, 2026
899d99b
[core][iOS] Bind each host runtime callback to the app context it cre…
LizunovSergey Sep 1, 2026
568c2fa
[image][android] Overwrite Glide disk cache entries that fail to deco…
intergalacticspacehighway Sep 1, 2026
6a72800
[docs] Document EAS Simulator create links (#49571)
szdziedzic Sep 1, 2026
dde6051
[core][android] Fix Expo module views not receiving props with React …
behenate Sep 1, 2026
5a46f11
[cli] Fix iOS asset catalog scale-to-file pairing for assets with non…
janicduplessis Sep 1, 2026
b093b4f
[ios][autolinking] Read prebuilt XCFramework Info.plists in a single …
chrfalch Sep 1, 2026
c3753ed
[router] Fix animation when pushing to stack nested in tab (#49592)
Ubax Sep 1, 2026
64310f2
[router] Remove unnecessary wrapping of navigation containers (#49587)
Ubax Sep 1, 2026
8a48e58
[router] remove unhandeled linking context (#49616)
Ubax Sep 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/constants/navigation.js
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,7 @@ const preview = [
makePage('preview/eas-simulator/introduction.mdx'),
makePage('preview/eas-simulator/get-started.mdx'),
makePage('preview/eas-simulator/run-and-control.mdx'),
makePage('preview/eas-simulator/create-session-links.mdx'),
makePage('preview/eas-simulator/cli-reference.mdx'),
makePage('preview/eas-simulator/rest-api.mdx'),
makePage('preview/eas-simulator/troubleshooting.mdx'),
Expand Down
31 changes: 29 additions & 2 deletions docs/pages/get-started/create-a-project.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ hideTOC: true

import { RelatedSkills } from '~/ui/components/RelatedSkills';
import { Terminal } from '~/ui/components/Snippet';
import { Tabs, Tab } from '~/ui/components/Tabs';

Expo is a React Native framework that makes developing Android and iOS apps easier. Our framework provides file-based routing, a standard library of native modules, and much more. Expo is open source with an active community on [GitHub](https://github.com/expo/expo) and [Discord](https://chat.expo.dev).

Expand Down Expand Up @@ -63,12 +64,38 @@ To create a known example directly, pass its name:

> **info** The rest of the guides in this **"Get started"** section follows the default project. An example app may be organized differently but the concepts are the same.

## Expo Skills for AI agents
## Set up an AI agent

If you use an AI agent, install [Expo Skills](/skills/) to teach it where files live in a new Expo project:
A new project includes the project context files that AI agents read: **AGENTS.md**, **CLAUDE.md**, and **.claude/settings.json**. Claude Code and Codex also have an official Expo plugin. Using one command, you can install [Expo Skills](/skills/) and register the [Expo Model Context Protocol (MCP) Server](/mcp/):

<Tabs>

<Tab label="Claude Code">

<Terminal cmd={['$ claude plugin install expo@claude-plugins-official']} />

Then run `/mcp` inside your Claude Code session to sign in to your Expo account.

</Tab>

<Tab label="Codex">

<Terminal cmd={['$ codex plugin add expo@openai-curated']} />

Then sign in to your Expo account:

<Terminal cmd={['$ codex mcp login expo']} />

</Tab>

</Tabs>

The plugin also installs the skill that teaches an agent where files live in a new Expo project:

<RelatedSkills names={['expo-project-structure']} />

For Cursor and other agents, install [Expo Skills](/skills/) and the [Expo MCP Server](/mcp/) separately. The [AI agents and Expo](/agents/) overview covers setup for each agent.

## Next step

You have a project. Now it's time to set up your development environment so that you can start developing.
113 changes: 113 additions & 0 deletions docs/pages/preview/eas-simulator/create-session-links.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
---
title: Start an EAS Simulator session from a link
sidebar_title: Create session links
description: Construct an authenticated expo.dev URL that creates and opens an EAS Simulator session from an EAS Build, build fingerprint, or application archive.
---

> **important** **EAS Simulator is a limited-access preview.** It is not included with paid or free plans and is currently available only to select partners. [Join the waitlist](https://expo.dev/services/simulators) if you are interested in trying it.

A create session link starts an iOS Simulator session from an EAS Build, build fingerprint, or application archive and opens its session page on expo.dev. Use one to add an EAS Simulator action to a pull request, CI result, or an internal tool without integrating the [REST API](/preview/eas-simulator/rest-api/).

Create session links start browser-preview-only sessions. They do not provision agent-device, Appium, or Argent. Use [EAS CLI](/preview/eas-simulator/cli-reference/) or the [REST API](/preview/eas-simulator/rest-api/) when you need a controller, an Android Emulator, a blank device, Expo Go, or custom duration and idle limits.

> **warning** Opening a create session link starts a new session without a confirmation step. The link is not idempotent: opening it again can create another session that consumes EAS Simulator usage. Share the resulting session page URL when you want someone to view an existing session instead of starting a new one.

## Construct the URL

Use the Expo account name and project slug in the URL:

```text
https://expo.dev/accounts/<account>/projects/<project>/simulator-sessions/create?<parameters>
```

The person opening the link must sign in to an Expo account that can access the project. If they are signed out, expo.dev preserves the complete URL during authentication and starts the session after they sign in.

### Choose an application source

Every create session link requires exactly one application source:

| Parameter | Description |
| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `buildId` | ID of a finished, unexpired EAS Build for the iOS Simulator. The build determines the platform. |
| `buildFingerprint` | Fingerprint hash of an EAS Build. Requires `platform`. EAS resolves it to the most recent installable build with this fingerprint on the requested platform. |
| `applicationArchiveUrl` | URL of a downloadable iOS application archive. Encode this URL because it is nested inside the create session URL. Supported extensions are **.tar.gz**, **.tgz**, **.app**, and **.app.zip**. |

Do not include more than one application source. A link without an application source cannot create a session.

EAS treats an empty application source value, such as `buildId=`, as absent.

### Add other parameters

| Parameter | Description |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `platform` | Platform for `buildFingerprint` or `applicationArchiveUrl`. Create session links currently support `ios`. It is required with `buildFingerprint` and can be omitted when an archive URL has a supported iOS extension. It is ignored when the application source is `buildId` because the build determines its platform. |
| `launchArgs` | Argument passed to the application when it launches. Repeat this parameter to pass multiple arguments. Their order is preserved. |
| `openUrl` | Expo, development-client, or application deep link to open after the application launches. |
| `deviceIdentifier` | iOS Simulator name or unique device identifier (UDID), such as `iPhone 16 Pro`. The runner chooses the default device when this parameter is omitted. |
| `name` | Descriptive session name with a maximum of 255 characters. |

URL-encode parameter values, especially nested URLs and values that contain spaces. Most programming languages provide a URL builder that handles this encoding. For example:

```js
const url = new URL('https://expo.dev/accounts/acme/projects/my-app/simulator-sessions/create');

url.searchParams.set('buildFingerprint', 'FINGERPRINT_HASH');
url.searchParams.set('platform', 'ios');
url.searchParams.set('name', 'PR preview');
url.searchParams.set('deviceIdentifier', 'iPhone 16 Pro');
url.searchParams.append('launchArgs', '-UITestMode');
url.searchParams.append('launchArgs', '1');
url.searchParams.set('openUrl', 'myapp://profile/42');

console.log(url.toString());
```

## Examples

### Start a session from an EAS Build

```text
https://expo.dev/accounts/acme/projects/my-app/simulator-sessions/create?buildId=BUILD_UUID
```

The build must be finished, its artifact must not be expired, and it must target the iOS Simulator instead of a physical iOS device.

### Start the most recent installable build with a fingerprint

```text
https://expo.dev/accounts/acme/projects/my-app/simulator-sessions/create?buildFingerprint=FINGERPRINT_HASH&platform=ios
```

EAS resolves the fingerprint to the most recent installable iOS Simulator build. If no installable build with this fingerprint exists, the link shows a validation error. Use `buildId` instead when you need to select one specific build.

### Name the session and choose a device

```text
https://expo.dev/accounts/acme/projects/my-app/simulator-sessions/create?buildId=BUILD_UUID&name=PR%20preview&deviceIdentifier=iPhone%2016%20Pro
```

### Start a session from an application archive

```text
https://expo.dev/accounts/acme/projects/my-app/simulator-sessions/create?applicationArchiveUrl=https%3A%2F%2Fcdn.example.com%2FMyApp.app.zip&platform=ios
```

### Pass launch arguments and open a deep link

```text
https://expo.dev/accounts/acme/projects/my-app/simulator-sessions/create?buildId=BUILD_UUID&launchArgs=-UITestMode&launchArgs=1&openUrl=myapp%3A%2F%2Fprofile%2F42
```

## What happens when the link opens

After authentication, expo.dev validates the parameters and build, creates the session, and redirects to its session page:

```text
https://expo.dev/accounts/<account>/projects/<project>/simulator-sessions/<session-id>
```

The session page shows its startup progress and the browser preview when it becomes available. Keep this resulting URL to return to or share the same session.

Closing the page or navigating away does not cancel a session creation that the service already accepted, and it does not stop a running session. Stop the session when you finish so that it does not continue consuming usage.

If the parameters or build are invalid, expo.dev shows a **Cannot start simulator session** error instead. Common causes include an unfinished or expired build, an iOS device build, a fingerprint without `platform`, no installable build for a fingerprint, an unsupported archive URL, or more than one application source.
2 changes: 1 addition & 1 deletion docs/pages/preview/eas-simulator/get-started.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ If you use an AI agent, install [Expo Skills](/skills/) and ask it to use the EA

## Start a session manually

The steps below use EAS CLI. To manage sessions directly from your own HTTP client, see the [REST API reference](/preview/eas-simulator/rest-api/).
The steps below use EAS CLI. To manage sessions directly from your own HTTP client, see the [REST API reference](/preview/eas-simulator/rest-api/). To start a browser-preview-only session when someone opens an authenticated expo.dev URL, see [Create session links](/preview/eas-simulator/create-session-links/).

<Step label="1">

Expand Down
9 changes: 8 additions & 1 deletion docs/pages/preview/eas-simulator/introduction.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ A common setup is a [Cursor cloud agent](https://cursor.com/cloud) or another ba

An EAS Simulator workflow has four stages:

1. **Start a session** with EAS CLI or the [REST API](/preview/eas-simulator/rest-api/). Give the session a descriptive name, choose a remote device and session type, and optionally set automatic duration or idle limits.
1. **Start a session** with EAS CLI, the [REST API](/preview/eas-simulator/rest-api/), or an authenticated [create session link](/preview/eas-simulator/create-session-links/). Give the session a descriptive name, choose a remote device and session type, and optionally set automatic duration or idle limits.
2. **Install your app.** Pass an EAS Build, application archive URL, or Expo Go to the start command, or install a local build through the controller after the session starts. A session without an application source starts with a blank device.
3. **Drive the device.** Use [agent-device](/agents/agent-device/), [Argent](/agents/argent/), or [Appium](https://appium.io/docs/en/) for programmatic control. Supported iOS sessions also include a web preview.
4. **Stop the session.** Stop it explicitly when you finish. An unattended non-interactive session continues consuming usage until it stops or reaches a configured limit.
Expand Down Expand Up @@ -88,6 +88,13 @@ Use [EAS Build](/build/introduction/) to create installable builds, and use loca
Icon={Cloud01Icon}
/>

<BoxLink
title="Create session links"
description="Construct a URL that starts a browser preview from an EAS Build or application archive."
href="/preview/eas-simulator/create-session-links/"
Icon={Cloud01Icon}
/>

<BoxLink
title="CLI reference"
description="Review the experimental simulator commands, flags, output, and managed environment file."
Expand Down
7 changes: 7 additions & 0 deletions docs/pages/versions/unversioned/sdk/location.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,13 @@ You can configure `expo-location` using its built-in [config plugin](/config-plu
'A string to set the [`NSLocationWhenInUseUsageDescription`](#permission-nslocationwheninuseusagedescription) permission message.',
default: '"Allow $(PRODUCT_NAME) to use your location"',
},
{
name: 'motionUsagePermission',
platform: 'ios',
description:
'A string to set the `NSMotionUsageDescription` permission message shown when `getMotionActivityAsync` or `watchMotionActivityAsync` is called for the first time.',
default: '"Allow $(PRODUCT_NAME) to detect your current motion activity"',
},
{
name: 'isIosBackgroundLocationEnabled',
platform: 'ios',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,8 @@ Use `cornerRadius` to override the default Material3 menu shape with a custom co

<ComponentExample
title="RoundedDropdownMenuExample.tsx"
src="/static/images/expo-ui/examples/dropdownmenu-rounded-android-light.webp"
darkSrc="/static/images/expo-ui/examples/dropdownmenu-rounded-android-dark.webp"
alt="A menu with rounded corners opened below a Show menu button">

```tsx
Expand Down
7 changes: 7 additions & 0 deletions docs/pages/versions/v56.0.0/sdk/location.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,13 @@ You can configure `expo-location` using its built-in [config plugin](/config-plu
'A string to set the [`NSLocationWhenInUseUsageDescription`](#permission-nslocationwheninuseusagedescription) permission message.',
default: '"Allow $(PRODUCT_NAME) to use your location"',
},
{
name: 'motionUsagePermission',
platform: 'ios',
description:
'A string to set the `NSMotionUsageDescription` permission message shown when `getMotionActivityAsync` or `watchMotionActivityAsync` is called for the first time.',
default: '"Allow $(PRODUCT_NAME) to detect your current motion activity"',
},
{
name: 'isIosBackgroundLocationEnabled',
platform: 'ios',
Expand Down
7 changes: 7 additions & 0 deletions docs/pages/versions/v57.0.0/sdk/location.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,13 @@ You can configure `expo-location` using its built-in [config plugin](/config-plu
'A string to set the [`NSLocationWhenInUseUsageDescription`](#permission-nslocationwheninuseusagedescription) permission message.',
default: '"Allow $(PRODUCT_NAME) to use your location"',
},
{
name: 'motionUsagePermission',
platform: 'ios',
description:
'A string to set the `NSMotionUsageDescription` permission message shown when `getMotionActivityAsync` or `watchMotionActivityAsync` is called for the first time.',
default: '"Allow $(PRODUCT_NAME) to detect your current motion activity"',
},
{
name: 'isIosBackgroundLocationEnabled',
platform: 'ios',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,8 @@ Use `cornerRadius` to override the default Material3 menu shape with a custom co

<ComponentExample
title="RoundedDropdownMenuExample.tsx"
src="/static/images/expo-ui/examples/dropdownmenu-rounded-android-light.webp"
darkSrc="/static/images/expo-ui/examples/dropdownmenu-rounded-android-dark.webp"
alt="A menu with rounded corners opened below a Show menu button">

```tsx
Expand Down
2 changes: 1 addition & 1 deletion docs/public/static/data/unversioned/expo-router.json

Large diffs are not rendered by default.

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/public/static/data/unversioned/expo-router/link.json

Large diffs are not rendered by default.

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/public/static/data/unversioned/expo-router/stack.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/public/static/data/unversioned/expo-router/ui.json

Large diffs are not rendered by default.

Loading
Loading