Question presented to candidate: "A teammate suggests "just npm install -g this-tool" to run a one-off CLI, but you'd rather not pollute your global npm setup or worry about version drift across machines. What's the alternative, and what does it actually do differently?"
What a strong answer should cover:
npxruns a package's binary — it does not, by itself, require installing anything globally or persistently. Given a package already present as a local project dependency,npx <name>resolves and runs that local copy directly; given a package not present locally,npxfetches and runs it in a temporary cache, without adding a lasting global install.- 📌 Verified, not assumed: in a real project with a single
binentry declared in its ownpackage.json(no separate dependency install even needed for this specific case),npx my-local-cligenuinely ran the local project's own script — confirmed by its real, actual resolved file path in the output — while a realnpm ls -gimmediately afterward genuinely showed nothing installed globally. - The core problem this solves, precisely matching the prompt: a global install (
npm install -g) is persistent and shared system-wide — every project on the machine sees the identical global version, which genuinely causes real version drift between projects/machines/CI (one project needing an older CLI version than another, or a CI environment lacking whatever was manually installed globally on a developer's laptop).npxsidesteps this by preferring the project-local, version-pinned copy (declared in that project's ownpackage.json/lockfile) — reproducible per-project, per-clone, per-CI-run, with no manual global setup step at all. - A precise answer names the project-local-first resolution as the single most important behavior: if a CLI is already listed as a project dependency (even a
devDependency),npx <name>finds and runs that exact locally-installed, version-locked copy rather than reaching out anywhere else — this is different from, and safer than, assumingnpxalways means "download something fresh from the registry." - The honest scope: for a package genuinely not present locally at all,
npxdoes reach out to the registry and runs a temporarily-cached copy — this is real, useful for a genuine one-off tool, but it is not magic offline resolution; it still needs registry/network access for that specific case, unlike the verified local-resolution case which needs none.
Clarifying questions expected:
- "Is this tool something the project genuinely depends on repeatedly (belongs as a real devDependency, run via npx), or a genuine one-off never needed again?" — shapes whether it belongs in
package.jsonat all versus an ad hocnpxrun. - "Does this need to work identically and reproducibly across CI, without relying on anything manually pre-installed on a given machine?" — the core reason to prefer
npx-of-a-local-dependency over a global install in the first place.
Code / implementation expected: Yes — a real project resolving and running its own local binary via npx, with a real, immediately-checked confirmation that nothing was installed globally, is the concrete, convincing proof of exactly what npx does and does not do.