# The project root by default is one level up from the ios directory
export PROJECT_ROOT="$PROJECT_DIR"/..
if [[ "$CONFIGURATION" = *Debug* ]]; then
  export SKIP_BUNDLING=1
fi
if [[ -z "$ENTRY_FILE" ]]; then
  # Set the entry JS file using the bundler's entry resolution.
  export ENTRY_FILE="$("$NODE_BINARY" -e "require('expo/scripts/resolveAppEntry')" "$PROJECT_ROOT" ios relative | tail -n 1)"
fi
if [[ -z "$CLI_PATH" ]]; then
  # Use Expo CLI
  export CLI_PATH="$("$NODE_BINARY" --print "require.resolve('@expo/cli')")"
fi
if [[ -z "$BUNDLE_COMMAND" ]]; then
  # Default Expo CLI command for bundling
  export BUNDLE_COMMAND="export:embed"
fi
`"$NODE_BINARY" --print "require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'"`
```
And add support the `"main"` field in **package.json** by making the following change to **AppDelegate.swift**:
```diff
diff --git a/ios/AppDelegate.swift b/ios/AppDelegate.swift
index 0000000..1111111 100644
--- a/ios/AppDelegate.swift
+++ b/ios/AppDelegate.swift
@@ -1,7 +1,7 @@
   override func bundleURL() -> URL? {
 #if DEBUG
-    RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index")
+    RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: ".expo/.virtual-metro-entry")
 #else
     Bundle.main.url(forResource: "main", withExtension: "jsbundle")
 #endif
   }
