Skip to content
Latchkey

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

.github/workflows/ci.yml
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.

Terminal
# locally, regenerate and commit the lockfile:
npm install
git add package-lock.json && git commit -m "sync lockfile"

Key options

FlagEffect
--omit=devSkip devDependencies (production install)
--ignore-scriptsSkip lifecycle scripts
--no-auditSkip the audit step (faster CI)
--prefer-offlineUse cache before hitting the registry

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →