# Configure JavaScript build tools

URL: https://chainguard-docs-preview-git-fix-ai-metadata-year.chainguard.app/chainguard/libraries/javascript/build-configuration.md
Last Modified: October 7, 2026
Tags: Chainguard Libraries, JavaScript

Configuring Chainguard Libraries for JavaScript on your workstation


Chainguard Libraries for JavaScript works with your existing build tools — npm,
pnpm, Yarn, and Bun — through a registry configuration change. This page is a
reference for configuring each supported build tool. It covers registry
configuration, authentication, cache clearing, and minimal example projects.

Apply these changes on every workstation and build server that builds your
applications or downloads libraries, including CI/CD infrastructure such as
Jenkins, TeamCity, or GitHub Actions.

The `https://libraries.cgr.dev/javascript` endpoint is also the [Chainguard
Repository](/chainguard/chainguard-repository/overview/) endpoint for JavaScript. By
default, it serves only Chainguard-built artifacts. When [upstream
fallback](/chainguard/libraries/introduction/overview/#upstream-fallback-and-controls) is
enabled for your organization, the same endpoint can also serve requested
versions from upstream, under Chainguard security controls.

The same endpoint also serves remediated `-cgr.N` artifacts, so there is no
separate remediated repository to configure. The registry configuration on this
page does not select remediated versions on its own; to select them, run
`chainctl libraries remediate` in your project. Refer to [CVE
remediation](/chainguard/libraries/policies-and-security/cve-remediation/) for
details.

This guide outlines how to configure your build tool. If you are looking for something else, refer to the following guides depending on your goals:

| If you want to... | Use this page |
| --- | --- |
| Understand what Chainguard Libraries for JavaScript is and how it works | [JavaScript overview](/chainguard/libraries/javascript/overview/) |
| Set up organization-wide access through a repository manager | [Global configuration](/chainguard/libraries/javascript/global-configuration/) |
| Look up how to configure a specific build tool (npm, pnpm, Yarn, Bun) | This page |
| Migrate an existing project step by step | [JavaScript migration guide](/chainguard/libraries/javascript/migration/) |
| Install inside a container build without leaking credentials into the image | [Container builds](/chainguard/libraries/policies-and-security/build-containers/) |

If a package or version is blocked by a policy or malware scan, your build tool returns an error. Refer to the [Error messages documentation](/chainguard/libraries/troubleshooting/errors/) for more details.

## Access approaches

### Repository manager: JFrog Artifactory

Build configuration to retrieve artifacts from Artifactory typically requires
you to authenticate and use the identity token in the configuration of your
build tool.

Follow the steps from the [global
configuration](/chainguard/libraries/javascript/global-configuration/#jfrog-artifactory)
to determine URL and authentication details.

### Repository manager: Sonatype Nexus Repository

Build configuration to retrieve artifacts from Nexus may require authentication.
Use your username and password for Nexus in your build tool configuration.

Follow the steps from the [global
configuration](/chainguard/libraries/javascript/global-configuration/#sonatype-nexus-repository)
to determine URL and authentication details.

<a id="direct-access"></a>

### Direct access

Build configuration to retrieve artifacts **directly** from the Chainguard
Libraries for JavaScript repository at `https://libraries.cgr.dev/javascript/`
requires authentication with username and password from a pull token as detailed
in [access documentation](/chainguard/libraries/introduction/access/#pull-token).

Refer to the minimal example projects on this page for demonstrations using direct access for each build tool.

> Note: Direct access requires per-project and per-workstation configuration.
For organizations with multiple teams, proxying through an artifact manager is
recommended. Refer to the [global
configuration](/chainguard/libraries/javascript/global-configuration/) for setup
guides.

## Updating lockfile hashes

When migrating an existing JavaScript project to Chainguard Libraries, your
lockfile contains integrity hashes generated against packages previously
downloaded from the npm registry or through your repository manager. Because
Chainguard rebuilds packages in a secured build environment rather than
distributing upstream artifacts directly, the resulting checksums differ even
for identical package versions. These hashes must be updated before your package
manager will accept packages from Chainguard.

Learn more in the [JavaScript migration guide](/chainguard/libraries/javascript/migration/#step-3-update-your-lockfile) and in the [`chainctl libraries update-hashes` command docs](/platform/chainctl/chainctl-docs/chainctl_libraries_update-hashes/).

<a id="update-hashes-auth"></a>

### Authentication

`update-hashes` fetches checksums from Chainguard Libraries,
which requires authentication. Where it fetches from depends on your environment: some setups authenticate directly to `libraries.cgr.dev`, but if your build routes through a repository manager configured as a pull-through proxy for Chainguard Libraries, point `update-hashes` there instead with `--registry-url` so it validates against the same source your build used.

> **Note**: Running `chainctl libraries update-hashes` requires the `libraries.javascript.pull` permission or the Owner role.

Authenticating to `libraries.cgr.dev` directly:

- **Logged in locally**: Run the command while authenticated; if you have no
  other credential it authenticates with a
  [pull token](/chainguard/libraries/introduction/access/#pull-token) for your
  organization, prompting for one only if you have access to more than one. Pass
  `--parent <organization>` to skip that prompt. To avoid it entirely,
  scope your login to the libraries registry once with
  `chainctl auth login --audience=libraries.cgr.dev` — that session is then used
  automatically. (`chainctl auth configure-npm` also sets up this
  libraries-scoped session as part of configuring npm.)
- **CI or non-interactive**:
    - For a session token, pass `--token <token>` or set `CHAINCTL_AUTH_TOKEN`. The
    token must be scoped to the libraries registry; mint one with
    `chainctl auth token --audience=libraries.cgr.dev`.
    - For a [pull token](/chainguard/libraries/introduction/access/#pull-token) (an identity and
    secret), pass it as basic auth: `--username <identity> --password <secret>`,
    or set `CHAINCTL_REGISTRY_USERNAME` / `CHAINCTL_REGISTRY_PASSWORD`.
- **From `~/.netrc`**: Credentials for the registry host are read from `~/.netrc`
  (or `$NETRC`); refer to [.netrc for authentication](/chainguard/libraries/introduction/access/#netrc).
  Pass `--ignore-netrc` to skip an unrelated entry.

Authenticating to a repository manager:

When you target a repository manager with `--registry-url`, authenticate with **that** registry's credentials —
`--username`/`--password`, the `CHAINCTL_REGISTRY_USERNAME` /
`CHAINCTL_REGISTRY_PASSWORD` environment variables, or a matching `~/.netrc`
entry. Chainguard-scoped tokens are never sent to third-party hosts.

Learn more about using a repository manager in the [global configuration documentation](/chainguard/libraries/javascript/global-configuration/).

## Adopting remediated JavaScript artifacts

Pointing your build tool at the Chainguard registry does not select remediated
`-cgr.N` artifacts on its own. JavaScript remediation operates on the resolved
dependency tree in your lockfile, so you adopt it with `chainctl libraries
remediate` after your project is configured to use the Chainguard registry and a
lockfile exists.

> **Note**: Running `chainctl libraries remediate` requires the
> `libraries.javascript.pull` permission or the Owner role.

First, preview the available remediations:

```bash
chainctl libraries remediate
```

The `--apply` step reads credentials from a `.npmrc` file in your project
directory. Some registry setup options on this page store those settings
elsewhere, such as your user-level `.npmrc` or your package manager's own
configuration, so you can finish registry setup without a project `.npmrc`. If
you don't have one, create it by running `chainctl auth configure-npm` from the
project directory:

```bash
chainctl auth configure-npm
```

This writes a project-level `.npmrc` with the registry URL and credentials. Do
not commit these credentials to version control; supply them through environment
variables or CI secrets at build time. Yarn and pnpm authenticate differently;
see [Yarn](#yarn) and [pnpm](#pnpm) for their setup steps.

Then adopt them:

```bash
chainctl libraries remediate --apply
```

With `--apply`, the command walks your lockfile and updates each eligible
package to the corresponding Chainguard remediated version. How it records the
change depends on where the package sits in your dependency tree: for a direct
dependency, it sets the exact `-cgr.N` version in `package.json`; for a
transitive dependency, it adds an override or resolution rule your package
manager supports (for example, the `overrides` field for npm or `resolutions`
for Yarn). The command also updates the lockfile. Only packages with a `-cgr.N`
build for the exact version resolved in your lockfile are changed; every other
dependency stays unchanged.

Because `--apply` updates the lockfile and verifies the result before it changes
your project, adoption is complete once the command succeeds. You don't need to
regenerate the lockfile or rewrite hashes afterward. To confirm the change,
review the modified files (`package.json` and your lockfile), run an install
that preserves the lockfile, and run your application's tests.

If you also changed your registry configuration, see the per-tool **Apply
registry changes** sections for [npm](#npm-apply), [pnpm](#pnpm-apply),
[Yarn](#yarn-apply), or [Bun](#bun-apply).

Re-run `chainctl libraries remediate` after every install or dependency update
so that newly resolved entries are evaluated.

### Adopt remediated versions manually

You can also adopt a remediation manually, without `chainctl libraries
remediate`:

1. Identify the exact remediated version.
1. Pin the exact `-cgr.N` version as an override or resolution in the
`package.json` or lockfile (the `overrides` field for npm or Bun, `pnpm.overrides` for pnpm, or `resolutions` for Yarn).
1. Regenerate only the relevant lockfile entries. For example:
    - `npm install --package-lock-only`
    - `pnpm install --lockfile-only`
    - `yarn install`
    - `bun install`

Review the lockfile diff and run your normal tests afterward. An override may affect multiple occurrences, and some package managers apply the rule tree-wide.

Refreshing the lockfile alone
doesn't adopt the remediation: because `-cgr.N` is an npm prerelease identifier,
a semver range such as `^4.17.21` never matches it, so the override is what
selects the remediated build.

For remediated version naming and how remediation propagates through transitive
dependencies, see [CVE remediation for Chainguard
Libraries](/chainguard/libraries/policies-and-security/cve-remediation/).

<a id="npm"></a>

## npm

[npm](https://www.npmjs.com/) is the default package manager for Node.js, widely
used for managing JavaScript dependencies and scripts. It allows developers to
install, share, and manage packages for their projects. For more details, see
the [npm documentation](https://docs.npmjs.com/).

**Declare dependencies in package.json**

With npm, you declare JavaScript package dependencies in a `package.json` file
and separated into development and runtime dependencies. The following snippet
shows a minimal example with a couple of dependencies each:

```json
{
  "dependencies": {
    "@emotion/react": "^11.14.0",
    "@emotion/styled": "^11.14.0",
    "@fontsource/roboto": "^5.1.1",
    "node": "^22.18.0",
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "react-router-dom": "^7.1.5",
  },
  "devDependencies": {
    "@eslint/js": "^9.14.0",
    "@types/react": "^18.3.18",
    "@types/react-dom": "^18.3.5"
  }
}
```

By default, npm retrieves packages from the npm Registry at
`https://registry.npmjs.org` and stores them locally in the `node_modules`
directory of the project after running `npm install`. This operation also
creates the `package-lock.json` file.

Note that dependency versions are typically declared with the `^` before the
version string. This indicates higher, compatible versions, following the
semantic versioning scheme of the package are used automatically. For example,
the declaration of version `^22.18.0` for `node`, actually results in the use of
version `22.20.0` or even a higher version once available and `npm install` is
run.  

Any dependency or dependency version changes require another install and
therefore an update to the lock file. The lock file also encodes the checksum
values in the `integrity` field and the download URL in the `resolved` field for
each module.

**Direct access: Point registry to Chainguard**

To change a project to use Chainguard Libraries for JavaScript, set the registry
URL to point to Chainguard in your user `.npmrc` file:

```bash
npm config set registry https://libraries.cgr.dev/javascript/
```

### Using a repository manager

To change a project to use Chainguard Libraries for JavaScript, set the registry
URL to point to your repository manager in your user `.npmrc` file:

```shell
npm config set registry https://repo.example.com:8443/repository/javascript-all/
```

The command results in the following line in the `.npmrc` file:

```properties
registry=https://repo.example.com:8443/repository/javascript-all/
```

Refer to the [`npmrc`
documentation](https://docs.npmjs.com/cli/v11/configuring-npm/npmrc) for
alternative configurations, for example per project or globally, and details for
configuring authentication.

Example URLs:

- JFrog Artifactory: `https://example.jfrog.io/artifactory/javascript-all/`
- Sonatype Nexus: `https://repo.example.com:8443/repository/javascript-all/`
- Direct access: `https://libraries.cgr.dev/javascript/`

<a id="npm-apply"></a>

### Apply registry changes

To apply the registry changes, remove the `node_modules` directory, [update the artifact hashes](#updating-lockfile-hashes), then run the `npm install` command again. This re-fetches all
packages from Chainguard and updates the lockfile in place with updated hashes:

```bash
rm -rf node_modules
chainctl libraries update-hashes
npm install
```

As an alternative, you can remove the `node_modules` directory _and_ the `package-lock.json` file, then reinstall. This regenerates the lockfile and updates the hashes. Regenerating re-resolves your dependencies, so it can change your pinned versions, and any new versions published within your configured cooldown window will return an error. See [Update your lockfile](/chainguard/libraries/javascript/migration/#step-3-update-your-lockfile).

**Clear caches**

If you encounter stale or corrupted package data, clear the cache with:

```bash
npm cache clean --force
```

To verify the cache is empty:

```bash
npm cache verify
```

### Using private npm packages alongside Chainguard Repository

If your organization publishes its own packages to the public npm Registry under
a scoped prefix (for example, `@your-org/package-name`), you may want those
packages to be fetched directly from npm rather than going through the
[Chainguard Repository](/chainguard/libraries/javascript/overview/); for
example, to bypass the cooldown period for packages you own and trust.

npm supports per-scope registry configuration, which lets you route packages
with a specific prefix to a different registry:

```
# .npmrc
registry=https://libraries.cgr.dev/javascript/
//libraries.cgr.dev/javascript/:_auth=${token}

@your-org:registry=https://registry.npmjs.org/
```

However, npm has a behavior where, when it fetches package metadata from a
scoped registry, it may rewrite the resolved tarball URL in the lockfile to use
the primary registry host (in this case, Chainguard Repository) instead of the
scoped registry. This causes subsequent `npm install` runs to attempt to fetch
your scoped packages from Chainguard Repository, resulting in a 404 or
authentication error.

To prevent this, add the following line to your `.npmrc`:

```
replace-registry-host=never
```

This tells npm never to rewrite the registry host in resolved URLs, so scoped
packages remain associated with their correct upstream registry in the lockfile.

After adding this line, verify your lockfile reflects the
correct resolved URLs: scoped packages should resolve to `registry.npmjs.org`
and all other packages should resolve to `libraries.cgr.dev/javascript`.

<a id="npm-minimal"></a>

### Minimal example project

For testing purposes, you can use direct access and environment variables as
detailed in the [access documentation](/chainguard/libraries/introduction/access/#use-environment-variables-for-pull-token-credentials).

**1. Create a JavaScript project**

Use the following steps to create a minimal example project for npm with
Chainguard Libraries for JavaScript.

```shell
mkdir npm-example
cd npm-example
npm init -y
```

**2. Configure the .npmrc file**

Once the environment variables are set, configure the `.npmrc` file.

Run the following command to configure registry
access and authentication in the `.npmrc` file in the current project
directory:

```shell
chainctl auth configure-npm
```

[This command](/platform/chainctl/chainctl-docs/chainctl_auth_configure-npm/) writes a project-level `.npmrc` with the registry URL and base64-encoded credentials. It also prints the equivalent `npm config set` commands for use in CI or other environments where you need to configure `.npmrc` manually. If this command returns an error, ensure that you are using the [latest version of `chainctl`](/platform/chainctl-usage/how-to-install-chainctl/#updating-chainctl).

Alternatively, you can configure the `.npmrc` file manually:

**Configure .npmrc manually**


The following steps configure registry
access with authentication in the `.npmrc` file in the current project
directory:

```shell
export token=$(echo -n "${CHAINGUARD_JAVASCRIPT_IDENTITY_ID}:${CHAINGUARD_JAVASCRIPT_TOKEN}" | base64 -w 0)

npm config set registry https://libraries.cgr.dev/javascript/ --location=project
npm config set //libraries.cgr.dev/javascript/:_auth "${token}" --location=project
```

Note that the trailing slash in the registry URL is required, and that setting
`username` and `_password` instead of `auth` with a token does not work with
npm. The `-w 0` option for `base64` is required and supported by the GNU
coreutils versions included in most operating systems.



**Example .npmrc file**

```
registry=https://libraries.cgr.dev/javascript/
//libraries.cgr.dev/javascript/:_auth=aWRlbnRpdHktaWQ6dG9rZW4=
```

The value of `auth` is the base64 encoding of `identity-id:token`, including the `/` character in the username.

**3. Verify authentication with npm ping**

Before installing packages, you can verify that authentication is configured correctly by running:

```bash
npm ping --userconfig .npmrc
```

A successful response looks like:

```bash
npm notice PING https://libraries.cgr.dev/javascript/
npm notice PONG 1065ms
```

The PONG response confirms that your credentials are valid and the registry is reachable. If the command fails, check that the .npmrc file exists in the current directory and that your token has not expired.

**4. Add dependencies and build the project**

Add dependencies for your project into the `package.json` file to test retrieval
from Chainguard Libraries, build the project, and list the dependencies:

```shell
npm add commander@4.1.1
npm install
npm list
```

Following this, find the downloaded package in `node_modules/commander`. The
commands also result in the creation of the lock file `package-lock.json`, which
contains the source URL for each package in the `resolved` field.

Adjust the registry configuration to use your repository manager and add any
other desired packages for further testing.

<a id="pnpm"></a>

## pnpm

[pnpm](https://pnpm.io/) is a fast, disk space-efficient package manager for
JavaScript, designed as an alternative to npm and Yarn. For
more information, refer to the [pnpm documentation](https://pnpm.io/motivation).

**Limitations**

Before getting started, note the following limitations:

- The Chainguard Repository [upstream fallback](/chainguard/libraries/javascript/overview/#upstream-fallback-policy-and-controls) has been tested with pnpm v11. We recommend using pnpm v11 or newer.
- pnpm v11 re-verifies lockfile entries during install, including when you run `pnpm install --frozen-lockfile`. With Chainguard Repository for JavaScript, this can cause errors even when the lockfile is up to date. If this issue occurs, set `trustLockfile: true` in the `pnpm-workspace.yaml` to configure pnpm to trust the existing lockfile.
- Setting `lockfileIncludeTarballUrl: true` in the `pnpm-workspace.yaml` ensures pnpm continues to fetch the upstream tarball URL recorded in the lockfile. Without this setting, you can encounter integrity errors when Chainguard builds a package version that had previously been mirrored from upstream. This helps avoid integrity errors until the lockfile is updated.
- If you use Chainguard Libraries with pnpm `trustPolicy: no-downgrade`, pnpm may fail installation. Because Chainguard Libraries serves rebuilt packages, pnpm may treat those packages as a trust downgrade. To work around this, disable it in your pnpm configuration: `trustPolicy: off`

**Declare dependencies in package.json**

With pnpm, you declare JavaScript package dependencies in a `package.json` file
and separated into development and runtime dependencies. The following snippet
shows a minimal example with a couple of dependencies each:

```json
{
  "dependencies": {
    "@emotion/react": "^11.14.0",
    "@emotion/styled": "^11.14.0",
    "@fontsource/roboto": "^5.1.1",
    "node": "^22.18.0",
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "react-router-dom": "^7.1.5",
  },
  "devDependencies": {
    "@eslint/js": "^9.14.0",
    "@types/react": "^18.3.18",
    "@types/react-dom": "^18.3.5"
  }
}
```

By default, pnpm retrieves the packages the npm Registry at
`https://registry.npmjs.org` and stores them locally in the `node_modules`
directory of the project after running `pnpm install`. This operation also
creates the `pnpm-lock.yaml` file.

Note that dependency versions are typically declared with the `^` before the
version string. This indicates higher, compatible versions, following the
semantic versioning scheme of the package, are used automatically. For example,
the declaration of version `^22.18.0` for `node`, actually results in the use of
version `22.20.0` or even a higher version once available and pnpm install is
run.  

Any dependency or dependency version changes require another install and
therefore an update to the lock file. The lock file also encodes the checksum
values in the `integrity` field and other information for each module.

**Direct access: Point registry to Chainguard**

To change a project to use Chainguard Libraries for JavaScript, set the registry
URL to point to Chainguard and set auth credentials. The following command writes to the project-level configuration:

```bash
export token=$(echo -n "${CHAINGUARD_JAVASCRIPT_IDENTITY_ID}:${CHAINGUARD_JAVASCRIPT_TOKEN}" | base64 -w 0)

pnpm config set registry https://libraries.cgr.dev/javascript/ --location=project
pnpm config set //libraries.cgr.dev/:_auth "${token}" --location=project
```

To set the registry at the user level instead of project-level, omit the `--location=project` flag.

The configuration should look like the following:

```properties
registry=https://libraries.cgr.dev/javascript/
//libraries.cgr.dev/:_auth=<base64-encoded-token>
```

The registry URL always points to the `/javascript/` repository; you do not point
it at `/javascript-upstream/`. The authentication entry, however, is keyed to the
whole `libraries.cgr.dev` host (`//libraries.cgr.dev/`) rather than to the
`/javascript/` path alone. This matters because packages that Chainguard has not
yet rebuilt are served through the [upstream
fallback](/chainguard/libraries/javascript/overview/#upstream-fallback-policy-and-controls)
at `https://libraries.cgr.dev/javascript-upstream/`, and pnpm authenticates against
whatever tarball URL the registry returns for each package. A credential keyed to
the host covers both the `/javascript/` and `/javascript-upstream/` paths.

If you prefer to scope credentials per path, you must configure **both** paths.
Otherwise, installs that resolve upstream-fallback packages fail with an HTTP 401
error:

```properties
registry=https://libraries.cgr.dev/javascript/
//libraries.cgr.dev/javascript/:_auth=<base64-encoded-token>
//libraries.cgr.dev/javascript-upstream/:_auth=<base64-encoded-token>
```

### Using a repository manager

To change a project to use Chainguard Libraries for JavaScript, set the registry
URL to point to your repository manager in your user `.npmrc` file:

```shell
pnpm config set registry https://repo.example.com:8443/repository/javascript-all/
```

The command results in the following line in the `.npmrc` file:

```properties
registry=https://repo.example.com:8443/repository/javascript-all/
```

Refer to the [pnpm registry
documentation](https://pnpm.io/settings#registry--authentication-settings) for
alternative configurations, for example per project or globally, and details for
configuring authentication.

Example URLs:

- JFrog Artifactory: `https://example.jfrog.io/artifactory/javascript-all/`
- Sonatype Nexus: `https://repo.example.com:8443/repository/javascript-all/`
- Direct access: `https://libraries.cgr.dev/javascript/`

<a id="pnpm-apply"></a>

### Apply registry changes

To apply the registry changes, remove the `node_modules` directory, [update the artifact hashes](#updating-lockfile-hashes), then run the `pnpm install` command again. This re-fetches all
packages from Chainguard and updates the lockfile in place with updated hashes:

```bash
rm -rf node_modules
chainctl libraries update-hashes
pnpm install
```

As an alternative, you can remove the `node_modules` directory _and_ the `pnpm-lock.yaml` file, then reinstall. This regenerates the lockfile and updates the hashes. Regenerating re-resolves your dependencies, so it can change your pinned versions, and any new versions published within your configured cooldown window will return an error. See [Update your lockfile](/chainguard/libraries/javascript/migration/#step-3-update-your-lockfile).

**Clear pnpm caches**

pnpm has three separate layers of cached data. If you encounter stale or corrupted package data, you can clear all of these caches:

**Clear pnpm caches**



**Metadata (packuments)**

There is an [experimental command](https://pnpm.io/cli/cache-delete) to delete the metadata cache:

```bash
pnpm cache delete
```

**HTTP cache**

pnpm maintains a separate HTTP cache at `~/.cache/pnpm` (or `$XDG_CACHE_HOME/pnpm` if that variable is set). Delete it with:

```bash
rm -rf "${XDG_CACHE_HOME:-$HOME/.cache}/pnpm"
```

**Content-addressable store (tarballs)**

To find and manually remove the full store:

```bash
pnpm store path
```

Then delete the directory that command outputs:

On macOS/Linux -

```bash
rm -rf "$(pnpm store path)"
```

On Windows -

Use the path returned by `pnpm store path` and delete it via File Explorer or `rmdir`.

> Note: pnpm prune removes unused tarballs but does not remove packument metadata. If you are seeing 404 errors after switching to or updating the Chainguard registry endpoint, use the commands above rather than pnpm prune.




### Update lockfile hashes

If you are migrating an existing project and want to preserve your current
lockfile, use [`chainctl libraries update-hashes`](#updating-lockfile-hashes)
to update only the integrity hashes in place instead.

Now you can proceed with your development and testing.

<a id="pnpm-minimal"></a>

### Minimal example project

Use the following steps to create a minimal example project for pnpm with
Chainguard Libraries for JavaScript.

```shell
mkdir pnpm-example
cd pnpm-example
pnpm init
```

For testing purposes, you can use direct access and environment variables as
detailed in the [access documentation](/chainguard/libraries/introduction/access/#use-environment-variables-for-pull-token-credentials).

To create pull token credentials and set them as environment variables, run:

```bash
eval $(chainctl auth pull-token --output env --repository=javascript)
```

Once
the environment variables are set, the following steps configure registry
access and authentication in the `.npmrc` file in the current project
directory:

```bash
export token=$(echo -n "${CHAINGUARD_JAVASCRIPT_IDENTITY_ID}:${CHAINGUARD_JAVASCRIPT_TOKEN}" | base64 -w 0)

pnpm config set registry https://libraries.cgr.dev/javascript/ --location=project
pnpm config set //libraries.cgr.dev/:_auth "${token}" --location=project
```

The trailing slash in the registry URL is required. The authentication entry is
keyed to the whole `libraries.cgr.dev` host (`//libraries.cgr.dev/`) so that it
also covers packages served through the [upstream
fallback](/chainguard/libraries/javascript/overview/#upstream-fallback-policy-and-controls)
path. Note that the `-w 0` option for `base64` is required and supported by the GNU
coreutils versions included in most operating systems.

Alternatively, you can set `username` and `_password` instead of `_auth`. Note
that the `_password` value must still be base64-encoded; pnpm does not accept a
raw token here:

```bash
pnpm config set //libraries.cgr.dev/:username "${CHAINGUARD_JAVASCRIPT_IDENTITY_ID}" --location=project
pnpm config set //libraries.cgr.dev/:_password "$(echo -n "${CHAINGUARD_JAVASCRIPT_TOKEN}" | base64 -w 0)" --location=project
```

Add dependencies for your project into the `package.json` file to test retrieval
from Chainguard Libraries, build the project, and list the dependencies:

```shell
pnpm add commander@4.1.1
pnpm install
pnpm list
```

Following this, find the downloaded package in
`node_modules/.pnpm/commander@4.1.1` and `node_modules/commander`. The commands
also result in the creation of the lock file `pnpm-lock.yaml`, which contains
the source URL for each package in the `tarball` field.

Adjust the registry configuration to use your repository manager and add any
other desired packages for further testing.

<a id="yarn"></a>

## Yarn

[Yarn](https://yarnpkg.com/) is a popular package manager for JavaScript
projects, offering fast, reliable, and secure dependency management as an
alternative to npm. It is widely used for managing
project dependencies, scripts, and workflows in Node.js and other JavaScript
development environments. For more details, refer to the [Yarn
documentation](https://yarnpkg.com/getting-started).

This section applies to modern versions of Yarn, also known as Yarn Berry, with
versions 2.x and higher. If you are using Yarn 1.x refer to the [Yarn Classic
section](#yarn-classic).

**Declare dependencies in package.json**

With Yarn, you declare JavaScript package dependencies in a `package.json` file
and separated into different scoped dependencies such as development and runtime
dependencies. The following block shows a minimal example with `react` and
`node` as main runtime dependencies and `eslint` as development dependency:

```json
{
  "name": "yarn-berry-example",
  "packageManager": "yarn@4.10.3",
  "dependencies": {
    "node": "^22.20.0",
    "react": "^19.1.1"
  },
  "devDependencies": {
    "eslint": "^9.36.0"
  }
}
```

By default, Yarn retrieves the packages from the registry at
`https://registry.yarnpkg.com` and stores them locally in the `.yarn` folder in the user's
home directory after running `yarn`. Specific packages are linked into the
project. This operation also creates the `yarn.lock` file.

Note that dependency versions are typically declared with the `^` before the
version string. This indicates higher, compatible versions, following the
semantic versioning scheme of the package, are used automatically. For example,
the declaration of version `^22.18.0` for `node`, actually results in the use of
version `22.20.0` or even a higher version once available and `yarn` is run.  

Any dependency or dependency version changes require another install and
therefore an update to the lock file. The lock file also encodes the checksum
values in the `checksum` field.

**Direct access: Point registry to Chainguard**

To change a project to use Chainguard Libraries for JavaScript, set the registry
URL to point to Chainguard in your user `.yarnrc` file:

```bash
yarn config set npmRegistryServer https://libraries.cgr.dev/javascript/
```

### Using a repository manager

To change a project to use Chainguard Libraries for JavaScript, set the registry
URL to point to your repository manager in your project `.yarnrc.yml` file:

```shell
yarn config set npmRegistryServer https://repo.example.com:8443/repository/javascript-all
```

The command results in the following line in the `.yarnrc.yml` file:

```
npmRegistryServer: "https://repo.example.com:8443/repository/javascript-all"
```

Refer to the [`config set` documentation](https://yarnpkg.com/cli/config/set) for
more details such as authentication support.

Example URLs:

- JFrog Artifactory: `https://example.jfrog.io/artifactory/javascript-all`
- Sonatype Nexus: `https://repo.example.com:8443/repository/javascript-all`
- Direct access: `https://libraries.cgr.dev/javascript`

<a id="yarn-apply"></a>

### Apply registry changes

To apply the registry change, run the `yarn` command again. This forces an update of
all packages from the new registry and regeneration of the lock file.

If you encounter stale or corrupted package data, clear the cache with:

```bash
yarn cache clean --all
```

If you're seeing checksum mismatch errors rather than stale data, you can control Yarn's behavior via the [`checksumBehavior` setting](https://yarnpkg.com/configuration/yarnrc#checksumBehavior) in `.yarnrc.yml`. Setting it to `reset` causes Yarn to purge and re-fetch any cache entry whose checksum doesn't match, without clearing the entire cache:

```yaml
checksumBehavior: reset
```

### Update lockfile hashes

If you are migrating an existing project and want to preserve your current
lockfile, use [`chainctl libraries update-hashes`](#updating-lockfile-hashes)
to update only the integrity hashes in place instead.

#### Using Chainguard Libraries with `yarn install --immutable`

Yarn Berry's `--immutable` flag prevents changes to `yarn.lock` during installation. Migrating to Chainguard Libraries requires a lockfile preparation step before your normal `--immutable` workflow can resume.

Yarn Berry's lockfile stores both resolved `__archiveUrl` entries and Yarn-specific checksums (used by `--immutable` to detect tampering). Run the following command to update both:

```bash
chainctl auth configure-npm
TOKEN=$(grep '_authToken=' .npmrc | sed 's/.*_authToken=//')
chainctl libraries update-hashes --token "$TOKEN" yarn.lock
yarn install --mode=update-lockfile
```

After running these commands, verify that your lockfile is stable under `--immutable`:

```bash
yarn install --immutable
```

If this command exits without error and without modifying `yarn.lock`, your lockfile is ready to commit.

Expand the following section to learn about recommended workflows.

**Workflows when using the --immutable flag**



**Recommended workflow for dependency updates**

When updating dependencies, repeat the lockfile preparation steps before committing:

```bash
chainctl auth configure-npm
TOKEN=$(grep '_authToken=' .npmrc | sed 's/.*_authToken=//')
chainctl libraries update-hashes --token "$TOKEN" yarn.lock
yarn install --mode=update-lockfile
yarn install --immutable
yarn build
yarn test
```

Review the `yarn.lock` diff before committing. Expected changes are updated `__archiveUrl` resolutions pointing to Chainguard, updated Yarn checksum entries, and any intentional dependency version changes. Unexpected changes to package versions should be investigated before committing.

**Recommended CI workflow**

After the updated lockfile is committed, your CI configuration does not need to change. Use your standard immutable install:

```bash
yarn install --immutable
yarn build
yarn test
```

For stricter checksum and cache validation, you can also add `--check-cache`:

```bash
yarn install --immutable --check-cache
```

Do not commit `.npmrc` credentials to version control. Use environment variables or CI secrets to supply credentials at build time.




<a id="yarn-berry-minimal"></a>

### Minimal example project

Use the following steps to create a minimal example project for yarn with
Chainguard Libraries for JavaScript. The script sets the policy to use the
latest stable release of Yarn.

```shell
mkdir yarn-berry-example
cd yarn-berry-example
yarn policies set-version stable
yarn init
```

For testing purposes, you can use direct access and environment variables as
detailed in the [access documentation](/chainguard/libraries/introduction/access/#use-environment-variables-for-pull-token-credentials). Once
the environment variables are set, the following steps configure registry
access with authentication in the `.yarnrc.yml` file in the current project
directory:

```shell
export authInfo="${CHAINGUARD_JAVASCRIPT_IDENTITY_ID}:${CHAINGUARD_JAVASCRIPT_TOKEN}"

yarn config set npmRegistryServer https://libraries.cgr.dev/javascript
yarn config set 'npmRegistries["//libraries.cgr.dev/javascript"].npmAuthIdent' "${authInfo}"
yarn config set 'npmRegistries["//libraries.cgr.dev/javascript"].npmAlwaysAuth' "true"
```

Note the following details:

- The `authInfo` token is passed as authentication identity `npmAuthIdent` and only uses
  the username and password values from the pull token separated by colon without any further encoding.
- Setting `npmAlwaysAuth` is required.

Add dependencies for your project into the `package.json` file to test retrieval
from Chainguard Libraries, build the project, and list the dependencies:

```shell
yarn add commander@4.1.1
yarn install
yarn info
```

Following this, find the downloaded package in the local shared cache. The
commands also result in the creation of the lock file `yarn.lock`, which
contains the source URL for each package in the `archiveUrl` parameter of the
`resolution` field.

Adjust the registry configuration to use your repository manager and add any
other desired packages for further testing.

<a id="yarn-classic"></a>

## Yarn Classic

[Yarn Classic](https://classic.yarnpkg.com/) is the legacy 1.x release of
[Yarn](#yarn).

With Yarn, you declare JavaScript package dependencies in a `package.json` file
and separated into different scoped dependencies such as development and runtime
dependencies. The following block shows a minimal example with `react` and
`node` as main runtime dependencies and `eslint` as development dependency:

```json
{
  "name": "yarn-classic-example",
  "version": "1.0.0",
  "description": "A minimal example project for using yarn classic",
  "main": "index.js",
  "author": "Chainguard",
  "license": "MIT",
  "private": false,
  "dependencies": {
    "node": "^22.18.0",
    "react": "^19.1.1"
  },
  "devDependencies": {
    "eslint": "^9.36.0"
  }
}
```

By default, Yarn retrieves the packages from the registry at
`https://registry.yarnpkg.com` and stores them locally in the `node_modules`
directory of the project after running `yarn`. This operation also creates the
`yarn.lock` file.

Note that dependency versions are typically declared with the `^` before the
version string. This indicates higher, compatible versions, following the
semantic versioning scheme of the package, are used automatically. For example,
the declaration of version `^22.18.0` for `node`, actually results in the use of
version `22.20.0` or even a higher version once available and `yarn` is run.  

Any dependency or dependency version changes require another install and
therefore an update to the lock file. The lock file also encodes the checksum
values in the `integrity` field and the download URL in the `resolved` field for
each module.

**Direct access: Point registry to Chainguard**

To change a project to use Chainguard Libraries for JavaScript, first export your pull token as base64-encoded environment variables:

```bash
export token=$(echo -n "${CHAINGUARD_JAVASCRIPT_IDENTITY_ID}:${CHAINGUARD_JAVASCRIPT_TOKEN}" | base64 -w 0)
```

Then, set auth and set the registry URL to point to Chainguard in your user `.npmrc` file:

```bash
cat > .npmrc << 'EOF'
registry=https://libraries.cgr.dev/javascript/
//libraries.cgr.dev/javascript/:_auth="$token"
//libraries.cgr.dev/javascript/:always-auth=true
//libraries.cgr.dev/javascript-upstream/:_auth="$token"
//libraries.cgr.dev/javascript-upstream/:always-auth=true
EOF
```

### Using a repo manager

To change a project to use Chainguard Libraries for JavaScript, set the registry
URL to point to your repository manager in your `.npmrc` file:

```
cat > .npmrc << EOF
registry=https://repo.example.com:8443/repository/javascript-all
EOF
```

Example URLs:

- JFrog Artifactory: `https://example.jfrog.io/artifactory/javascript-all`
- Sonatype Nexus: `https://repo.example.com:8443/repository/javascript-all`
- Direct access: `https://libraries.cgr.dev/javascript`

### Apply registry changes

Note that you can also use the `yarn config set registry` command to set the
registry in the `.yarnrc` file, however this approach does not support
authentication as typically required for repository managers as well as for
direct access to Chainguard Libraries for JavaScript.

Refer to the [`.yarnrc`
documentation](https://classic.yarnpkg.com/lang/en/docs/yarnrc/) for more
details.

To apply the registry changes, remove the `node_modules` directory, [update the artifact hashes](#updating-lockfile-hashes), then run the `yarn install` command again. This re-fetches all
packages from Chainguard and updates the lockfile in place with updated hashes:

```bash
rm -rf node_modules
chainctl libraries update-hashes
yarn install
```

As an alternative, you can remove the `node_modules` directory _and_ the `yarn-lock.json` file, then reinstall. This regenerates the lockfile and updates the hashes. Regenerating re-resolves your dependencies, so it can change your pinned versions, and a release still inside your configured cooldown window returns a 404 error. See [Update your lockfile](/chainguard/libraries/javascript/migration/#step-3-update-your-lockfile).

Another option, after deleting `node_modules` and `yarn-lock.json`, is to run `yarn upgrade`. This updates all dependencies to their latest allowed
versions and regenerates the lock file with updated hashes.

If you encounter stale or corrupted package data, clear the cache with:

```bash
yarn cache clean
```

<a id="yarn-classic-minimal"></a>

### Minimal example project

Use the following steps to create a minimal example project for yarn with
Chainguard Libraries for JavaScript.

```shell
mkdir yarn-classic-example
cd yarn-classic-example
yarn init -y
```

For testing purposes, you can use direct access and environment variables as
detailed in the [access documentation](/chainguard/libraries/introduction/access/#use-environment-variables-for-pull-token-credentials). Once
the environment variables are set, the following steps configure registry access
with authentication in the `.npmrc` file directory:

```shell
export token=$(echo -n "${CHAINGUARD_JAVASCRIPT_IDENTITY_ID}:${CHAINGUARD_JAVASCRIPT_TOKEN}" | base64 -w 0)
cat > .npmrc << EOF
registry=https://libraries.cgr.dev/javascript/
//libraries.cgr.dev/javascript/:_auth="$token"
//libraries.cgr.dev/javascript/:always-auth=true
EOF
```

Note the following details:

- Using yarn configuration files such as `.yarnrc` and commands like `yarn
  config set registry` does not work with authentication details, and the
  proposed approach with `.npmrc` file is preferable.
- The `token` token is passed as authentication token `_auth` and uses the
  username and password values from the pull token separated by colon in
  `base64` encoding. Note that the `-w 0` option for `base64` is required and
  supported by the GNU coreutils versions included in most operating systems.
- Setting `always-auth` is required.
- The trailing slash in the registry URL and authentication references to it is required.

Add dependencies for your project into the `package.json` file to test retrieval
from Chainguard Libraries, build the project, and list the dependencies:

```shell
yarn add commander@4.1.1
yarn install
yarn list
```

Following this, find the downloaded package in the `node_modules` directory.
The commands also result in the creation of the lock file `yarn.lock`, which
contains the source URL for each package in the `resolved` field.

Adjust the registry configuration to use your repository manager and add any
other desired packages for further testing.

<a id="bun"></a>

## Bun

[Bun](https://bun.com/) is a fast, all-in-one JavaScript runtime, bundler, and
package manager designed as an alternative to Node.js tooling. It provides an
integrated package manager that is compatible with the npm ecosystem.

**Declare dependencies in package.json**

With Bun you declare dependencies in a `package.json` file just like
[npm](#npm). The following snippet shows a minimal example:

```json
{
  "dependencies": {
    "@emotion/react": "^11.14.0",
    "@emotion/styled": "^11.14.0",
    "@fontsource/roboto": "^5.1.1",
    "node": "^22.18.0",
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "react-router-dom": "^7.1.5"
  },
  "devDependencies": {
    "@eslint/js": "^9.14.0",
    "@types/react": "^18.3.18",
    "@types/react-dom": "^18.3.5"
  }
}
```

By default Bun installs packages from the npm Registry at
`https://registry.npmjs.org` and stores them locally in the `node_modules`
directory after running `bun install`. Bun creates a binary lockfile named
`bun.lock` to record resolved versions and checksums.

Note that dependency versions are typically declared with `^` to allow
compatible newer releases under semantic versioning. For example, `^22.18.0` for
`node` can result in `22.20.0` or higher when `bun install` runs.

Any dependency or version changes require running `bun install` again, which
updates the lockfile.

### Using a repository manager

To switch a project to use Chainguard Libraries for JavaScript, point Bun at
your repository manager. Add the [registry
configuration](https://bun.com/docs/runtime/bunfig#install-registry) to the
`bunfig.toml` file of your project: `

```toml
[install]
# set default registry as a string
registry = "https://repo.example.com:8443/repository/javascript-all/"
```

Alternatively you can use an [`.npmrc` file](#npm).

You can also temporarily override for install:

```shell
bun install --registry=https://repo.example.com:8443/repository/javascript-all/
```

Refer to [Bun documentation](https://bun.com/docs) for additional registry and authentication options.

Example registry URLs:

- JFrog Artifactory: https://example.jfrog.io/artifactory/javascript-all/
- Sonatype Nexus: https://repo.example.com:8443/repository/javascript-all/
- Direct access: https://libraries.cgr.dev/javascript/

<a id="bun-apply"></a>

### Apply registry changes

To apply the registry changes, remove the `node_modules` directory, [update the artifact hashes](#updating-lockfile-hashes), then run the `bun install` command again. This re-fetches all
packages from Chainguard and updates the lockfile in place with updated hashes:

```bash
rm -rf node_modules
chainctl libraries update-hashes
bun install
```

As an alternative, you can remove the `node_modules` directory _and_ the `bun-lock.json` file, then reinstall. This regenerates the lockfile and updates the hashes. Regenerating re-resolves your dependencies, so it can change your pinned versions, and a release still inside your configured cooldown window returns a 404 error. See [Update your lockfile](/chainguard/libraries/javascript/migration/#step-3-update-your-lockfile).

<a id="bun-minimal"></a>

### Minimal example project

Use the following steps to create a minimal example project for bun with
Chainguard Libraries for JavaScript.

```shell
mkdir bun-example
cd bun-example
bun init -y
```

For testing purposes, you can use direct access and environment variables as
detailed in the [access documentation](/chainguard/libraries/introduction/access/#use-environment-variables-for-pull-token-credentials). Once
the environment variables are set, the following steps configure registry
access with authentication in the `bunfig.toml` file in the current project
directory:

```shell
cat > bunfig.toml << EOF
[install.registry]
url = "https://libraries.cgr.dev/javascript/"
username = "$CHAINGUARD_JAVASCRIPT_IDENTITY_ID"
password = "$CHAINGUARD_JAVASCRIPT_TOKEN"
EOF
```

Note that the trailing slash in the registry URL is required.

Add dependencies for your project into the `package.json` file to test retrieval
from Chainguard Libraries, build the project, and list the dependencies:

```shell
bun add commander@4.1.1
bun install
bun pm ls
```

Following this, find the downloaded package in `node_modules/commander`. The
 commands also result in the creation of the lock file `bun.lock`, which
contains the source URL for each package in the `packages` section.

Adjust the registry configuration to use your repository manager and add any
other desired packages for further testing.