```
---
## Usage
### Verifying installation
You can verify that the installation was successful by logging a value from [`expo-constants`](/versions/latest/sdk/constants).
- Run `npx expo install expo-constants`
- Then, run `npx expo run` and modify your app JavaScript code to add the following:
```js
import Constants from 'expo-constants';
console.log(Constants.systemFonts);
```
### Using Expo SDK packages
Once the `expo` package is installed and configured in your project, you can use `npx expo install` to add any other Expo module from the SDK. See [Using Libraries](/workflow/using-libraries) for more information.
### Expo modules included in the `expo` package
The following Expo modules are brought in as dependencies of the `expo` package:
- [`expo-asset`](/versions/latest/sdk/asset) - A JavaScript-only package that builds around `expo-file-system` and provides a common foundation for assets across all Expo modules.
- [`expo-constants`](/versions/latest/sdk/constants) - Provides access to the manifest.
- [`expo-file-system`](/versions/latest/sdk/filesystem) - Interact with the device file system. Used by `expo-asset` and many other Expo modules. Commonly used directly by developers in application code.
- [`expo-font`](/versions/latest/sdk/font) - Load fonts at runtime. This module is optional and can be safely removed, however; it is recommended if you use `expo-dev-client` for development and it is required by `@expo/vector-icons`.
- [`expo-keep-awake`](/versions/latest/sdk/keep-awake) - Prevents your device from going to sleep while developing your app. This module is optional and can be safely removed.
To exclude any of these modules, refer to the following guide on [excluding modules from autolinking](#excluding-specific-modules-from-autolinking).
### Excluding specific modules from autolinking
If you need to exclude native code from Expo modules you are not using, but were installed by other dependencies, you can use the [`expo.autolinking.exclude`](/modules/autolinking/#exclude) property in **package.json**:
```json package.json
{
  "name": "...",
  "dependencies": {},
  "expo": {
    "autolinking": {
      "exclude": ["expo-keep-awake"]
    }
  }
}
```


## Migrate from React Native CLI to Expo CLI

Learn how to migrate from React Native CLI (@react-native-community/cli) to Expo CLI for any React Native project.

To migrate from React Native CLI (`npx @react-native-community/cli@latest init`) to Expo CLI, you'll need to install the `expo` package, which includes the Expo Modules API and Expo CLI. This guide covers the installation step, the benefits of using Expo CLI, and how to compile and run your project after migrating to Expo CLI.
It is strongly recommended to use Expo CLI when using other Expo tools. It is required for many tools, such as EAS Update, Expo Router, and expo-dev-client, and other features may not work as well without it.
## Install the `expo` package
In most cases, executing the following command in a project directory to install the package is all you need to do:
```sh
$ npx install-expo-modules@latest
```
For a detailed installation guide, see [Install Expo modules](/bare/installing-expo-modules).
> **info** After installing the `expo` package, you'll need to configure your project to use Expo CLI. This includes setting up Metro config, Babel preset, and native project configurations. See the [Configure Expo CLI for bundling on Android and iOS](/bare/installing-expo-modules/#configure-expo-cli-for-bundling-on-android-and-ios) section for the complete setup instructions.
## Why Expo CLI instead of React Native CLI
Expo CLI commands provide several benefits over the similar commands in `@react-native-community/cli`, which includes:
- Instant access to Hermes debugger with <kbd>j</kbd> keystroke.
- The debugger ships with [React Native DevTools](/debugging/tools/#debugging-with-react-native-devtools).
- [Continuous Native Generation (CNG)](/workflow/continuous-native-generation/) support with [`expo prebuild`](/workflow/prebuild/) for upgrades, white-labeling, easy third-party package setup, and better maintainability of the codebase (by reducing the surface area).
- Support for file-based routing with [`expo-router`](/router/introduction/).
  - [Async bundling](/router/web/async-routes) in development.
- Built-in [environment variable support](/guides/environment-variables) and **.env** file integration.
- View native logs directly in the terminal alongside JavaScript logs.
- Improved native build log formatting using Expo CLI's `xcpretty`-style tool built specifically for React Native apps. For example, when compiling a Pod, you can see which Node module included it.
- [First-class TypeScript support](/guides/typescript).
- Support for **tsconfig.json** aliases with `paths` and `baseUrl` [built-in to Metro](/guides/typescript/#path-aliases-optional).
- [Web support](/guides/customizing-metro/#adding-web-support-to-metro) with Metro. Fully typed for React Native Web.
- Modern [CSS support](/versions/latest/config/metro#css) with Tailwind, PostCSS, CSS Modules, SASS, and more.
- Static site generation with Expo Router and Metro web.
- Out of the box [support for monorepos](/guides/monorepos).
- Support for Expo tooling such as [`expo-dev-client`](/develop/development-builds/introduction), the [Expo Updates protocol](/technical-specs/expo-updates-1) and [EAS Update](/eas-update/introduction).
- Automated `pod install` execution when using `npx expo run:ios`.
- `npx expo install` selects compatible dependency versions for well-known packages.
- Automatic port detection when running `npx expo run:[android|ios]` and `npx expo start`. If another app is running on the default port, a different port is used.
- Android or iOS device launch selection shortcuts using <kbd>Shift</kbd> + <kbd>a</kbd> or <kbd>Shift</kbd> + <kbd>i</kbd> from the interactive prompt.
- Built-in support for serving your app over an [ngrok tunnel](/develop/development-builds/development-workflows/#tunnel-urls).
- Develop on any port with any entry JavaScript file.
We recommend Expo CLI for most React Native projects that target Android, iOS, and/or web. It does not yet have built-in support for the most popular out-of-tree platforms, such as
Windows and macOS. If building for these platforms, you can utilize Expo CLI for the supported platforms and `@react-native-community/cli` for the others.
## Compile and run your app
After installing the `expo` package, you can use the following commands which are alternatives to `npx react-native run-android` and `npx react-native run-ios`:
```sh
$ npx expo run:android
$ npx expo run:ios
```
When building your project, you can choose a device or simulator by using the `--device` flag. This also applies to any iOS device that is connected to your computer.
## Start the bundler independently
`npx expo run:[android|ios]` automatically starts the bundler/development server. If you want to independently start the bundler with `npx expo start` command, pass the `--no-bundler` to the `npx expo run:[android|ios]` command.
## Common questions
Note: Can I use Expo CLI without installing the Expo Modules API?
---
Expo Modules API is also installed when you install the `expo` package with `npx install-expo-modules`. If you want to try out Expo CLI for now without installing Expo Modules API, install the `expo` package with `npm install` and then configure the **react-native.config.js** to exclude the package from autolinking:
```js react-native.config.js
module.exports = {
  dependencies: {
    expo: {
      platforms: {
        android: null,
        ios: null,
        macos: null,
      },
    },
  },
};
```
> **Note:** Without Expo API Modules installed, certain features such as `expo-dev-client` or `expo-router` are unavailable.
---
Note: Can I use prebuild for out-of-tree platforms, such as macOS or Windows?
---
Yes! Refer to the [Customized Prebuild Example repository](https://github.com/byCedric/custom-prebuild-example) for more information.
---
## Next steps
Now, with the `expo` package installed and configured in your project, you can start using all features from Expo CLI and SDK. Here are some recommended next steps to dive deep:


## Install expo-updates in an existing React Native project

Learn how to install and configure expo-updates in your existing React Native project.

`expo-updates` is a library that enables your app to manage remote updates to your application code. It communicates with the configured remote update service to get information about available updates. This guide explains how to set up a bare React Native project for use with [EAS Update](/eas-update/introduction), a hosted remote update service that includes tools to simplify installation and configuration of the `expo-updates` library.
Note: Do you use Continuous Native Generation (CNG) in your project?
---
You may be reading the wrong guide. To use `expo-updates` in a project that uses [CNG](/workflow/continuous-native-generation/), see [EAS Update "Get started"](/eas-update/getting-started/).
---
## Prerequisites
**The `expo` package must be installed and configured.** If you created your project with `npx @react-native-community/cli@latest init` and do not have any other Expo libraries installed, you will need to [install Expo modules](/bare/installing-expo-modules) before proceeding.
## Installation
To get started, install `expo-updates`:
```sh
$ npx expo install expo-updates
```
Then, install pods for iOS:
```sh
$ npx pod-install
```
## Configuring expo-updates library
Apply the changes from the diffs from the following sections to configure `expo-updates` in your project.
### JavaScript and JSON
Run `eas update:configure` to set the `updates` URL and `projectId` in **app.json**.
```sh
$ eas update:configure
```
Modify the `expo` section of **app.json**. If you created your project using `npx @react-native-community/cli@latest init`, you will need to add the following changes including the [`updates` URL](/versions/latest/config/app/#url).
> The example `updates` URL and `projectId` shown below are used with EAS Update. The EAS CLI sets this URL correctly for the EAS Update service when running `eas update:configure`.
<DiffBlock source="/static/diffs/expo-updates-app-json.diff" />
If you want to set up a [custom `expo-updates` server](https://github.com/expo/custom-expo-updates-server) instead, add your URL to `updates.url` in **app.json**.
```diff
diff --git a/app.json b/app.json
index 0000000..1111111 100644
--- a/app.json
+++ b/app.json
@@ -1,7 +1,7 @@
   "expo": {
     "name": "MyApp",
-    "updates": {
-      "url": "https://u.expo.dev/[your-project-id]"
-    }
+    "updates": {
+      "url": "http://localhost:3000/api/manifest"
+    }
   }
 }
