Skip to content

/commands/nodejs/node-run-package-json-script

node --run build: run a package.json script without npm

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash) · v24.20.0updated
tool
Node.js
versions
Node.js 22+
os
any

node --run build runs the build script from the nearest package.json, the same command npm run build would run, but without starting npm. It was added in Node.js 22.0.0. It is meant for quick local scripts: it does not run pre/post scripts and sets fewer environment variables than npm.

Run a script

bash
cat > package.json <<'EOF'
{
  "name": "app",
  "scripts": {
    "prehello": "echo this pre script is skipped",
    "hello": "node -e \"console.log('hello from', process.env.NODE_RUN_SCRIPT_NAME)\"",
    "args": "node print-args.js"
  }
}
EOF
echo 'console.log(process.argv.slice(2));' > print-args.js
node --run hello
node --run args -- --watch src

Output

hello from hello
[ '--watch', 'src' ]

Only hello runs; the prehello script that npm run hello would run first is ignored. Instead of npm's variables, node --run sets NODE_RUN_SCRIPT_NAME (the script name) and NODE_RUN_PACKAGE_JSON_PATH (the package.json it read), and arguments after -- are appended to the command.

A script that does not exist

bash
echo '{ "name": "app", "scripts": { "build": "echo building" } }' > package.json
node --run biuld 2>&1 | grep -v "^$" | sed 's/ for .*package.json$/ for package.json/'
exit "${PIPESTATUS[0]}"

Output · exit 1

Missing script: "biuld" for package.json
Available scripts are:
  build: echo building

Node.js prints the missing name and the available scripts and exits with code 1, much like npm's Missing script error. node --run with no name is an error (--run requires an argument); use npm run to list scripts.

node --run vs npm run

Behaviournode --runnpm run
Starts npmNoYes
pre and post scriptsNot runRun (prebuild, postbuild)
node_modules/.bin on PATHYes, from the current folder and its parentsYes
EnvironmentNODE_RUN_SCRIPT_NAME and NODE_RUN_PACKAGE_JSON_PATH onlynpm_lifecycle_event, npm_package_* and npm_config_* variables
Workspaces (--workspace)Not supportedSupported
Arguments after --Appended to the commandAppended to the command
Shell on Windowscmd.execmd.exe (script-shell can change it)

The script is run by the system shell: /bin/sh on Linux and macOS, cmd.exe on Windows. A script such as echo $HOME therefore prints the literal text on Windows with both tools. Write cross-platform scripts as node -e or small .js files, as in the example above.

Pitfalls

  • Scripts that call npm run other still start npm, so the speed gain is lost for chained scripts.
  • Tools that read npm_lifecycle_event, npm_package_* or npm_config_* from the environment see nothing under node --run.
  • node --run looks for package.json in the current folder and then in its parents, so it can run a script from an enclosing project when the folder has none.

How to confirm it worked

node --run exits with the script's exit code, so node --run test; echo $? shows whether the script passed. Check that your Node.js has the flag with node --help | grep -- --run; on Node.js 20 and older it fails with bad option: --run.

FAQ

Is node --run faster than npm run?

It starts faster because it does not load npm. The Node.js documentation describes it as a lighter alternative that deliberately skips features of npm run, such as pre and post scripts, to keep startup cheap.

Does node --run run prebuild and postbuild?

No. Only the named script runs. If your project relies on pre or post scripts, keep using npm run, or call the steps explicitly in one script.

How do I pass arguments with node --run?

Put them after --, for example node --run test -- --watch. Everything after the double dash is appended to the script command, as with npm run.

Sources