Run npm ci when you want exactly what package-lock.json describes, and npm install when you intend to add or update a dependency. The first fails loudly if the lockfile and package.json disagree. The second quietly rewrites the lockfile, which is how unreviewed versions reach your machine.
What npm ci does differently
According to the npm documentation, npm ci is meant for automated environments, but also for any situation where you want a clean install of your dependencies. The documented differences are practical:
- The project must already have a package-lock.json or npm-shrinkwrap.json.
- If the lockfile does not match package.json, npm ci exits with an error instead of updating the lockfile.
- It installs the whole project at once. You cannot add a single package with it.
- If node_modules already exists, it is removed before the install begins.
- It never writes to package.json or to the lockfiles. Installs are essentially frozen.
That last point is the security value. A frozen install means the versions and integrity data you reviewed in the pull request are the ones that land on disk.
Why this matters on a laptop
Most people use npm install out of habit. It is fine on day one of a project. The trouble starts when you pull a branch, run npm install, and the tool resolves a range to a newer version than anyone reviewed. The lockfile changes in your working tree, and you may commit it without noticing.
If a dependency was compromised an hour ago and your range allows it, a habit of running install is how you meet it first.
A simple rule of thumb
- After cloning or pulling: run npm ci.
- When changing dependencies on purpose: run npm install with the package name, then read the lockfile diff before committing.
- When the install fails on a mismatch: treat it as a finding. Someone changed package.json without the lockfile, or the other way around.
One gotcha from the docs
If you created your lockfile by running npm install with flags that affect the shape of the tree, such as the legacy peer deps or install links options, the documentation says you must pass the same flags to npm ci or expect errors. The suggested fix is to set them in a project level .npmrc and commit that file, so both commands agree.
What a lockfile does not do
A lockfile pins versions and records integrity hashes. It does not tell you whether a pinned version is malicious or vulnerable. Pair it with a review of new packages, a delay before adopting fresh releases, and regular scanning of what the lockfile resolves.
If you want a quick look at what your projects actually resolve, Safeguard offers SBOM and dependency scanning, and there is a free scan at gold.safeguard.sh/scan.
Click through it at your own pace, or open it full screen.
Quick check
Can npm ci add a new package?
No. The npm documentation says it installs entire projects at a time and individual dependencies cannot be added with it.
Will npm ci change my lockfile?
No. It never writes to package.json or the lockfiles. If they disagree, it stops with an error.
Sources
Last reviewed: 19 October 2026.