```
### Android
Modify **android/app/build.gradle** to check for the JS engine configuration (JSC or Hermes) in Expo files:
<DiffBlock source="/static/diffs/expo-updates-android-build-gradle.diff" />
Modify **android/app/src/main/AndroidManifest.xml** to add the `expo-updates` configuration XML so that it matches the contents of **app.json**:
<DiffBlock source="/static/diffs/expo-updates-android-manifest.diff" />
If using the updates server URL (a custom non-HTTPS update server running on the same machine), you will need to modify **android/app/src/main/AndroidManifest.xml** to add the update server URL and enable `usesCleartextTraffic`:
<DiffBlock source="/static/diffs/expo-updates-android-manifest-cleartext.diff" />
Add the Expo runtime version string key to **android/app/src/main/res/values/strings.xml**:
<DiffBlock source="/static/diffs/expo-updates-strings-xml.diff" />
### iOS
Add the file **Podfile.properties.json** to the **ios** directory:
```json ios/Podfile.properties.json
{
  "expo.jsEngine": "hermes"
}
```
Modify **ios/Podfile** to check for the JS engine configuration (JSC or Hermes) in Expo files:
<DiffBlock source="/static/diffs/expo-updates-ios-podfile.diff" />
Using Xcode, add **Expo.plist** file to **ios/your-project/Supporting** with the following content to match the contents of **app.json**:
```xml Expo.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>EXUpdatesCheckOnLaunch</key>
    <string>ALWAYS</string>
    <key>EXUpdatesEnabled</key>
    <true/>
    <key>EXUpdatesLaunchWaitMs</key>
    <integer>0</integer>
    <key>EXUpdatesRuntimeVersion</key>
    <string>1.0.0</string>
    <key>EXUpdatesURL</key>
    <string>http://localhost:3000/api/manifest</string>
  </dict>
