In an Expo project, what is the difference between npx expo install --check and --fix, and how would you use each in CI?
answer
- validate versus correct
- --check prompts locally
- non-zero exit when not interactive
- --fix always installs
- expo.install.exclude for deliberate pins
basics
~10 snpx expo install --check compares installed packages with the SDK's expected versions and reports mismatches, prompting to fix when interactive and exiting non-zero in CI. --fix installs the expected versions unconditionally.
solid answer
~40 sBoth compare the project's dependencies with the versions the installed Expo SDK expects. `--check` validates: it lists mismatches and, in an interactive terminal, asks whether to fix them; in CI it cannot prompt, so it exits with a non-zero code, which makes it a gate that keeps the lockfile unchanged. `--fix` corrects: it installs the expected versions wherever needed, in any environment, and is what you run after bumping `expo` during an upgrade. Both accept package names to limit the scope, such as `npx expo install react-native --check`. A package deliberately held at another version goes into `expo.install.exclude` in `package.json`, which removes it from `npx expo install`, `npx expo-doctor` and `npx expo start` checks. So CI runs `--check` and fails the build; a developer runs `--fix` and commits the result.
code
bash · 6 lines# CI: validate only; exits non-zero on any mismatch and changes nothing
npx expo install --check
# Local: correct every mismatch, then review and commit the diff
npx expo install --fix
git diff package.jsongo deeper
Know that --check reports packages that do not match the SDK and --fix installs the expected versions.
Explain the interactive prompt versus the non-zero exit in CI, scoping by package name, and install.exclude.
Gate CI on --check, keep --fix a reviewed local step, and trace drift back to its source such as bots or plain npm installs.
Make dependency alignment an enforced policy with recorded exceptions, so SDK upgrades start from a known-clean state.
## Two flags, two jobs Every Expo SDK has a **known-versions map**: the versions of Expo packages and popular third-party libraries that were tested with that SDK's React Native. `npx expo install` uses it to install; the `--check` and `--fix` flags use it to **audit** what is already installed. | | `npx expo install --check` | `npx expo install --fix` | |---|---|---| | Purpose | validate | correct | | Interactive terminal | lists mismatches, asks whether to fix | installs expected versions | | CI / non-interactive | exits non-zero on mismatches, changes nothing | installs expected versions | | Changes `package.json` and lockfile | only if you accept the prompt | yes, when something is wrong | | Typical use | a CI gate, a quick local audit | after upgrading `expo`, repairing drift | When everything matches, both report that dependencies are up to date. ## Scoping and output - Pass package names to limit the audit: `npx expo install react-native expo-sms --check`. - `npx expo install expo-camera` and `npx expo install expo-camera --fix` serve the same purpose for a single package; `--fix` without names is the whole-project version. - `--json`, used with `--check`, prints the mismatches as JSON for tooling and exits non-zero when anything is outdated. ## Deliberate exceptions Sometimes you need a version the SDK does not map, for example a library release with a fix you depend on. Add it to `expo.install.exclude` in `package.json`: ```json { "expo": { "install": { "exclude": ["react-native-reanimated"] } } } ``` Excluded packages are skipped by `npx expo install`'s checks, by `npx expo-doctor`, and by the dependency check `npx expo start` runs at startup. The CLI prints which packages it skipped, so the exception stays visible. ## Using them in CI A sound setup for a pet-adoption app's pipeline: 1. **Install from the lockfile** exactly as committed. 2. **Run `npx expo install --check`.** In CI it cannot prompt, so any mismatch exits non-zero and fails the job without changing files. 3. **Never run `--fix` in CI** as a silent repair: it would build something different from what was reviewed, and the corrected lockfile would be lost with the job. 4. **Fix locally.** A developer runs `npx expo install --fix`, reviews the diff, and commits it. This keeps the rule simple: CI detects drift; people correct it. ## Where drift comes from - A developer ran `npm install some-native-lib` instead of `npx expo install`. - A dependency bot bumped a library past the version the SDK maps. - `expo` was upgraded but its companion packages were not. - A merge resolved `package.json` conflicts by picking the higher versions. Each of these produces a project that may still build, but on combinations nobody tested. ## The start-up check `npx expo start` performs the same validation when it launches, unless you are offline or `EXPO_NO_DEPENDENCY_VALIDATION` is set, and warns that listed packages "should be updated for best compatibility" with the installed `expo` version. That warning is the same signal `--check` gives, just earlier and easier to ignore. ## A worked example A pet-adoption app's CI starts failing on a Monday. The log from `npx expo install --check` lists `react-native-screens` at a version newer than SDK 57 maps. The history shows a dependency bot bumped it over the weekend. The fix is not to relax the gate: a developer runs `npx expo install --fix`, which moves the package back to the mapped range, reviews the diff and commits it. The team then configures the bot to leave SDK-mapped packages alone, because those move with SDK upgrades, not on their own. If the newer version had been needed for a real bug, the right move would have been an explicit version plus an `expo.install.exclude` entry, not a silent bump. ## Mistakes to avoid - Treating `--check` in CI as advisory; its non-zero exit is the whole point. - Excluding a package to silence a warning without writing down why. - Running `--fix` and committing without reading the diff, which can hide a major version jump.
- Why not just run npx expo install --fix in CI and carry on?It would build a dependency set nobody reviewed, and the corrected `package.json` and lockfile would vanish with the job, so the drift stays in the repository. Running `--check` makes CI fail loudly; a developer then runs `--fix` locally, reads the diff and commits it.
- A library must stay on a version the SDK does not map; how do you stop the checks failing?List it in `expo.install.exclude` in `package.json`. `npx expo install --check`, `npx expo-doctor` and the start-up validation then skip it, and the CLI notes the exclusion, so the exception is visible and deliberate rather than a warning everyone learns to ignore.
saying these in an interview costs you the question
- --check and --fix both change package.json by default
- --check in CI only prints warnings and exits successfully
- Running --fix in CI is a safe way to keep builds green
- install.exclude only affects npx expo install, not doctor or start
- --fix checks versions but never installs anything