npm ci: Usage, Options & Common CI Errors
The deterministic install built for CI pipelines.
npm ci installs exactly what package-lock.json specifies, deleting node_modules first for a clean, reproducible tree. It is faster and stricter than npm install - and it is what you should run in CI.
What it does
Requires both package.json and package-lock.json (or npm-shrinkwrap.json). Deletes any existing node_modules, then installs the exact versions in the lockfile. It never writes to package.json or the lockfile, and it errors out if the two are out of sync.
Common usage
npm ci # clean install from the lockfile
npm ci --omit=dev # production install, skip devDependencies
npm ci --ignore-scripts # skip lifecycle scripts (faster, safer)Common CI error: lockfile out of sync
CI fails with "npm error code EUSAGE / npm ci can only install packages when your package.json and package-lock.json are in sync". Someone edited package.json without regenerating the lockfile. Fix it by running npm install locally, then committing the updated package-lock.json - do not switch CI to npm install to paper over it.
# locally, regenerate and commit the lockfile:
npm install
git add package-lock.json && git commit -m "sync lockfile"Key options
| Flag | Effect |
|---|---|
| --omit=dev | Skip devDependencies (production install) |
| --ignore-scripts | Skip lifecycle scripts |
| --no-audit | Skip the audit step (faster CI) |
| --prefer-offline | Use cache before hitting the registry |
Using this in CI
Node tooling on a runner differs from your machine in three ways that matter: CI=true is set, there is no TTY, and the Node major may not be the one you develop on.
- Pin the Node major with
setup-nodeand inengines. Native modules resolve different prebuilt binaries per major. CI=truechanges behaviour in several tools, most often by promoting warnings to errors or disabling interactive prompts.- Commands that expect a TTY will hang. Pass the non-interactive or
--yesflag explicitly. - Use
npm execornode_modules/.binrather than assuming a globally installed binary is on PATH.