</plist>
```
## Next steps
- To start using EAS Update with EAS Build, see the EAS Update [Get started](/eas-update/getting-started/).
- See [`expo-updates` API reference](/versions/latest/sdk/updates/) for more information on how to use the library.
- See how to use [EAS Update with a local build directly](/eas-update/standalone-service/).
- It is also possible to use `expo-updates` with a custom server that implements the [Expo Updates protocol](/technical-specs/expo-updates-1/). See [`custom-expo-updates-server` README](https://github.com/expo/custom-expo-updates-server#readme).


## Install expo-dev-client in an existing React Native project

Learn how to install and configure expo-dev-client in your existing React Native project.

The following guide explains how to install and configure `expo-dev-client` in an existing React Native project.
Note: Do you need to create a new project?
---
If you're starting with a new project, create it using the `with-dev-client` template:
```sh
$ npx create-expo-app -e with-dev-client
```
---
Note: Do you use Continuous Native Generation (CNG) in your project?
---
To use `expo-dev-client` in a project that uses [CNG](/workflow/continuous-native-generation/), see [Create a development build](/develop/development-builds/create-a-build/).
---
## Prerequisites
**The `expo` package must be installed and configured.** If you created your project with `npx @react-native-community/cli@latest init` and do not have any other Expo libraries installed, you will need to [install Expo modules](/bare/installing-expo-modules) before proceeding.
Step 1: 
## Install expo-dev-client
Add the `expo-dev-client` library to your **package.json**:
```sh
$ npx expo install expo-dev-client
```
If your project has an **ios** directory on disk, run the following command to fully install the native code for `expo-dev-client`:
```sh
$ npx pod-install
```
If your project doesn't have an **ios** directory, you can skip this step.
Step 2: 
## Configure deep links
Expo CLI uses a deep link to launch your project, and it's also useful if you use plan to [use `expo-dev-client` for launching preview updates](/eas-update/getting-started/) if you have added a custom deep link scheme to your project.
If you haven't configured a `scheme` for your app yet to support deep linking, then use `uri-scheme` library to do this for you.
```sh
$ npx uri-scheme list
$ npx uri-scheme add your-scheme
```
For more information, see the [`uri-scheme` library](https://www.npmjs.com/package/uri-scheme).
Step 3: 
## Build and install the app
Create a debug build of your app using the tools of your choice. For example, you can do this [locally with Expo CLI](/guides/local-app-development/) or [in the cloud with EAS Build](/develop/development-builds/create-a-build/).


## Native project upgrade helper

View file-by-file diffs of all the changes you need to make to your native projects to upgrade them to the next Expo SDK version.

If you manage your native projects (previously known as bare workflow), to [upgrade to the latest Expo SDK](/workflow/upgrading-expo-sdk-walkthrough/), you have to make changes to your native projects. It can be a complex process to find which native file changes and what to update in which file.
The following guide provides diffs to compare native project files between your project's current SDK version and the target SDK version you want to upgrade. You can use them to make changes to your project depending on the `expo` package version your project uses. The tools on this page are similar to [React Native Upgrade Helper](https://react-native-community.github.io/upgrade-helper/). However, they are oriented around projects that use Expo modules and related tooling.
> Interested in avoiding upgrading native code altogether? See [Continuous Native Generation (CNG)](/workflow/continuous-native-generation/) to learn how Expo Prebuild can generate your native projects before a build.
## Upgrade native project files
Once you have [upgraded your Expo SDK version and related dependencies](/workflow//upgrading-expo-sdk-walkthrough/#how-to-upgrade-to-the-latest-sdk-version), use the diff tool below to learn about changes you need to make to your native project and bring them up to date with the current Expo SDK version.
Choose your **from SDK version** and **to SDK version** to see the generated diff. Then, apply those changes to your native projects by copying and pasting or manually making changes to the project files.
<TemplateBareMinimumDiffViewer />