npx stands for Node Package Execute. npx is one of the most-used tools in Node.js and yet its internals are not commonly understood. Most developers think that npx just downloads and runs packages. That's only the last step.
In practice, npx resolves an executable through a strict, ordered search process, and will install a package only if nothing is found locally or globally.
Overview
npx does the following:
npx searches for an executable and runs it.
It downloads it temporarily and runs the executable, if the executable is not available locally or globally.
Consider npx as an executable resolver, not a package manager.
Note
npxcan both install and execute a package only if that package exposes an executable (via thebinfield).If the package is a CLI tool,
npxwill:
- Download it temporarily (if not already available)
- Execute its binary
- Remove it after execution (unless cached)
Examples
npx vite
viteis a CLI package that exposes a binary.npxinstalls it (if missing) and runs the Vite dev server.
npx express
Theexpresspackage is a library, not a CLI. It does not expose an executable, sonpx expressfails.Key Rule
npxworks only with packages that provide executables.
Libraries without abinentry cannot be executed usingnpx.
Exact Resolution Order (Quick Scan)
What npx does?
Searches for a file and executes it.
Search Step-1
Searches for package.json in current working directory
Searches for name key in the json
Searches for bin key
Search Step-2
Searches for node_modules\.bin\hello in current working directory
And executes this file
Search Step-3
Searches for hello in global npm folder
And executes this file
Search Step-4
Searches for hello package in npx cache
And executes this file
Search Step-5
Searches for hello package in npm registry
Prompts to install the package if found
Downloads and installs
Execution stops immediately when a match is found.
Deep Explanation: How Each Step Works
Below is the Deep Explanation of each Step
Step: Project package.json — Project-Scoped CLI (Highest Priority)
npx first checks whether the current working directory contains a package.json.
If found, it inspects two fields:
→ name
→ bin
If the executed command matches:
→ the project name
→ a key exposed in the bin field
then npx executes the mapped file directly from the project, without any global installation.
Minimal Working Example (Test This Locally)
Create a new project folder
→ Open a terminal
→ Run:
mkdir hello-project
cd hello-project
Initialize package.json
→ Run:
npm init -y
→ Update package.json:
{
"name": "hello",
"version": "1.0.0",
"bin": {
"hello": "./index.js"
}
}
Create the executable file
Folder structure:
hello-project/
├── package.json
└── index.js
→ Create index.js:
#!/usr/bin/env node
console.log("Hello from project-scoped CLI");
Make the file executable (Linux / macOS)
→ Run:
chmod +x index.js
→ Windows users can skip this step
Run the command using npx
→ Execute:
npx hello
→ Output:
Hello from project-scoped CLI
What Happens Internally
When you run npx hello, npx performs the following:
→ Detects package.json
→ Reads name → hello
→ Resolves bin → ./index.js
→ Executes the mapped file
→ No downloads
→ No global installs
→ No cache lookup
Why This Matters
→ Enables project-scoped CLIs
→ Prevents global version conflicts
→ Ensures project and CLI stay in sync
→ Ideal for internal tooling
Step 2: Local node_modules/.bin (Preferred Execution)
If Step 1 fails, npx checks the local project’s executable directory:
./node_modules/.bin/hello
This directory is automatically created by npm when a dependency exposes a bin field in its package.json.
Example: Local CLI Installation
npm install hello-cli
This produces the following structure:
project-root/
├─ package.json
├─ node_modules/
│ ├─ .bin/
│ │ ├─ hello (macOS / Linux)
│ │ ├─ hello.cmd (Windows)
│ │ └─ hello.ps1 (Windows PowerShell)
│ └─ hello-cli/
│ ├─ package.json
│ └─ index.js
The .bin files are shims generated by npm that point to the actual executable defined in the package’s bin field.
Execution
npx hello
npx resolves and executes:
./node_modules/.bin/hello
No global lookup occurs once a local match is found.
Key rule
Local project executables always override global ones.
This guarantees:
- Version consistency per project
- Predictable CLI behavior
- Reproducible development and CI environments
Step 3: Global npm Binary Folder
If no local executable exists, npx checks the global npm executable path.
In modern npm versions, the npm bin -g command no longer exists. Instead, npx derives the global binary location from the global npm root:
npm root -g
Example (Windows):
C:\Users\username\AppData\Roaming\npm\node_modules
Global CLI executables are exposed one level above this directory:
C:\Users\username\AppData\Roaming\npm\
If a matching executable (for example hello.cmd or hello) exists in this location and is available in the system PATH, npx executes it immediately.
Reason for lower priority
Global CLIs:
- Are shared across all projects
- Can introduce version mismatches
- Reduce reproducibility across environments
For this reason, npx always prefers project-local binaries over global ones.
Step 4: npx Cache — Fast Reuse
If the executable is still not found locally or globally, npx checks its local execution cache.
This cache is maintained by npm and reused by npx to avoid unnecessary network calls.
What the npx cache does
- Stores previously downloaded CLI packages (temporary installs)
- Reuses exact package versions across executions
- Eliminates repeated downloads from the npm registry
- Significantly improves execution speed for recurring commands
Where the cache lives
npx uses npm’s cache directory.
Check the active cache path:
Check the active cache path:
npm config get cache
Example output:
- Windows
C:\Users\<username>\AppData\Local\npm-cache
- Linux / macOS
/home/<username>/.npm
npx creates and manages its execution cache inside this directory:
Step 5: npm Registry (Last Resort)
When all previous steps fail, npx queries the npm registry.
If a hello-named package does exist:
- The package is downloaded
- Its
binentry is resolved - The executable is run immediately
- The package is cached
Example:
npx create-react-app my-app
Nothing is installed globally, nor saved to package.json.
This behavior is tightly integrated with Node.js, npm’s binary linking system, and shebang-based execution.
Mental Model to Remember
npx = resolve an executable, not install a dependency.
Installation occurs only when resolution fails.
Final Takeaway
-
npxis a command runner - Local project tools always win
- Global tools are fallback
- Cache avoids re-downloads
- The registry fetch is the last step
Use npx when you want:
- One-off CLI usage
- Zero global installs
- Version-safe tooling
- Clean developer environments
Questions to Think About
Q1: If no version is specified, how does npx know which version to download?
Q2: What if the same command exists locally and globally?
Q3: Why is node_modules/.bin preferred over global binaries in npx resolution?


Top comments (0)