Expo prebuild writes the android and ios folders from your config, and expects to write them again.
npx expo prebuild turns a JavaScript project into two native projects. It copies a template matched to the Expo SDK version you have installed, runs every config plugin in your app config over that template, and leaves you an android folder and an ios folder. Expo's own sentence for the result: this creates the android and ios directories for running your React code. It also quietly changes two fields in your package.json. And it is designed to be run again, which is the part that catches people who have edited the output by hand. Every quote and flag below comes from Expo's documentation, read on 17 October 2026. If you are asking because a tool generated the project, start with who owns AI generated code, because the command only works on a project that is genuinely yours.
What follows is what the command generates, what it touches outside those two folders, whether you can undo it, and what changes when something else wrote the project for you. One answer up front, because the internet is years out of date on it: there is no eject step any more.
Start hereThe short version
Two folders out, two package.json fields changed, and no undo command.
Treat the android and ios folders as output, not source. Expo describes them as generated on demand and discarded once the native project is compiled into a native app, and a new project adds both to .gitignore for you. That arrangement has a name, Continuous Native Generation, and it is the assumption behind every upgrade instruction Expo publishes. The things you are supposed to keep are the app config and the config plugins, because those are the inputs the command reads.
The honest gap in the documentation is reversibility. Expo publishes no revert command. What it publishes instead is an instruction to commit first, so your version control is the undo. Run it on a dirty tree and you are relying on the warning prompt to save you, and that prompt is skipped in CI.
What does npx expo prebuild actually do?
It runs in two steps, and knowing which step did something to your project is most of the debugging. Step one: Expo copies a project template. Expo says prebuild begins by initialising new native projects from a template corresponding to each Expo SDK version, and that the template comes from the npm package expo-template-bare-minimum, picked by the version of expo installed in your project. Step two: it evaluates your app config and runs the config plugins over those template files. The output is an android folder and an ios folder that Gradle and Xcode can compile.
That second step is why the command exists rather than a folder of instructions. Expo's example is a camera library, which needs a permission string added to AndroidManifest.xml on Android and Info.plist on iOS. Paste those by hand and you now own two native files you did not write and cannot trace back to the package. A config plugin does the same edit every time the command runs, which is how one line in the config ends up setting a value in two different native file formats.
Continuous Native Generation is the name for the arrangement this assumes, and you will meet the phrase in the documentation whether you asked for it or not. The idea is that native projects are short-lived. Expo says they are generated only when needed, such as when debugging or building, and that the generated source code and configuration are discarded once the native project is compiled into a native app. If you inherited this project rather than chose it, that is the sentence to hold on to. The two folders you are about to create are not the codebase. They stand to your app config roughly as a compiled binary stands to source. That is why an instruction that begins with open ios and edit this file is often telling you to change a file that will not survive.
Two limits worth knowing before you run anything. Prebuild covers Android and iOS only, and --platform ios or --platform android runs it for one of them. And Expo is blunt about who should not use it: for an existing React Native project where the native projects are managed manually, it says do not run prebuild, because it may overwrite your manual customisations. Read that line before you run the command on a codebase somebody hand-tuned.
Check yours
What happens to your change when prebuild runs again
Tick what you did to the project. The answers are what Expo's own documentation says happens, not what the command happens to do today.
Nothing ticked. A project where every native setting lives in the app config and in config plugins can be regenerated as often as you like, which is the whole point of the command.
Which files does it change outside android and ios?
Your package.json, in two places, and Expo lists them as side effects rather than features. It modifies the scripts field to replace expo start --android and expo start --ios with expo run:android and expo run:ios. And it modifies the dependencies field. Expo says work is in progress to eliminate these side effects, and that ideally the command would generate the two native projects and leave the rest of the project untouched. For now, the scripts change is the one Expo names as altering how a developer works on the app before and after the run.
The dependency edit has a tail. When dependencies change, prebuild reinstalls packages with the package manager it infers from your lockfile, and you can force the choice with --npm, --yarn or --pnpm. You will also see a warning when your React and React Native versions differ from the ones the template expects. --skip-dependency-update react-native,react holds those versions where they are, and --no-install skips the install entirely, which is the fast way to see what the command generates without changing your node_modules.
One file it does not touch is the one people expect it to. Expo says the android and ios directories are automatically added to .gitignore when you create a new project, which is the template doing that rather than the command. If you need them ignored in an older project, you add /android and /ios yourself. Everything else prebuild changes, Expo says, can be left in place and committed to git to keep the diff small the next time you run it.
Running the command locally also costs you a toolchain. Compiling what it generates means Gradle and Android Studio for Android, and Xcode on a Mac for iOS, which is the same bill you meet when you work out what it costs to publish an app. Generating the folders is free and quick. Building them is the part that wants a machine.
Can you undo an expo prebuild?
There is no undo command. That is a claim about an absence, so here is how it was checked: Expo's prebuild and Continuous Native Generation page, its Adopt Prebuild guide, the Expo CLI reference and the documentation's own Markdown index, all read on 17 October 2026. None of them documents a revert operation of any kind. What Expo documents instead is git. The Adopt Prebuild guide says to make sure you have committed your changes in case you want to revert, and adds that the command will warn you about this too. That warning is the uncommitted-changes prompt you get with the --clean option, which is skipped in CI and can be disabled with EXPO_NO_GIT_STATUS=1.
So the folders themselves are cheap to lose. Three other things are not. A hand edit inside android or ios, which Expo says you risk losing the next time you run the command with --clean. The package.json scripts rewrite, which changes how you start the app and stays until you change it back. And the quietest one: once those two folders exist in your repository, a cloud build stops generating them, because Expo says it will not run prebuild on a project that has them, in order to avoid overwriting changes you may have made. That is a durable change in how your builds work, made by the presence of two directories.
This is also where the word people are reaching for has stopped existing. Expo's documentation states that the expo eject command was removed in SDK 46, in 2022, and that ejecting is not an operation any more. The glossary carries no entry with the word in it, and the CLI reference lists no such command. The old pairing of a managed workflow you leave for a bare workflow is gone with it: the glossary entry for bare workflow is marked deprecated and says Expo no longer separates the two. Running prebuild is not a one-way door you walk through, it is a build step you can run as often as you like.
If you would rather look before you leap, Expo documents two ways to. --no-install generates the folders without touching your installed packages. And the VS Code Expo extension has a Preview Modifier command that shows you the native file prebuild would generate, so you can check an expected change against a real file before any of it lands on disk.
A last practical note. A regenerated project that compiles and then dies on launch is usually a different problem from a bad regeneration, and chasing it as a config issue wastes a day. The first move is a clean run. If the app still starts and falls over, that is debugging a crash, and it wants a stack trace rather than another prebuild.
Expo, Adopt Prebuild, page last updated 28 July 2026, read 17 October 2026
Generated every time, or committed once and maintained
Both columns are supported, and the choice is which maintenance you prefer. Expo calls generating them the recommended approach and the other one high maintenance overhead with freedom to customise.
| The question | Generated by prebuild | Native folders in your repo | Same either way |
|---|---|---|---|
| Who writes the android and ios folders | The command, from a template plus your config | You, once, and then you keep them | No |
| In git by default | No, a new project gitignores both | Yes, versioned and reviewed like any code | No |
| Where a camera permission string lives | app.json, written into Info.plist on each run | Info.plist, edited by hand | No |
| A cloud build regenerates them | Yes | No | No |
| An SDK upgrade touches native files | Bump the versions, run it again | Merge the template changes yourself | No |
| A hand edit inside the folders survives | No | Yes | No |
Do you have to run it on a project a tool generated for you?
Not to ship. Newly writes a real React Native and Expo project you own, and the steps that need a native build are handled on its side: it uploads the iOS build to TestFlight, publishes to Google Play internal testing, and builds a standalone Android APK. Nothing in that path asks you to open a terminal. It is $25 a month, with no free tier.
You reach for the command when you want the native project in front of you. Opening the app in Xcode or Android Studio, attaching a native debugger, archiving a build by hand, or adding native code that no config plugin covers: all of those need the folders to exist, and prebuild is how they come to exist. Two-way GitHub sync is the practical route, because it puts the project on your machine as an ordinary repository, and an ordinary Expo project is exactly what the command expects to find.
The decision to make once, rather than per run, is whether those folders go into the repository. Leave them out and the project keeps working the way Expo intends: the config is the source, upgrades are a version bump and another run, and a cloud build regenerates the native side for you. Commit them and you have taken the native projects on, with the freedom and the maintenance that comes with them. Neither is wrong. What is worth knowing is that the documentation, the upgrade instructions and the cloud builds all assume the first column, so a project that has quietly moved to the second one stops matching what you read.
One limit is worth saying plainly, because it is the step no generator removes. Apple requires the content owner to submit the app, so no builder presses submit on your behalf. Prebuild does not change that either way: it produces a native project, not a review submission. The sequence from a generated project to a live listing is publishing to the App Store, and the command on this page is optional at every step of it.
Questions people ask about expo prebuild
It generates the native android and ios projects for a React Native app from your app config. Expo's documentation describes the output in one line: this creates the android and ios directories for running your React code. Underneath, the command starts from a template that matches the Expo SDK version installed in your project, taken from the npm package expo-template-bare-minimum, then runs every config plugin listed in your app config over those template files. Prebuild supports Android and iOS only. There is nothing to generate for web, because a web app runs in a browser.
Describe the app, then open the folders if you want them
The project is a standard React Native and Expo codebase, so every command on this page works on it. Keep the native folders generated and you keep the upgrade path. Commit them the day you actually need to, and know that you did.
Start building