---
title: Node.js Package
description: Provision official Node.js distributions and run npm and npx tasks.
---

# Node.js Package

The Node.js package provisions a specific official Node.js distribution, including its bundled npm and npx. A global Node.js installation is not needed.

Load an exact release without a leading `v`:

```python
load("@nodejs@22.14.0", "nodejs", "npm_install", "npm_run", "npx_run")
```

Versions must be stable `x.y.z` releases or release candidates in the form `x.y.z-rc.N`. The exact release and host artifact must exist in the corresponding official [Node.js release index](https://nodejs.org/download/release/) or [release-candidate index](https://nodejs.org/download/rc/). Its distribution must bundle compatible npm and npx CLIs at version 7 or newer. Aliases, ranges, nightlies, other prereleases, and fallback to another version are not supported.

## `nodejs`

`nodejs` is a dependency that provisions and activates the selected distribution. It puts the managed Node.js binary directory first in `PATH`. Use it with [`run`](os.md#run) to invoke Node.js directly:

```python
load("@nodejs@22.14.0", "nodejs")
load("@os@1", "run")

run(("node", "server.js"), deps=[nodejs])
```

## `npm_install`

```python
npm_install(
    frozen_lockfile=False,
    omit=[],
    ignore_scripts=False,
    audit=True,
    deps=[],
)
```

Installs dependencies at project root with bundled npm. After `deps` finish, project-root `package.json` must exist as a regular, non-symlink file. Root-package workspaces are honored by npm.

| Argument | Default | Description |
| --- | --- | --- |
| `frozen_lockfile` | `False` | Use `npm install` when false or `npm ci` when true |
| `omit` | `[]` | Dependency types to omit; each value must be a unique `"dev"`, `"optional"`, or `"peer"` |
| `ignore_scripts` | `False` | Pass npm `--ignore-scripts`; true prevents package lifecycle scripts from running |
| `audit` | `True` | Enable or disable npm's audit request |
| `deps` | `[]` | Dependencies activated before installation, in list order |

xx forces `--global=false`; installation is always project-local. There are no `packages`, `global`, generic `args`, or `directory` arguments.

`frozen_lockfile=True` uses `npm ci`. **`npm ci` removes an existing `node_modules`, requires a lockfile, errors when lockfile and `package.json` disagree, and does not update package metadata or lockfiles.** Use non-frozen `npm install` when dependencies or metadata need updating.

Lifecycle scripts can execute package-supplied code. Set `ignore_scripts=True` when that code should not run, while recognizing packages may depend on install scripts. npm audit sends dependency information over the network to the configured registry; set `audit=False` when its network or privacy behavior is unsuitable.

`npm_install` reserves `node_modules`, `package-lock.json`, and `npm-shrinkwrap.json`. Declare it exactly once per project execution; another declaration conflicts even if options match.

The selected Node.js distribution is an implicit dependency. `npm_install` is also a root command and returns a dependency for explicit ordering:

```python
install = npm_install(frozen_lockfile=True)
npm_run("build", deps=[install])
```

Commands are independent roots and may run concurrently unless linked through `deps` as above.

## `npm_run`

```python
npm_run(script, args=[], deps=[])
```

Runs the named project-root package script as `npm run <script> -- <args...>`, using bundled npm directly through managed Node.js. Project-root `package.json` must be a regular, non-symlink file after `deps` finish.

| Argument | Required | Description |
| --- | --- | --- |
| `script` | Yes | Nonempty script name that does not begin with `-` |
| `args` | No | String arguments passed to the package script after `--` |
| `deps` | No | Dependencies activated before the script, in list order |

The selected SDK is implicit. `npm_run` registers a root command and returns its dependency.

## `npx_run`

```python
npx_run(command, version, args=[], deps=[])
```

Runs `npx <command>@<version> <args...>` using bundled npx directly through managed Node.js. It does not require `package.json`.

| Argument | Required | Description |
| --- | --- | --- |
| `command` | Yes | Nonempty command name that does not begin with `-` |
| `version` | Yes | Nonempty package version, range, or tag appended to `command` as an npm package specifier |
| `args` | No | String arguments passed after the command |
| `deps` | No | Dependencies activated before npx, in list order |

npx-level options are not modeled, and `command` cannot be an option. In particular, `npx_run` has no first-class `--yes` support. npx may use a local package, use its cache, or download a remote package and prompt. Understand and trust the selected command and registry before allowing that network activity or code execution.

The selected SDK is implicit. `npx_run` registers a root command and returns its dependency.

## Environment and Hermeticity

xx's clean task environment applies, so helpers do not inherit arbitrary variables such as `NODE_OPTIONS` from the invoking shell. After applying `deps`, helpers restore the managed Node.js binary directory to the front of `PATH` while preserving any `NODE_OPTIONS` or `NPM_CONFIG_*` values explicitly added through those dependencies. npm lifecycle child processes therefore resolve managed `node` first. npm may still discover user configuration, cache, registry, credentials, or authentication through its own behavior and the `HOME` or system configuration files available to the task. xx is not fully hermetic; those inputs, project files, npm registry state, and network can affect results.

## Distribution Download and Cache

On first use, xx reads official Node.js release metadata and checksum manifests, requires the exact host artifact, downloads it, and verifies its SHA-256 checksum. It validates the Node.js identity and bundled compatible npm/npx version before publishing the distribution to the operating-system user cache under `xx/nodejs/<version>`.

Later builds reuse a valid cached distribution. Concurrent tasks requesting the same version share setup work. Invalid cached distributions are removed and provisioned again.

Supported hosts:

- Windows x86-64 (`windows/amd64`)
- Windows ARM64 (`windows/arm64`)
- Linux x86-64 (`linux/amd64`)
- Linux ARM64 (`linux/arm64`)
- macOS ARM64 (`darwin/arm64`)

Unsupported hosts, absent artifacts, incompatible bundled npm/npx, and checksum mismatches fail with an error.

## Examples

See [Node.js examples](../examples/nodejs.md) for install, build, test, direct Node.js, and npx patterns.

<!--
Sitemap

URL: https://withxx.dev/index.md
Title: xx
Description: Practical, reproducible builds without build-system ceremony

URL: https://withxx.dev/examples/commands.md
Title: Command Examples
Description: General command, environment, and entrypoint patterns.

URL: https://withxx.dev/examples/go.md
Title: Go Examples
Description: Common Go build patterns with managed SDKs.

URL: https://withxx.dev/examples/index.md
Title: Examples
Description: Common xx build and task patterns.

URL: https://withxx.dev/examples/nodejs.md
Title: Node.js Examples
Description: Common Node.js task patterns with a managed distribution.

URL: https://withxx.dev/load.md
Title: Loading Files
Description: Split xx configuration into local Starlark modules.

URL: https://withxx.dev/packages/go.md
Title: Go Package
Description: Provision an official Go SDK, run or install Go tools, and build Go binaries.

URL: https://withxx.dev/packages/nodejs.md
Title: Node.js Package
Description: Provision official Node.js distributions and run npm and npx tasks.

URL: https://withxx.dev/packages/os.md
Title: OS Package
Description: Run commands and construct isolated task environments.
-->
