# Table of Contents - [Benchmarks of JavaScript Package Managers | pnpm](#benchmarks-of-javascript-package-managers-pnpm) - [Motivation | pnpm](#motivation-pnpm) - [The year 2021 for pnpm | pnpm](#the-year-2021-for-pnpm-pnpm) - [Flat node_modules is not the only way | pnpm](#flat-node-modules-is-not-the-only-way-pnpm) - [Node-Modules configuration options with pnpm | pnpm](#node-modules-configuration-options-with-pnpm-pnpm) - [Blog | pnpm](#blog-pnpm) - [The year 2022 for pnpm | pnpm](#the-year-2022-for-pnpm-pnpm) - [How We're Protecting Our Newsroom from npm Supply Chain Attacks | pnpm](#how-we-re-protecting-our-newsroom-from-npm-supply-chain-attacks-pnpm) - [Archive | pnpm](#archive-pnpm) - [Authors | pnpm](#authors-pnpm) - [Blog | pnpm](#blog-pnpm) - [pnpm 10.15 | pnpm](#pnpm-10-15-pnpm) - [pnpm 10.14 | pnpm](#pnpm-10-14-pnpm) - [pnpm 10.17 | pnpm](#pnpm-10-17-pnpm) - [pnpm 10.16 | pnpm](#pnpm-10-16-pnpm) - [pnpm 10.18 | pnpm](#pnpm-10-18-pnpm) - [pnpm 10.19 | pnpm](#pnpm-10-19-pnpm) - [pnpm 10.20 | pnpm](#pnpm-10-20-pnpm) - [Articles | pnpm](#articles-pnpm) - [Podcasts | pnpm](#podcasts-pnpm) - [Videos | pnpm](#videos-pnpm) - [Tools | pnpm](#tools-pnpm) - [Fast, disk space efficient package manager | pnpm](#fast-disk-space-efficient-package-manager-pnpm) - [Catalogs | pnpm](#catalogs-pnpm) - [pnpm cache | pnpm](#pnpm-cache-pnpm) - [Aliases | pnpm](#aliases-pnpm) - [pnpm add | pnpm](#pnpm-add-pkg-pnpm) - [pnpm audit | pnpm](#pnpm-audit-pnpm) - [pnpm bin | pnpm](#pnpm-bin-pnpm) - [pnpm cache delete | pnpm](#pnpm-cache-delete-pnpm) - [pnpm cache list-registries | pnpm](#pnpm-cache-list-registries-pnpm) - [pnpm cache list | pnpm](#pnpm-cache-list-pnpm) - [pnpm cache view | pnpm](#pnpm-cache-view-pnpm) - [pnpm cat-index | pnpm](#pnpm-cat-index-pnpm) - [pnpm cat-file | pnpm](#pnpm-cat-file-pnpm) - [pnpm config | pnpm](#pnpm-config-pnpm) - [pnpm create | pnpm](#pnpm-create-pnpm) - [pnpm dedupe | pnpm](#pnpm-dedupe-pnpm) - [pnpm dlx | pnpm](#pnpm-dlx-pnpm) - [pnpm deploy | pnpm](#pnpm-deploy-pnpm) - [pnpm doctor | pnpm](#pnpm-doctor-pnpm) - [pnpm env | pnpm](#pnpm-env-cmd-pnpm) - [pnpm exec | pnpm](#pnpm-exec-pnpm) - [pnpm fetch | pnpm](#pnpm-fetch-pnpm) - [pnpm 10.21 | pnpm](#pnpm-10-21-pnpm) - [pnpm](#pnpm) - [pnpm publish | pnpm](#pnpm-publish-pnpm) - [pnpm import | pnpm](#pnpm-import-pnpm) - [pnpm 10.22 | pnpm](#pnpm-10-22-pnpm) - [pnpm 10.23 | pnpm](#pnpm-10-23-pnpm) - [pnpm -r, --recursive | pnpm](#pnpm-r-recursive-pnpm) - [pnpm 10.24 | pnpm](#pnpm-10-24-pnpm) - [pnpm 10.25 | pnpm](#pnpm-10-25-pnpm) - [Tags | pnpm](#tags-pnpm) - [Crypto Donations | pnpm](#crypto-donations-pnpm) - [12 posts tagged with "release" | pnpm](#12-posts-tagged-with-release-pnpm) - [Search the documentation | pnpm](#search-the-documentation-pnpm) - [12 posts tagged with "release" | pnpm](#12-posts-tagged-with-release-pnpm) - [pnpm remove | pnpm](#pnpm-remove-pnpm) - [pnpm rebuild | pnpm](#pnpm-rebuild-pnpm) - [pnpm find-hash | pnpm](#pnpm-find-hash-pnpm) - [pnpm init | pnpm](#pnpm-init-pnpm) - [pnpm install | pnpm](#pnpm-install-pnpm) - [pnpm install-test | pnpm](#pnpm-install-test-pnpm) - [pnpm licenses | pnpm](#pnpm-licenses-pnpm) - [pnpm link | pnpm](#pnpm-link-pnpm) - [pnpm list | pnpm](#pnpm-list-pnpm) - [pnpm patch | pnpm](#pnpm-patch-pkg-pnpm) - [pnpm outdated | pnpm](#pnpm-outdated-pnpm) - [pnpm pack | pnpm](#pnpm-pack-pnpm) - [pnpm patch-commit | pnpm](#pnpm-patch-commit-path-pnpm) - [pnpm patch-remove | pnpm](#pnpm-patch-remove-pkg-pnpm) - [pnpm prune | pnpm](#pnpm-prune-pnpm) - [pnpm root | pnpm](#pnpm-root-pnpm) - [pnpm run | pnpm](#pnpm-run-pnpm) - [pnpm self-update | pnpm](#pnpm-self-update-pnpm) - [pnpm start | pnpm](#pnpm-start-pnpm) - [pnpm server | pnpm](#pnpm-server-pnpm) - [pnpm setup | pnpm](#pnpm-setup-pnpm) - [pnpm test | pnpm](#pnpm-test-pnpm) - [pnpm store | pnpm](#pnpm-store-pnpm) - [Command line tab-completion | pnpm](#command-line-tab-completion-pnpm) - [pnpm why | pnpm](#pnpm-why-pnpm) - [pnpm unlink | pnpm](#pnpm-unlink-pnpm) - [pnpm update | pnpm](#pnpm-update-pnpm) - [Configuring | pnpm](#configuring-pnpm) - [Frequently Asked Questions | pnpm](#frequently-asked-questions-pnpm) - [Continuous Integration | pnpm](#continuous-integration-pnpm) - [Working with Docker | pnpm](#working-with-docker-pnpm) - [Feature Comparison | pnpm](#feature-comparison-pnpm) - [Error Codes | pnpm](#error-codes-pnpm) - [Working with Git | pnpm](#working-with-git-pnpm) - [Git Branch Lockfiles | pnpm](#git-branch-lockfiles-pnpm) - [Filtering | pnpm](#filtering-pnpm) - [Only allow pnpm | pnpm](#only-allow-pnpm-pnpm) - [How peers are resolved | pnpm](#how-peers-are-resolved-pnpm) - [Limitations | pnpm](#limitations-pnpm) - [Installation | pnpm](#installation-pnpm) - [Production | pnpm](#production-pnpm) - [Logos | pnpm](#logos-pnpm) - [Motivation | pnpm](#motivation-pnpm) - [Settings (.npmrc) | pnpm](#settings-npmrc-pnpm) - [pnpm CLI | pnpm](#pnpm-cli-pnpm) - [pnpm-workspace.yaml | pnpm](#pnpm-workspace-yaml-pnpm) - [pnpm vs npm | pnpm](#pnpm-vs-npm-pnpm) - [.pnpmfile.cjs | pnpm](#-pnpmfile-cjs-pnpm) - [Scripts | pnpm](#scripts-pnpm) - [Working with Podman | pnpm](#working-with-podman-pnpm) - [pnpm cache | pnpm](#pnpm-cache-pnpm) - [pnpm cat-index | pnpm](#pnpm-cat-index-pnpm) - [pnpm cat-file | pnpm](#pnpm-cat-file-pnpm) - [pnpm find-hash | pnpm](#pnpm-find-hash-pnpm) - [Uninstalling pnpm | pnpm](#uninstalling-pnpm-pnpm) - [Symlinked `node_modules` structure | pnpm](#symlinked-node-modules-structure-pnpm) - [package.json | pnpm](#package-json-pnpm) - [Using Changesets with pnpm | pnpm](#using-changesets-with-pnpm-pnpm) - [Workspace | pnpm](#workspace-pnpm) - [Aliases | pnpm](#aliases-pnpm) - [Catalogs | pnpm](#catalogs-pnpm) - [pnpm cache list | pnpm](#pnpm-cache-list-pnpm) - [pnpm cache delete | pnpm](#pnpm-cache-delete-pnpm) - [pnpm approve-builds | pnpm](#pnpm-approve-builds-pnpm) - [pnpm cache list-registries | pnpm](#pnpm-cache-list-registries-pnpm) - [pnpm audit | pnpm](#pnpm-audit-pnpm) - [pnpm cache view | pnpm](#pnpm-cache-view-pnpm) - [pnpm env | pnpm](#pnpm-env-cmd-pnpm) - [Frequently Asked Questions | pnpm](#frequently-asked-questions-pnpm) - [pnpm create | pnpm](#pnpm-create-pnpm) - [Only allow pnpm | pnpm](#only-allow-pnpm-pnpm) - [pnpm bin | pnpm](#pnpm-bin-pnpm) - [pnpm patch-commit | pnpm](#pnpm-patch-commit-path-pnpm) - [Production | pnpm](#production-pnpm) - [pnpm licenses | pnpm](#pnpm-licenses-pnpm) - [pnpm patch-remove | pnpm](#pnpm-patch-remove-pkg-pnpm) - [pnpm dlx | pnpm](#pnpm-dlx-pnpm) - [pnpm ignored-builds | pnpm](#pnpm-ignored-builds-pnpm) - [pnpm patch | pnpm](#pnpm-patch-pkg-pnpm) - [pnpm add | pnpm](#pnpm-add-pkg-pnpm) - [pnpm dedupe | pnpm](#pnpm-dedupe-pnpm) - [pnpm exec | pnpm](#pnpm-exec-pnpm) - [pnpm outdated | pnpm](#pnpm-outdated-pnpm) - [pnpm list | pnpm](#pnpm-list-pnpm) - [Configuring | pnpm](#configuring-pnpm) - [pnpm doctor | pnpm](#pnpm-doctor-pnpm) - [pnpm config | pnpm](#pnpm-config-pnpm) - [Command line tab-completion | pnpm](#command-line-tab-completion-pnpm) - [pnpm deploy | pnpm](#pnpm-deploy-pnpm) - [pnpm import | pnpm](#pnpm-import-pnpm) - [pnpm fetch | pnpm](#pnpm-fetch-pnpm) - [pnpm install-test | pnpm](#pnpm-install-test-pnpm) - [Filtering | pnpm](#filtering-pnpm) - [pnpm help | pnpm](#pnpm-help-command-pnpm) - [Working with Git | pnpm](#working-with-git-pnpm) - [pnpm init | pnpm](#pnpm-init-pnpm) - [pnpm link | pnpm](#pnpm-link-pnpm) - [Config Dependencies | pnpm](#config-dependencies-pnpm) - [Working with Docker | pnpm](#working-with-docker-pnpm) - [Feature Comparison | pnpm](#feature-comparison-pnpm) - [Limitations | pnpm](#limitations-pnpm) - [Error Codes | pnpm](#error-codes-pnpm) - [Git Branch Lockfiles | pnpm](#git-branch-lockfiles-pnpm) - [Continuous Integration | pnpm](#continuous-integration-pnpm) - [Scripts | pnpm](#scripts-pnpm) - [pnpm cache | pnpm](#pnpm-cache-pnpm) - [pnpm install | pnpm](#pnpm-install-pnpm) - [pnpm prune | pnpm](#pnpm-prune-pnpm) - [pnpm test | pnpm](#pnpm-test-pnpm) - [pnpm start | pnpm](#pnpm-start-pnpm) - [How peers are resolved | pnpm](#how-peers-are-resolved-pnpm) - [pnpm-workspace.yaml | pnpm](#pnpm-workspace-yaml-pnpm) - [pnpm rebuild | pnpm](#pnpm-rebuild-pnpm) - [pnpm CLI | pnpm](#pnpm-cli-pnpm) - [Installation | pnpm](#installation-pnpm) - [Motivation | pnpm](#motivation-pnpm) - [pnpm why | pnpm](#pnpm-why-pnpm) - [Finders | pnpm](#finders-pnpm) - [package.json | pnpm](#package-json-pnpm) - [Aliases | pnpm](#aliases-pnpm) - [pnpm pack | pnpm](#pnpm-pack-pnpm) - [pnpm remove | pnpm](#pnpm-remove-pnpm) - [pnpm run | pnpm](#pnpm-run-pnpm) - [pnpm vs npm | pnpm](#pnpm-vs-npm-pnpm) - [Logos | pnpm](#logos-pnpm) - [Mitigating supply chain attacks | pnpm](#mitigating-supply-chain-attacks-pnpm) - [pnpm root | pnpm](#pnpm-root-pnpm) - [Working with Podman | pnpm](#working-with-podman-pnpm) - [Uninstalling pnpm | pnpm](#uninstalling-pnpm-pnpm) - [Catalogs | pnpm](#catalogs-pnpm) - [pnpm self-update | pnpm](#pnpm-self-update-pnpm) - [pnpm publish | pnpm](#pnpm-publish-pnpm) - [pnpm setup | pnpm](#pnpm-setup-pnpm) - [.pnpmfile.cjs | pnpm](#-pnpmfile-cjs-pnpm) - [Working with TypeScript | pnpm](#working-with-typescript-pnpm) - [Symlinked `node_modules` structure | pnpm](#symlinked-node-modules-structure-pnpm) - [pnpm -r, --recursive | pnpm](#pnpm-r-recursive-pnpm) - [pnpm unlink | pnpm](#pnpm-unlink-pnpm) - [Using Changesets with pnpm | pnpm](#using-changesets-with-pnpm-pnpm) - [pnpm server | pnpm](#pnpm-server-pnpm) - [pnpm update | pnpm](#pnpm-update-pnpm) - [pnpm store | pnpm](#pnpm-store-pnpm) - [pnpm cache delete | pnpm](#pnpm-cache-delete-pnpm) - [pnpm cat-file | pnpm](#pnpm-cat-file-pnpm) - [Workspace | pnpm](#workspace-pnpm) - [pnpm cache list-registries | pnpm](#pnpm-cache-list-registries-pnpm) - [pnpm cache view | pnpm](#pnpm-cache-view-pnpm) - [pnpm cat-index | pnpm](#pnpm-cat-index-pnpm) - [pnpm approve-builds | pnpm](#pnpm-approve-builds-pnpm) - [pnpm cache list | pnpm](#pnpm-cache-list-pnpm) - [pnpm env | pnpm](#pnpm-env-cmd-pnpm) - [pnpm find-hash | pnpm](#pnpm-find-hash-pnpm) - [pnpm audit | pnpm](#pnpm-audit-pnpm) - [pnpm create | pnpm](#pnpm-create-pnpm) - [pnpm licenses | pnpm](#pnpm-licenses-pnpm) - [pnpm patch-commit | pnpm](#pnpm-patch-commit-path-pnpm) - [pnpm patch-remove | pnpm](#pnpm-patch-remove-pkg-pnpm) - [pnpm patch | pnpm](#pnpm-patch-pkg-pnpm) - [pnpm bin | pnpm](#pnpm-bin-pnpm) - [pnpm ignored-builds | pnpm](#pnpm-ignored-builds-pnpm) - [pnpm dlx | pnpm](#pnpm-dlx-pnpm) - [pnpm dedupe | pnpm](#pnpm-dedupe-pnpm) - [pnpm exec | pnpm](#pnpm-exec-pnpm) - [pnpm outdated | pnpm](#pnpm-outdated-pnpm) - [pnpm list | pnpm](#pnpm-list-pnpm) - [pnpm fetch | pnpm](#pnpm-fetch-pnpm) - [pnpm install-test | pnpm](#pnpm-install-test-pnpm) - [pnpm add | pnpm](#pnpm-add-pkg-pnpm) - [pnpm doctor | pnpm](#pnpm-doctor-pnpm) - [pnpm config | pnpm](#pnpm-config-pnpm) - [pnpm import | pnpm](#pnpm-import-pnpm) - [pnpm start | pnpm](#pnpm-start-pnpm) - [pnpm deploy | pnpm](#pnpm-deploy-pnpm) - [pnpm help | pnpm](#pnpm-help-command-pnpm) - [pnpm init | pnpm](#pnpm-init-pnpm) - [pnpm link | pnpm](#pnpm-link-pnpm) - [pnpm prune | pnpm](#pnpm-prune-pnpm) - [pnpm test | pnpm](#pnpm-test-pnpm) - [pnpm install | pnpm](#pnpm-install-pnpm) - [pnpm rebuild | pnpm](#pnpm-rebuild-pnpm) - [pnpm pack | pnpm](#pnpm-pack-pnpm) - [pnpm run | pnpm](#pnpm-run-pnpm) - [pnpm root | pnpm](#pnpm-root-pnpm) - [pnpm remove | pnpm](#pnpm-remove-pnpm) - [pnpm -r, --recursive | pnpm](#pnpm-r-recursive-pnpm) - [pnpm publish | pnpm](#pnpm-publish-pnpm) - [pnpm setup | pnpm](#pnpm-setup-pnpm) - [pnpm unlink | pnpm](#pnpm-unlink-pnpm) - [pnpm self-update | pnpm](#pnpm-self-update-pnpm) - [Settings (pnpm-workspace.yaml) | pnpm](#settings-pnpm-workspace-yaml-pnpm) - [pnpm server | pnpm](#pnpm-server-pnpm) - [pnpm store | pnpm](#pnpm-store-pnpm) --- # Benchmarks of JavaScript Package Managers | pnpm [Skip to main content](https://pnpm.io/benchmarks#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** **Last benchmarked at**: _Dec 7, 2025, 3:13 AM_ (_daily_ updated). This benchmark compares the performance of npm, pnpm, Yarn Classic, and Yarn PnP (check [Yarn's benchmarks](https://yarnpkg.com/benchmarks) for any other Yarn modes that are not included here). Here's a quick explanation of how these tests could apply to the real world: * `clean install`: How long it takes to run a totally fresh install: no lockfile present, no packages in the cache, no `node_modules` folder. * `with cache`, `with lockfile`, `with node_modules`: After the first install is done, the install command is run again. * `with cache`, `with lockfile`: When a repo is fetched by a developer and installation is first run. * `with cache`: Same as the one above, but the package manager doesn't have a lockfile to work from. * `with lockfile`: When an installation runs on a CI server. * `with cache`, `with node_modules`: The lockfile is deleted and the install command is run again. * `with node_modules`, `with lockfile`: The package cache is deleted and the install command is run again. * `with node_modules`: The package cache and the lockfile is deleted and the install command is run again. * `update`: Updating your dependencies by changing the version in the `package.json` and running the install command again. Lots of Files[​](https://pnpm.io/benchmarks#lots-of-files "Direct link to Lots of Files") ------------------------------------------------------------------------------------------ The app's `package.json` [here](https://github.com/pnpm/pnpm.io/blob/main/benchmarks/fixtures/alotta-files/package.json) | action | cache | lockfile | node\_modules | npm | pnpm | Yarn | Yarn PnP | | --- | --- | --- | --- | --- | --- | --- | --- | | install | | | | 31.2s | 7.2s | 7.2s | 3.5s | | install | ✔ | ✔ | ✔ | 1.3s | 761ms | 5.2s | n/a | | install | ✔ | ✔ | | 9.1s | 2.3s | 5.3s | 1.3s | | install | ✔ | | | 13.8s | 5.1s | 7.3s | 2.9s | | install | | ✔ | | 12.5s | 4.9s | 5.4s | 1.3s | | install | ✔ | | ✔ | 1.8s | 1.9s | 7s | n/a | | install | | ✔ | ✔ | 1.3s | 739ms | 5.2s | n/a | | install | | | ✔ | 1.8s | 4.9s | 7s | n/a | | update | n/a | n/a | n/a | 6.3s | 3.2s | 5.7s | 3s | ![Graph of the alotta-files results](https://pnpm.io/img/benchmarks/alotta-files.svg) * [Lots of Files](https://pnpm.io/benchmarks#lots-of-files) --- # Motivation | pnpm [Passer au contenu principal](https://pnpm.io/fr/motivation#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** Version : 10.x Sur cette page Saving disk space[​](https://pnpm.io/fr/motivation#saving-disk-space "Direct link to Saving disk space") --------------------------------------------------------------------------------------------------------- ![An illustration of the pnpm content-addressable store. On the illustration there are two projects with node_modules. The files in the node_modules directories are hard links to the same files in the content-addressable store.](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgeG1sbnM6eGw9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjExMC41IDEyMSA2NTkuMjk0NCAyNzIuODM1OTQiIHdpZHRoPSI2NTkuMjk0NCIgaGVpZ2h0PSIyNzIuODM1OTQiPgogIDxkZWZzPgogICAgPG1hcmtlciBvcmllbnQ9ImF1dG8iIG92ZXJmbG93PSJ2aXNpYmxlIiBtYXJrZXJVbml0cz0ic3Ryb2tlV2lkdGgiIGlkPSJGaWxsZWRBcnJvd19NYXJrZXIiIHN0cm9rZS1saW5lam9pbj0ibWl0ZXIiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgdmlld0JveD0iLTEgLTQgMTAgOCIgbWFya2VyV2lkdGg9IjEwIiBtYXJrZXJIZWlnaHQ9IjgiIGNvbG9yPSIjN2Y4MDgwIj4KICAgICAgPGc+CiAgICAgICAgPHBhdGggZD0iTSA4IDAgTCAwIC0zIEwgMCAzIFoiIGZpbGw9ImN1cnJlbnRDb2xvciIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMSIvPgogICAgICA8L2c+CiAgICA8L21hcmtlcj4KICA8L2RlZnM+CiAgPGcgaWQ9IkNhbnZhc18xIiBzdHJva2UtZGFzaGFycmF5PSJub25lIiBmaWxsPSJub25lIiBzdHJva2Utb3BhY2l0eT0iMSIgZmlsbC1vcGFjaXR5PSIxIiBzdHJva2U9Im5vbmUiPgogICAgPHRpdGxlPkNhbnZhcyAxPC90aXRsZT4KICAgIDxyZWN0IGZpbGw9IndoaXRlIiB4PSIxMTAuNSIgeT0iMTIxIiB3aWR0aD0iNjU5LjI5NDQiIGhlaWdodD0iMjcyLjgzNTk0Ii8+CiAgICA8ZyBpZD0iQ2FudmFzXzFfTGF5ZXJfMSI+CiAgICAgIDx0aXRsZT5MYXllciAxPC90aXRsZT4KICAgICAgPGcgaWQ9IkdyYXBoaWNfNjMiPgogICAgICAgIDxyZWN0IHg9IjM4Ny4zOTcyIiB5PSIxNTcuMzM1OTQiIHdpZHRoPSIxMDUuNSIgaGVpZ2h0PSIzOC41IiBmaWxsPSJ3aGl0ZSIvPgogICAgICAgIDxyZWN0IHg9IjM4Ny4zOTcyIiB5PSIxNTcuMzM1OTQiIHdpZHRoPSIxMDUuNSIgaGVpZ2h0PSIzOC41IiBzdHJva2U9ImJsYWNrIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMSIvPgogICAgICAgIDx0ZXh0IHRyYW5zZm9ybT0idHJhbnNsYXRlKDM5Mi4zOTcyIDE2NS45MTc5NykiIGZpbGw9ImJsYWNrIj4KICAgICAgICAgIDx0c3BhbiBmb250LWZhbWlseT0iTW9uYWNvIiBmb250LXNpemU9IjE2IiBmaWxsPSJibGFjayIgeD0iNC41NDI5NjkiIHk9IjE2Ij4wMDAwMDAwMDE8L3RzcGFuPgogICAgICAgIDwvdGV4dD4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY182MiI+CiAgICAgICAgPHJlY3QgeD0iMzg3LjM5NzIiIHk9IjE5NS44MzU5NCIgd2lkdGg9IjEwNS41IiBoZWlnaHQ9IjM4LjUiIGZpbGw9IiNjMGZmZmYiLz4KICAgICAgICA8cmVjdCB4PSIzODcuMzk3MiIgeT0iMTk1LjgzNTk0IiB3aWR0aD0iMTA1LjUiIGhlaWdodD0iMzguNSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjEiLz4KICAgICAgICA8dGV4dCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgzOTIuMzk3MiAyMDQuNDE3OTcpIiBmaWxsPSJibGFjayI+CiAgICAgICAgICA8dHNwYW4gZm9udC1mYW1pbHk9Ik1vbmFjbyIgZm9udC1zaXplPSIxNiIgZmlsbD0iYmxhY2siIHg9IjQuNTQyOTY5IiB5PSIxNiI+MDAwMDAwMDAyPC90c3Bhbj4KICAgICAgICA8L3RleHQ+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfNjEiPgogICAgICAgIDxyZWN0IHg9IjM4Ny4zOTcyIiB5PSIyMzQuMzM1OTQiIHdpZHRoPSIxMDUuNSIgaGVpZ2h0PSIzOC41IiBmaWxsPSJ3aGl0ZSIvPgogICAgICAgIDxyZWN0IHg9IjM4Ny4zOTcyIiB5PSIyMzQuMzM1OTQiIHdpZHRoPSIxMDUuNSIgaGVpZ2h0PSIzOC41IiBzdHJva2U9ImJsYWNrIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMSIvPgogICAgICAgIDx0ZXh0IHRyYW5zZm9ybT0idHJhbnNsYXRlKDM5Mi4zOTcyIDI0Mi45MTc5NykiIGZpbGw9ImJsYWNrIj4KICAgICAgICAgIDx0c3BhbiBmb250LWZhbWlseT0iTW9uYWNvIiBmb250LXNpemU9IjE2IiBmaWxsPSJibGFjayIgeD0iNC41NDI5NjkiIHk9IjE2Ij4wMDAwMDAwMDQ8L3RzcGFuPgogICAgICAgIDwvdGV4dD4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY182MCI+CiAgICAgICAgPHJlY3QgeD0iMzg3LjM5NzIiIHk9IjI3Mi44MzU5NCIgd2lkdGg9IjEwNS41IiBoZWlnaHQ9IjM4LjUiIGZpbGw9IndoaXRlIi8+CiAgICAgICAgPHJlY3QgeD0iMzg3LjM5NzIiIHk9IjI3Mi44MzU5NCIgd2lkdGg9IjEwNS41IiBoZWlnaHQ9IjM4LjUiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIxIi8+CiAgICAgICAgPHRleHQgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMzkyLjM5NzIgMjgxLjQxNzk3KSIgZmlsbD0iYmxhY2siPgogICAgICAgICAgPHRzcGFuIGZvbnQtZmFtaWx5PSJNb25hY28iIGZvbnQtc2l6ZT0iMTYiIGZpbGw9ImJsYWNrIiB4PSI0LjU0Mjk2OSIgeT0iMTYiPjAwMDAwMDAwNTwvdHNwYW4+CiAgICAgICAgPC90ZXh0PgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzU5Ij4KICAgICAgICA8cmVjdCB4PSIzODcuMzk3MiIgeT0iMzExLjMzNTk0IiB3aWR0aD0iMTA1LjUiIGhlaWdodD0iMzguNSIgZmlsbD0iI2ZmZmZjMCIvPgogICAgICAgIDxyZWN0IHg9IjM4Ny4zOTcyIiB5PSIzMTEuMzM1OTQiIHdpZHRoPSIxMDUuNSIgaGVpZ2h0PSIzOC41IiBzdHJva2U9ImJsYWNrIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMSIvPgogICAgICAgIDx0ZXh0IHRyYW5zZm9ybT0idHJhbnNsYXRlKDM5Mi4zOTcyIDMxOS45MTc5NykiIGZpbGw9ImJsYWNrIj4KICAgICAgICAgIDx0c3BhbiBmb250LWZhbWlseT0iTW9uYWNvIiBmb250LXNpemU9IjE2IiBmaWxsPSJibGFjayIgeD0iNC41NDI5NjkiIHk9IjE2Ij4wMDAwMDAwMDY8L3RzcGFuPgogICAgICAgIDwvdGV4dD4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY181OCI+CiAgICAgICAgPHJlY3QgeD0iMzg3LjM5NzIiIHk9IjM0OS44MzU5NCIgd2lkdGg9IjEwNS41IiBoZWlnaHQ9IjM4LjUiIGZpbGw9IiNjMGZmYzAiLz4KICAgICAgICA8cmVjdCB4PSIzODcuMzk3MiIgeT0iMzQ5LjgzNTk0IiB3aWR0aD0iMTA1LjUiIGhlaWdodD0iMzguNSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjEiLz4KICAgICAgICA8dGV4dCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgzOTIuMzk3MiAzNTguNDE3OTcpIiBmaWxsPSJibGFjayI+CiAgICAgICAgICA8dHNwYW4gZm9udC1mYW1pbHk9Ik1vbmFjbyIgZm9udC1zaXplPSIxNiIgZmlsbD0iYmxhY2siIHg9IjQuNTQyOTY5IiB5PSIxNiI+MDAwMDAwMDA3PC90c3Bhbj4KICAgICAgICA8L3RleHQ+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfNTciPgogICAgICAgIDxyZWN0IHg9IjEzMy44MzcxOSIgeT0iMTk1LjgzNTk0IiB3aWR0aD0iMTg0LjU2IiBoZWlnaHQ9IjM4LjUiIGZpbGw9IiNjMGZmZmYiLz4KICAgICAgICA8cmVjdCB4PSIxMzMuODM3MTkiIHk9IjE5NS44MzU5NCIgd2lkdGg9IjE4NC41NiIgaGVpZ2h0PSIzOC41IiBzdHJva2U9ImJsYWNrIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMSIvPgogICAgICAgIDx0ZXh0IHRyYW5zZm9ybT0idHJhbnNsYXRlKDEzOC44MzcxOSAyMDQuNDE3OTcpIiBmaWxsPSJibGFjayI+CiAgICAgICAgICA8dHNwYW4gZm9udC1mYW1pbHk9Ik1vbmFjbyIgZm9udC1zaXplPSIxNiIgZmlsbD0iYmxhY2siIHg9IjAiIHk9IjE2Ij5pcy1vZGQvaW5kZXguanM8L3RzcGFuPgogICAgICAgIDwvdGV4dD4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY181NiI+CiAgICAgICAgPHJlY3QgeD0iMTMzLjgzNzE5IiB5PSIyMzQuMzM1OTQiIHdpZHRoPSIxODQuNTYiIGhlaWdodD0iMzguNSIgZmlsbD0iI2MwZmZjMCIvPgogICAgICAgIDxyZWN0IHg9IjEzMy44MzcxOSIgeT0iMjM0LjMzNTk0IiB3aWR0aD0iMTg0LjU2IiBoZWlnaHQ9IjM4LjUiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIxIi8+CiAgICAgICAgPHRleHQgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTM4LjgzNzE5IDI0Mi45MTc5NykiIGZpbGw9ImJsYWNrIj4KICAgICAgICAgIDx0c3BhbiBmb250LWZhbWlseT0iTW9uYWNvIiBmb250LXNpemU9IjE2IiBmaWxsPSJibGFjayIgeD0iMCIgeT0iMTYiPmlzLW9kZC9MSUNFTlNFLm1kPC90c3Bhbj4KICAgICAgICA8L3RleHQ+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfNTUiPgogICAgICAgIDxyZWN0IHg9IjU2MS44OTcyIiB5PSIxOTUuODM1OTQiIHdpZHRoPSIxODQuNTYiIGhlaWdodD0iMzguNSIgZmlsbD0iI2ZmZmZjMCIvPgogICAgICAgIDxyZWN0IHg9IjU2MS44OTcyIiB5PSIxOTUuODM1OTQiIHdpZHRoPSIxODQuNTYiIGhlaWdodD0iMzguNSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjEiLz4KICAgICAgICA8dGV4dCB0cmFuc2Zvcm09InRyYW5zbGF0ZSg1NjYuODk3MiAyMDQuNDE3OTcpIiBmaWxsPSJibGFjayI+CiAgICAgICAgICA8dHNwYW4gZm9udC1mYW1pbHk9Ik1vbmFjbyIgZm9udC1zaXplPSIxNiIgZmlsbD0iYmxhY2siIHg9IjAiIHk9IjE2Ij5pcy1ldmVuL2luZGV4LmpzPC90c3Bhbj4KICAgICAgICA8L3RleHQ+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfNTQiPgogICAgICAgIDxyZWN0IHg9IjU2MS44OTcyIiB5PSIyMzQuMzM1OTQiIHdpZHRoPSIxODQuNTYiIGhlaWdodD0iMzguNSIgZmlsbD0iI2MwZmZjMCIvPgogICAgICAgIDxyZWN0IHg9IjU2MS44OTcyIiB5PSIyMzQuMzM1OTQiIHdpZHRoPSIxODQuNTYiIGhlaWdodD0iMzguNSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjEiLz4KICAgICAgICA8dGV4dCB0cmFuc2Zvcm09InRyYW5zbGF0ZSg1NjYuODk3MiAyNDIuOTE3OTcpIiBmaWxsPSJibGFjayI+CiAgICAgICAgICA8dHNwYW4gZm9udC1mYW1pbHk9Ik1vbmFjbyIgZm9udC1zaXplPSIxNiIgZmlsbD0iYmxhY2siIHg9IjAiIHk9IjE2Ij5pcy1ldmVuL0xJQ0VOU0UubWQ8L3RzcGFuPgogICAgICAgIDwvdGV4dD4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY181MyI+CiAgICAgICAgPHRleHQgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMzIwLjEyNzY2IDEzMSkiIGZpbGw9ImJsYWNrIj4KICAgICAgICAgIDx0c3BhbiBmb250LWZhbWlseT0iTW9uYWNvIiBmb250LXNpemU9IjE2IiBmaWxsPSJibGFjayIgeD0iMCIgeT0iMTYiPkNvbnRlbnQtYWRkcmVzc2FibGUgc3RvcmU8L3RzcGFuPgogICAgICAgIDwvdGV4dD4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY181MiI+CiAgICAgICAgPHRleHQgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTIwLjUgMTY5LjUpIiBmaWxsPSJibGFjayI+CiAgICAgICAgICA8dHNwYW4gZm9udC1mYW1pbHk9Ik1vbmFjbyIgZm9udC1zaXplPSIxNiIgZmlsbD0iYmxhY2siIHg9IjAiIHk9IjE2Ij5wcm9qZWN0XzEvbm9kZV9tb2R1bGVzPC90c3Bhbj4KICAgICAgICA8L3RleHQ+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfNDciPgogICAgICAgIDx0ZXh0IHRyYW5zZm9ybT0idHJhbnNsYXRlKDU0OC41NiAxNzIuMzg3OTQpIiBmaWxsPSJibGFjayI+CiAgICAgICAgICA8dHNwYW4gZm9udC1mYW1pbHk9Ik1vbmFjbyIgZm9udC1zaXplPSIxNiIgZmlsbD0iYmxhY2siIHg9IjAiIHk9IjE2Ij5wcm9qZWN0XzIvbm9kZV9tb2R1bGVzPC90c3Bhbj4KICAgICAgICA8L3RleHQ+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkxpbmVfNjQiPgogICAgICAgIDxsaW5lIHgxPSIzMTguMzk3MiIgeTE9IjIxNS4wODU5NCIgeDI9IjM3Ny40OTcyIiB5Mj0iMjE1LjA4NTk0IiBtYXJrZXItZW5kPSJ1cmwoI0ZpbGxlZEFycm93X01hcmtlcikiIHN0cm9rZT0iIzdmODA4MCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjEiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iTGluZV83MSI+CiAgICAgICAgPHBhdGggZD0iTSA1NjEuODk3MiAyMTUuMDg1OTQgTCA1NTEuODk3MiAyMTUuMDg1OTQgTCA1MzEuNTE3NzUgMjE1LjI0MzQgTCA1MTguMDA5OTQgMjE1LjI0MzQgTCA1MTguMDA5OTQgMzMwLjU4NTk0IEwgNTAyLjc5NzIgMzMwLjU4NTk0IiBtYXJrZXItZW5kPSJ1cmwoI0ZpbGxlZEFycm93X01hcmtlcikiIHN0cm9rZT0iIzdmODA4MCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjEiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iTGluZV83MiI+CiAgICAgICAgPHBhdGggZD0iTSAzMTguMzk3MiAyNTMuNTg1OTQgTCAzMjguMzk3MiAyNTMuNTg1OTQgTCAzNTQuNDUxMzQgMjUzLjEwNjcgTCAzNTQuNTQxMiAzNDkuODM1OTQgTCAzNTQuNTQxMiAzNjkuMDg1OTQgTCAzNzcuNDk3MiAzNjkuMDg1OTQiIG1hcmtlci1lbmQ9InVybCgjRmlsbGVkQXJyb3dfTWFya2VyKSIgc3Ryb2tlPSIjN2Y4MDgwIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMSIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJMaW5lXzc0Ij4KICAgICAgICA8cGF0aCBkPSJNIDU2MS44OTcyIDI1My41ODU5NCBMIDU1MS44OTcyIDI1My41ODU5NCBMIDU0MC43MjMyIDI1My44ODc5NCBMIDU0MC43MjMyIDM2OS4wODU5NCBMIDUwMi43OTcyIDM2OS4wODU5NCIgbWFya2VyLWVuZD0idXJsKCNGaWxsZWRBcnJvd19NYXJrZXIpIiBzdHJva2U9IiM3ZjgwODAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIxIi8+CiAgICAgIDwvZz4KICAgIDwvZz4KICA8L2c+Cjwvc3ZnPgo=) Lorsque vous utilisez npm, si vous avez 100 projets utilisant une dépendance, vous aurez 100 copies de cette dépendance enregistrées sur le disque. Avec pnpm, la dépendance sera stockée dans un stockage adressable au contenu, donc: 1. Si vous dépendez de différentes versions de la dépendance, seuls les fichiers qui diffèrent sont ajoutés au stockage. For instance, if it has 100 files, and a new version has a change in only one of those files, `pnpm update` will only add 1 new file to the store, instead of cloning the entire dependency just for the singular change. 2. Tous les fichiers sont enregistrés en un seul endroit sur le disque. Lorsque des packages sont installés, leurs fichiers sont liés directement à partir de cet emplacement unique, ne consommant aucun espace disque supplémentaire. Cela vous permet de partager les dépendances de même version entre les projets. En conséquence, vous économisez beaucoup d'espace sur votre disque proportionnellement au nombre de projets et de dépendances, et vous avez des installations beaucoup plus rapides ! Boosting installation speed[​](https://pnpm.io/fr/motivation#boosting-installation-speed "Direct link to Boosting installation speed") --------------------------------------------------------------------------------------------------------------------------------------- pnpm performs installation in three stages: 1. Dependency resolution. All required dependencies are identified and fetched to the store. 2. Directory structure calculation. The `node_modules` directory structure is calculated based on the dependencies. 3. Linking dependencies. All remaining dependencies are fetched and hard linked from the store to `node_modules`. ![An illustration of the pnpm install process. Packages are resolved, fetched, and hard linked as soon as possible.](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bD0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHZpZXdCb3g9IjEzNS4wOTUwNSAxNDA3IDU3NC4zNDg3IDMxNC4zOTYiIHdpZHRoPSI1NzQuMzQ4NyIgaGVpZ2h0PSIzMTQuMzk2Ij4KICA8ZGVmcz4KICAgIDxtYXJrZXIgb3JpZW50PSJhdXRvIiBvdmVyZmxvdz0idmlzaWJsZSIgbWFya2VyVW5pdHM9InN0cm9rZVdpZHRoIiBpZD0iRmlsbGVkQXJyb3dfTWFya2VyIiBzdHJva2UtbGluZWpvaW49Im1pdGVyIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHZpZXdCb3g9Ii0xIC00IDEwIDgiIG1hcmtlcldpZHRoPSIxMCIgbWFya2VySGVpZ2h0PSI4IiBjb2xvcj0iYmxhY2siPgogICAgICA8Zz4KICAgICAgICA8cGF0aCBkPSJNIDggMCBMIDAgLTMgTCAwIDMgWiIgZmlsbD0iY3VycmVudENvbG9yIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIxIi8+CiAgICAgIDwvZz4KICAgIDwvbWFya2VyPgogIDwvZGVmcz4KICA8ZyBpZD0iQ2FudmFzXzEiIHN0cm9rZS1vcGFjaXR5PSIxIiBmaWxsPSJub25lIiBmaWxsLW9wYWNpdHk9IjEiIHN0cm9rZS1kYXNoYXJyYXk9Im5vbmUiIHN0cm9rZT0ibm9uZSI+CiAgICA8dGl0bGU+Q2FudmFzIDE8L3RpdGxlPgogICAgPHJlY3QgZmlsbD0id2hpdGUiIHg9IjEzNS4wOTUwNSIgeT0iMTQwNyIgd2lkdGg9IjU3NC4zNDg3IiBoZWlnaHQ9IjMxNC4zOTYiLz4KICAgIDxnIGlkPSJDYW52YXNfMV9MYXllcl8xIj4KICAgICAgPHRpdGxlPkxheWVyIDE8L3RpdGxlPgogICAgICA8ZyBpZD0iR3JhcGhpY18xNDgiPgogICAgICAgIDxyZWN0IHg9IjE0MS41OTUwNSIgeT0iMTQ0NS40NDgiIHdpZHRoPSI4Mi4xMjU5MiIgaGVpZ2h0PSIyMiIgZmlsbD0iIzYwZDkzNiIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzE0NyI+CiAgICAgICAgPHJlY3QgeD0iMjIzLjcyMDk3IiB5PSIxNDQ1LjQ0OCIgd2lkdGg9IjEwMC41NjIzNSIgaGVpZ2h0PSIyMiIgZmlsbD0iIzAwYTJmZiIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzE0NiI+CiAgICAgICAgPHJlY3QgeD0iNTA3LjM5MDYiIHk9IjE0NDUuNDQ4IiB3aWR0aD0iNDguNjA1MTM0IiBoZWlnaHQ9IjIyIiBmaWxsPSIjZmVhZTAwIi8+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfMTQ1Ij4KICAgICAgICA8cmVjdCB4PSIxNDEuNTk1MDUiIHk9IjE0NzIuNDQ4IiB3aWR0aD0iNDEuMDYyOTYiIGhlaWdodD0iMjIiIGZpbGw9IiM2MGQ5MzYiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xNDQiPgogICAgICAgIDxyZWN0IHg9IjE4Mi42NTgiIHk9IjE0NzIuNDQ4IiB3aWR0aD0iNjguMjU1MDIiIGhlaWdodD0iMjIiIGZpbGw9IiMwMGEyZmYiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xNDMiPgogICAgICAgIDxyZWN0IHg9IjIyMy43MjA5NyIgeT0iMTQ5OS40NDgiIHdpZHRoPSI0OC42MDUxMzQiIGhlaWdodD0iMjIiIGZpbGw9IiM2MGQ5MzYiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xNDIiPgogICAgICAgIDxyZWN0IHg9IjIyMy43MjA5NyIgeT0iMTUyNi40NDgiIHdpZHRoPSI4Mi4xMjU5MiIgaGVpZ2h0PSIyMiIgZmlsbD0iIzYwZDkzNiIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzE0MSI+CiAgICAgICAgPHJlY3QgeD0iMjcyLjMyNjEiIHk9IjE1NTMuNDQ4IiB3aWR0aD0iNTguNjYxMzciIGhlaWdodD0iMjIiIGZpbGw9IiM2MGQ5MzYiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xNDAiPgogICAgICAgIDxyZWN0IHg9IjMwNy41MjI5MiIgeT0iMTU4MC40NDgiIHdpZHRoPSI4Mi4xMjU5MiIgaGVpZ2h0PSIyMiIgZmlsbD0iIzYwZDkzNiIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzEzOSI+CiAgICAgICAgPHJlY3QgeD0iMzMwLjk4NzQ3IiB5PSIxNjA3LjQ0OCIgd2lkdGg9IjQxLjA2Mjk2IiBoZWlnaHQ9IjIyIiBmaWxsPSIjNjBkOTM2Ii8+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfMTM4Ij4KICAgICAgICA8cmVjdCB4PSIzMzAuOTg3NDciIHk9IjE2MzQuNDQ4IiB3aWR0aD0iODkuNSIgaGVpZ2h0PSIyMiIgZmlsbD0iIzYwZDkzNiIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzEzNyI+CiAgICAgICAgPHJlY3QgeD0iMjcyLjMyNjEiIHk9IjE0OTkuNDQ4IiB3aWR0aD0iMTkwLjIzMDQ0IiBoZWlnaHQ9IjIyIiBmaWxsPSIjMDBhMmZmIi8+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfMTM2Ij4KICAgICAgICA8cmVjdCB4PSIzMDUuODQ2OSIgeT0iMTUyNi40NDgiIHdpZHRoPSIyOTYuNjU4OTIiIGhlaWdodD0iMjIiIGZpbGw9IiMwMGEyZmYiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xMzUiPgogICAgICAgIDxyZWN0IHg9IjMzMC45ODc0NyIgeT0iMTU1My40NDgiIHdpZHRoPSIxNTguMzg1NyIgaGVpZ2h0PSIyMiIgZmlsbD0iIzAwYTJmZiIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzEzNCI+CiAgICAgICAgPHJlY3QgeD0iMzg5LjY0ODg0IiB5PSIxNTgwLjQ0OCIgd2lkdGg9IjE1MC4wMDU1IiBoZWlnaHQ9IjIyIiBmaWxsPSIjMDBhMmZmIi8+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfMTMzIj4KICAgICAgICA8cmVjdCB4PSIzNzIuMDUwNDMiIHk9IjE2MDcuNDQ4IiB3aWR0aD0iMjQ5LjcyOTgzIiBoZWlnaHQ9IjIyIiBmaWxsPSIjMDBhMmZmIi8+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfMTMyIj4KICAgICAgICA8cmVjdCB4PSI0MjAuNDkzNiIgeT0iMTYzNC40NDgiIHdpZHRoPSIxNTEuMDA1NSIgaGVpZ2h0PSIyMiIgZmlsbD0iIzAwYTJmZiIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzEzMCI+CiAgICAgICAgPHJlY3QgeD0iNTA3LjM5MDYiIHk9IjE0NzIuNDQ4IiB3aWR0aD0iMzIuMjYzNzUzIiBoZWlnaHQ9IjIyIiBmaWxsPSIjZmVhZTAwIi8+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfMTI5Ij4KICAgICAgICA8cmVjdCB4PSI1MDcuMzkwNiIgeT0iMTQ5OS40NDgiIHdpZHRoPSI2OC4yNTUwMiIgaGVpZ2h0PSIyMiIgZmlsbD0iI2ZlYWUwMCIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzEyOCI+CiAgICAgICAgPHJlY3QgeD0iNjAyLjUwNTgiIHk9IjE1MjYuNDQ4IiB3aWR0aD0iMTAwLjU2MjM1IiBoZWlnaHQ9IjIyIiBmaWxsPSIjZmVhZTAwIi8+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfMTI3Ij4KICAgICAgICA8cmVjdCB4PSI1MDcuMzkwNiIgeT0iMTU1My40NDgiIHdpZHRoPSI0Ny43NjcxMTUiIGhlaWdodD0iMjIiIGZpbGw9IiNmZWFlMDAiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xMjYiPgogICAgICAgIDxyZWN0IHg9IjUzOS42NTQzNCIgeT0iMTU4MC40NDgiIHdpZHRoPSIxMDAuNTYyMzUiIGhlaWdodD0iMjIiIGZpbGw9IiNmZWFlMDAiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xMjUiPgogICAgICAgIDxyZWN0IHg9IjYyMS43ODAyNiIgeT0iMTYwNy40NDgiIHdpZHRoPSI1OC42NjEzNyIgaGVpZ2h0PSIyMiIgZmlsbD0iI2ZlYWUwMCIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzEyNCI+CiAgICAgICAgPHJlY3QgeD0iNTcxLjQ5OTEiIHk9IjE2MzQuNDQ4IiB3aWR0aD0iNTguNjYxMzciIGhlaWdodD0iMjIiIGZpbGw9IiNmZWFlMDAiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iTGluZV8xMjMiPgogICAgICAgIDxwYXRoIGQ9Ik0gNTA3LjM5MDYgMTQzMS40NDggTCA1MDcuNTE1IDE0NzEuNDkxNSBMIDUwNy4zOTA2IDE1NDEuMjM3MyBMIDUwNi41MTUgMTY2Ni43NSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2UtZGFzaGFycmF5PSI0LjAsNC4wIiBzdHJva2Utd2lkdGg9IjEiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iTGluZV8xMjIiPgogICAgICAgIDxwYXRoIGQ9Ik0gMTQxLjQ3MDY2IDE0MzEuNDQ4IEwgMTQxLjU5NTA1IDE0NzEuOTIxIEwgMTQxLjQ3MDY2IDE1NDIuNDE0NiBMIDE0MC41OTUwNSAxNjY2Ljc1IiBzdHJva2U9ImJsYWNrIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS1kYXNoYXJyYXk9IjQuMCw0LjAiIHN0cm9rZS13aWR0aD0iMSIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJMaW5lXzEyMSI+CiAgICAgICAgPHBhdGggZD0iTSA3MDIuOTQzOCAxNDMxLjQ0OCBMIDcwMy4wNjgxNSAxNDcxLjA3IEwgNzAyLjk0MzggMTU0MC4wODE3IEwgNzAzLjA2ODE1IDE2NjcuMjUiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLWRhc2hhcnJheT0iNC4wLDQuMCIgc3Ryb2tlLXdpZHRoPSIxIi8+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfMTE2Ij4KICAgICAgICA8dGV4dCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyNzcuMDk2MyAxNDE3KSIgZmlsbD0iYmxhY2siPgogICAgICAgICAgPHRzcGFuIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2EgTmV1ZSIgZm9udC1zaXplPSIxNiIgZmlsbD0iYmxhY2siIHg9IjMxOTc0NDIzZS0yMCIgeT0iMTUiPjE8L3RzcGFuPgogICAgICAgIDwvdGV4dD4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iTGluZV8xMTUiPgogICAgICAgIDxsaW5lIHgxPSIxNDEuNDk0NTMiIHkxPSIxNDM5LjIxNDUiIHgyPSI0MTEuNDk0OTgiIHkyPSIxNDM5LjcyNDYiIG1hcmtlci1lbmQ9InVybCgjRmlsbGVkQXJyb3dfTWFya2VyKSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjEiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iTGluZV8xMTQiPgogICAgICAgIDxsaW5lIHgxPSI0MjMuNTg4NjMiIHkxPSIxNDM5LjQ0OCIgeDI9IjQ5Ny41MTYyNiIgeTI9IjE0MzkuNjY4MiIgbWFya2VyLWVuZD0idXJsKCNGaWxsZWRBcnJvd19NYXJrZXIpIiBzdHJva2U9ImJsYWNrIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMSIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJMaW5lXzExMyI+CiAgICAgICAgPGxpbmUgeDE9IjUwNy40MTQ3IiB5MT0iMTQzOS4yMTc2IiB4Mj0iNjkzLjA2ODIiIHkyPSIxNDM5LjIyNjgiIG1hcmtlci1lbmQ9InVybCgjRmlsbGVkQXJyb3dfTWFya2VyKSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjEiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xMTIiPgogICAgICAgIDx0ZXh0IHRyYW5zZm9ybT0idHJhbnNsYXRlKDQ2MC4yMDM2IDE0MTcpIiBmaWxsPSJibGFjayI+CiAgICAgICAgICA8dHNwYW4gZm9udC1mYW1pbHk9IkhlbHZldGljYSBOZXVlIiBmb250LXNpemU9IjE2IiBmaWxsPSJibGFjayIgeD0iMzE5NzQ0MjNlLTIwIiB5PSIxNSI+MjwvdHNwYW4+CiAgICAgICAgPC90ZXh0PgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzExMSI+CiAgICAgICAgPHRleHQgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNTk5LjgyMzk2IDE0MTcpIiBmaWxsPSJibGFjayI+CiAgICAgICAgICA8dHNwYW4gZm9udC1mYW1pbHk9IkhlbHZldGljYSBOZXVlIiBmb250LXNpemU9IjE2IiBmaWxsPSJibGFjayIgeD0iNi42ODM4NzciIHk9IjE1Ij4zPC90c3Bhbj4KICAgICAgICA8L3RleHQ+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfMTg2Ij4KICAgICAgICA8dGV4dCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNDYuNTk1MDUgMTY3MC45NDgpIiBmaWxsPSJibGFjayI+CiAgICAgICAgICA8dHNwYW4gZm9udC1mYW1pbHk9IkhlbHZldGljYSBOZXVlIiBmb250LXNpemU9IjE2IiBmaWxsPSJibGFjayIgeD0iODUyNjUxM2UtMTkiIHk9IjE1Ij5QYWNrYWdlIGluc3RhbGxhdGlvbiBwcm9ncmVzczo8L3RzcGFuPgogICAgICAgIDwvdGV4dD4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xODUiPgogICAgICAgIDxyZWN0IHg9IjE0MS41OTUwNSIgeT0iMTY5NC4zOTYiIHdpZHRoPSI4OS41IiBoZWlnaHQ9IjIyIiBmaWxsPSIjNjBkOTM2Ii8+CiAgICAgICAgPHRleHQgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTQ2LjU5NTA1IDE2OTYuMTcyKSIgZmlsbD0id2hpdGUiPgogICAgICAgICAgPHRzcGFuIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2EgTmV1ZSIgZm9udC1zaXplPSIxNiIgZmlsbD0id2hpdGUiIHg9IjQuNzkiIHk9IjE1Ij5SZXNvbHZpbmc8L3RzcGFuPgogICAgICAgIDwvdGV4dD4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xODQiPgogICAgICAgIDxyZWN0IHg9IjIzMS4wOTUwNSIgeT0iMTY5NC4zOTYiIHdpZHRoPSI4OS41IiBoZWlnaHQ9IjIyIiBmaWxsPSIjMDBhMmZmIi8+CiAgICAgICAgPHRleHQgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMjM2LjA5NTA1IDE2OTYuMTcyKSIgZmlsbD0id2hpdGUiPgogICAgICAgICAgPHRzcGFuIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2EgTmV1ZSIgZm9udC1zaXplPSIxNiIgZmlsbD0id2hpdGUiIHg9IjguNzgyIiB5PSIxNSI+RmV0Y2hpbmc8L3RzcGFuPgogICAgICAgIDwvdGV4dD4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xODMiPgogICAgICAgIDxyZWN0IHg9IjMyMC41OTUwNSIgeT0iMTY5NC4zOTYiIHdpZHRoPSI4OS41IiBoZWlnaHQ9IjIyIiBmaWxsPSIjZmVhZTAwIi8+CiAgICAgICAgPHRleHQgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMzI1LjU5NTA1IDE2OTYuMTcyKSIgZmlsbD0id2hpdGUiPgogICAgICAgICAgPHRzcGFuIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2EgTmV1ZSIgZm9udC1zaXplPSIxNiIgZmlsbD0id2hpdGUiIHg9IjE0LjExIiB5PSIxNSI+TGlua2luZzwvdHNwYW4+CiAgICAgICAgPC90ZXh0PgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJMaW5lXzE4OCI+CiAgICAgICAgPHBhdGggZD0iTSA0MjEuMzY5MiAxNDMxLjQ0OCBMIDQyMS40OTM2IDE0NzEuNDkxNSBMIDQyMS4zNjkyIDE1NDEuMjM3MyBMIDQyMC40OTM2IDE2NjYuNzUiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLWRhc2hhcnJheT0iNC4wLDQuMCIgc3Ryb2tlLXdpZHRoPSIxIi8+CiAgICAgIDwvZz4KICAgIDwvZz4KICA8L2c+Cjwvc3ZnPgo=) This approach is significantly faster than the traditional three-stage installation process of resolving, fetching, and writing all dependencies to `node_modules`. ![An illustration of how package managers like Yarn Classic or npm install dependencies.](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgeG1sbnM6eGw9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjE2Ny41OTUwNSAxNzc3IDY5MC4xMTk4IDMxNC4zOTYiIHdpZHRoPSI2OTAuMTE5OCIgaGVpZ2h0PSIzMTQuMzk2Ij4KICA8ZGVmcz4KICAgIDxtYXJrZXIgb3JpZW50PSJhdXRvIiBvdmVyZmxvdz0idmlzaWJsZSIgbWFya2VyVW5pdHM9InN0cm9rZVdpZHRoIiBpZD0iRmlsbGVkQXJyb3dfTWFya2VyIiBzdHJva2UtbGluZWpvaW49Im1pdGVyIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHZpZXdCb3g9Ii0xIC00IDEwIDgiIG1hcmtlcldpZHRoPSIxMCIgbWFya2VySGVpZ2h0PSI4IiBjb2xvcj0iYmxhY2siPgogICAgICA8Zz4KICAgICAgICA8cGF0aCBkPSJNIDggMCBMIDAgLTMgTCAwIDMgWiIgZmlsbD0iY3VycmVudENvbG9yIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIxIi8+CiAgICAgIDwvZz4KICAgIDwvbWFya2VyPgogIDwvZGVmcz4KICA8ZyBpZD0iQ2FudmFzXzEiIHN0cm9rZS1kYXNoYXJyYXk9Im5vbmUiIGZpbGw9Im5vbmUiIHN0cm9rZS1vcGFjaXR5PSIxIiBmaWxsLW9wYWNpdHk9IjEiIHN0cm9rZT0ibm9uZSI+CiAgICA8dGl0bGU+Q2FudmFzIDE8L3RpdGxlPgogICAgPHJlY3QgZmlsbD0id2hpdGUiIHg9IjE2Ny41OTUwNSIgeT0iMTc3NyIgd2lkdGg9IjY5MC4xMTk4IiBoZWlnaHQ9IjMxNC4zOTYiLz4KICAgIDxnIGlkPSJDYW52YXNfMV9MYXllcl8xIj4KICAgICAgPHRpdGxlPkxheWVyIDE8L3RpdGxlPgogICAgICA8ZyBpZD0iR3JhcGhpY18xMjAiPgogICAgICAgIDx0ZXh0IHRyYW5zZm9ybT0idHJhbnNsYXRlKDE3OS4wOTUwNSAyMDQwLjk0OCkiIGZpbGw9ImJsYWNrIj4KICAgICAgICAgIDx0c3BhbiBmb250LWZhbWlseT0iSGVsdmV0aWNhIE5ldWUiIGZvbnQtc2l6ZT0iMTYiIGZpbGw9ImJsYWNrIiB4PSI4NTI2NTEzZS0xOSIgeT0iMTUiPlBhY2thZ2UgaW5zdGFsbGF0aW9uIHByb2dyZXNzOjwvdHNwYW4+CiAgICAgICAgPC90ZXh0PgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzExOSI+CiAgICAgICAgPHJlY3QgeD0iMTc0LjA5NTA1IiB5PSIyMDY0LjM5NiIgd2lkdGg9Ijg5LjUiIGhlaWdodD0iMjIiIGZpbGw9IiM2MGQ5MzYiLz4KICAgICAgICA8dGV4dCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNzkuMDk1MDUgMjA2Ni4xNzIpIiBmaWxsPSJ3aGl0ZSI+CiAgICAgICAgICA8dHNwYW4gZm9udC1mYW1pbHk9IkhlbHZldGljYSBOZXVlIiBmb250LXNpemU9IjE2IiBmaWxsPSJ3aGl0ZSIgeD0iNC43OSIgeT0iMTUiPlJlc29sdmluZzwvdHNwYW4+CiAgICAgICAgPC90ZXh0PgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzExOCI+CiAgICAgICAgPHJlY3QgeD0iMjYzLjU5NTA1IiB5PSIyMDY0LjM5NiIgd2lkdGg9Ijg5LjUiIGhlaWdodD0iMjIiIGZpbGw9IiMwMGEyZmYiLz4KICAgICAgICA8dGV4dCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyNjguNTk1MDUgMjA2Ni4xNzIpIiBmaWxsPSJ3aGl0ZSI+CiAgICAgICAgICA8dHNwYW4gZm9udC1mYW1pbHk9IkhlbHZldGljYSBOZXVlIiBmb250LXNpemU9IjE2IiBmaWxsPSJ3aGl0ZSIgeD0iOC43ODIiIHk9IjE1Ij5GZXRjaGluZzwvdHNwYW4+CiAgICAgICAgPC90ZXh0PgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzExNyI+CiAgICAgICAgPHJlY3QgeD0iMzUzLjA5NTA1IiB5PSIyMDY0LjM5NiIgd2lkdGg9Ijg5LjUiIGhlaWdodD0iMjIiIGZpbGw9IiNmZWFlMDAiLz4KICAgICAgICA8dGV4dCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgzNTguMDk1MDUgMjA2Ni4xNzIpIiBmaWxsPSJ3aGl0ZSI+CiAgICAgICAgICA8dHNwYW4gZm9udC1mYW1pbHk9IkhlbHZldGljYSBOZXVlIiBmb250LXNpemU9IjE2IiBmaWxsPSJ3aGl0ZSIgeD0iMTQuMTEiIHk9IjE1Ij5MaW5raW5nPC90c3Bhbj4KICAgICAgICA8L3RleHQ+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfMTgyIj4KICAgICAgICA8cmVjdCB4PSIxNzQuMDk1MDUiIHk9IjE4MTUuNDQ4IiB3aWR0aD0iODIuMTI1OTIiIGhlaWdodD0iMjIiIGZpbGw9IiM2MGQ5MzYiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xODEiPgogICAgICAgIDxyZWN0IHg9IjQ1My45OTM2IiB5PSIxODE1LjQ0OCIgd2lkdGg9IjEwMC41NjIzNSIgaGVpZ2h0PSIyMiIgZmlsbD0iIzAwYTJmZiIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzE4MCI+CiAgICAgICAgPHJlY3QgeD0iNzUwLjY1MjUiIHk9IjE4MTUuNDQ4IiB3aWR0aD0iNDguNjA1MTM0IiBoZWlnaHQ9IjIyIiBmaWxsPSIjZmVhZTAwIi8+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfMTc5Ij4KICAgICAgICA8cmVjdCB4PSIxNzQuMDk1MDUiIHk9IjE4NDIuNDQ4IiB3aWR0aD0iNDEuMDYyOTYiIGhlaWdodD0iMjIiIGZpbGw9IiM2MGQ5MzYiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xNzgiPgogICAgICAgIDxyZWN0IHg9IjQ1My45OTM2IiB5PSIxODQyLjQ0OCIgd2lkdGg9IjY4LjI1NTAyIiBoZWlnaHQ9IjIyIiBmaWxsPSIjMDBhMmZmIi8+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfMTc3Ij4KICAgICAgICA8cmVjdCB4PSIyNTYuMjIwOTciIHk9IjE4NjkuNDQ4IiB3aWR0aD0iNDguNjA1MTM0IiBoZWlnaHQ9IjIyIiBmaWxsPSIjNjBkOTM2Ii8+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfMTc2Ij4KICAgICAgICA8cmVjdCB4PSIyNTYuMjIwOTciIHk9IjE4OTYuNDQ4IiB3aWR0aD0iODIuMTI1OTIiIGhlaWdodD0iMjIiIGZpbGw9IiM2MGQ5MzYiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xNzUiPgogICAgICAgIDxyZWN0IHg9IjMwNC44MjYxIiB5PSIxOTIzLjQ0OCIgd2lkdGg9IjU4LjY2MTM3IiBoZWlnaHQ9IjIyIiBmaWxsPSIjNjBkOTM2Ii8+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfMTc0Ij4KICAgICAgICA8cmVjdCB4PSIzNDAuMDIyOTIiIHk9IjE5NTAuNDQ4IiB3aWR0aD0iODIuMTI1OTIiIGhlaWdodD0iMjIiIGZpbGw9IiM2MGQ5MzYiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xNzMiPgogICAgICAgIDxyZWN0IHg9IjM2My40ODc0NyIgeT0iMTk3Ny40NDgiIHdpZHRoPSI0MS4wNjI5NiIgaGVpZ2h0PSIyMiIgZmlsbD0iIzYwZDkzNiIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzE3MiI+CiAgICAgICAgPHJlY3QgeD0iMzYzLjQ4NzQ3IiB5PSIyMDA0LjQ0OCIgd2lkdGg9IjkwLjUwNjExIiBoZWlnaHQ9IjIyIiBmaWxsPSIjNjBkOTM2Ii8+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfMTcxIj4KICAgICAgICA8cmVjdCB4PSI0NTMuOTkzNiIgeT0iMTg2OS40NDgiIHdpZHRoPSIxOTAuMjMwNDQiIGhlaWdodD0iMjIiIGZpbGw9IiMwMGEyZmYiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xNzAiPgogICAgICAgIDxyZWN0IHg9IjQ1My45OTM2IiB5PSIxODk2LjQ0OCIgd2lkdGg9IjI5Ni42NTg5MiIgaGVpZ2h0PSIyMiIgZmlsbD0iIzAwYTJmZiIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzE2OSI+CiAgICAgICAgPHJlY3QgeD0iNDUzLjk5MzYiIHk9IjE5MjMuMzMzNiIgd2lkdGg9IjE1OC4zODU3IiBoZWlnaHQ9IjIyIiBmaWxsPSIjMDBhMmZmIi8+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfMTY4Ij4KICAgICAgICA8cmVjdCB4PSI0NTMuOTkzNiIgeT0iMTk1MC4yMTkyIiB3aWR0aD0iMTUwLjAwNTUiIGhlaWdodD0iMjIiIGZpbGw9IiMwMGEyZmYiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xNjciPgogICAgICAgIDxyZWN0IHg9IjQ1My45OTM2IiB5PSIxOTc3LjMzMzYiIHdpZHRoPSIyNDkuNzI5ODMiIGhlaWdodD0iMjIiIGZpbGw9IiMwMGEyZmYiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xNjYiPgogICAgICAgIDxyZWN0IHg9IjQ1My45OTM2IiB5PSIyMDA0LjQ0OCIgd2lkdGg9IjE1MC4wMDU1IiBoZWlnaHQ9IjIyIiBmaWxsPSIjMDBhMmZmIi8+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkxpbmVfMTY1Ij4KICAgICAgICA8cGF0aCBkPSJNIDQ1My45OTM2IDE4MDEuNDQ4IEwgNDU0LjExOCAxODQxLjIzNzUgTCA0NTMuOTkzNiAxOTEwLjU0MSBMIDQ1NC4xMTggMjAzNS43NSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2UtZGFzaGFycmF5PSI0LjAsNC4wIiBzdHJva2Utd2lkdGg9IjEiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xNjQiPgogICAgICAgIDxyZWN0IHg9Ijc1MC42NTI1IiB5PSIxODQyLjQ0OCIgd2lkdGg9IjMyLjI2Mzc1MyIgaGVpZ2h0PSIyMiIgZmlsbD0iI2ZlYWUwMCIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzE2MyI+CiAgICAgICAgPHJlY3QgeD0iNzUwLjY1MjUiIHk9IjE4NjkuNDQ4IiB3aWR0aD0iNjguMjU1MDIiIGhlaWdodD0iMjIiIGZpbGw9IiNmZWFlMDAiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xNjIiPgogICAgICAgIDxyZWN0IHg9Ijc1MC42NTI1IiB5PSIxODk2LjQ0OCIgd2lkdGg9IjEwMC41NjIzNSIgaGVpZ2h0PSIyMiIgZmlsbD0iI2ZlYWUwMCIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzE2MSI+CiAgICAgICAgPHJlY3QgeD0iNzUwLjY1MjUiIHk9IjE5MjIuOTkwNCIgd2lkdGg9IjQ3Ljc2NzExNSIgaGVpZ2h0PSIyMiIgZmlsbD0iI2ZlYWUwMCIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzE2MCI+CiAgICAgICAgPHJlY3QgeD0iNzUwLjY1MjUiIHk9IjE5NTAuMjE5MiIgd2lkdGg9IjEwMC41NjIzNSIgaGVpZ2h0PSIyMiIgZmlsbD0iI2ZlYWUwMCIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzE1OSI+CiAgICAgICAgPHJlY3QgeD0iNzUwLjY1MjUiIHk9IjE5NzcuNDQ4IiB3aWR0aD0iNTguNjYxMzciIGhlaWdodD0iMjIiIGZpbGw9IiNmZWFlMDAiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xNTgiPgogICAgICAgIDxyZWN0IHg9Ijc1MC42NTI1IiB5PSIyMDAzLjk5MDQiIHdpZHRoPSI1OC42NjEzNyIgaGVpZ2h0PSIyMiIgZmlsbD0iI2ZlYWUwMCIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJMaW5lXzE1NyI+CiAgICAgICAgPHBhdGggZD0iTSA3NTAuNjUyNSAxODAxLjQ0OCBMIDc1MC43NzY5IDE4NDEuNDkxNSBMIDc1MC42NTI1IDE5MTEuMjM3MyBMIDc1MC43NzY5IDIwMzYuNzUiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLWRhc2hhcnJheT0iNC4wLDQuMCIgc3Ryb2tlLXdpZHRoPSIxIi8+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkxpbmVfMTU2Ij4KICAgICAgICA8cGF0aCBkPSJNIDE3My45NzA2NiAxODAxLjQ0OCBMIDE3NC4wOTUwNSAxODQxLjU3NyBMIDE3My45NzA2NiAxOTExLjQ3MTQgTCAxNzMuMDk1MDUgMjAzOC4yNSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2UtZGFzaGFycmF5PSI0LjAsNC4wIiBzdHJva2Utd2lkdGg9IjEiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iTGluZV8xNTUiPgogICAgICAgIDxwYXRoIGQ9Ik0gODUxLjIxNDkgMTgwMS40NDggTCA4NTEuMzM5MiAxODQxLjA3IEwgODUxLjIxNDkgMTkxMC4wODE3IEwgODUyLjIxNDkgMjAzNiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2UtZGFzaGFycmF5PSI0LjAsNC4wIiBzdHJva2Utd2lkdGg9IjEiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xNTQiPgogICAgICAgIDx0ZXh0IHRyYW5zZm9ybT0idHJhbnNsYXRlKDMwOS41OTYzIDE3ODcpIiBmaWxsPSJibGFjayI+CiAgICAgICAgICA8dHNwYW4gZm9udC1mYW1pbHk9IkhlbHZldGljYSBOZXVlIiBmb250LXNpemU9IjE2IiBmaWxsPSJibGFjayIgeD0iMzE5NzQ0MjNlLTIwIiB5PSIxNSI+MTwvdHNwYW4+CiAgICAgICAgPC90ZXh0PgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJMaW5lXzE1MyI+CiAgICAgICAgPGxpbmUgeDE9IjE3My45OTQ4OCIgeTE9IjE4MDkuMjY0IiB4Mj0iNDQ0LjExNzgiIHkyPSIxODA5LjE5MjUiIG1hcmtlci1lbmQ9InVybCgjRmlsbGVkQXJyb3dfTWFya2VyKSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjEiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iTGluZV8xNTIiPgogICAgICAgIDxsaW5lIHgxPSI0NTYuMDg4NjMiIHkxPSIxODA5LjQ0OCIgeDI9Ijc0MC43NzgxIiB5Mj0iMTgwOS42ODkyIiBtYXJrZXItZW5kPSJ1cmwoI0ZpbGxlZEFycm93X01hcmtlcikiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIxIi8+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkxpbmVfMTUxIj4KICAgICAgICA8bGluZSB4MT0iNzUwLjY3NjYiIHkxPSIxODA5LjIxNzUiIHgyPSI4NDEuMzM5MSIgeTI9IjE4MDkuMTg5MyIgbWFya2VyLWVuZD0idXJsKCNGaWxsZWRBcnJvd19NYXJrZXIpIiBzdHJva2U9ImJsYWNrIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMSIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzE1MCI+CiAgICAgICAgPHRleHQgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNjA5LjEwMTE1IDE3ODcpIiBmaWxsPSJibGFjayI+CiAgICAgICAgICA8dHNwYW4gZm9udC1mYW1pbHk9IkhlbHZldGljYSBOZXVlIiBmb250LXNpemU9IjE2IiBmaWxsPSJibGFjayIgeD0iMzE5NzQ0MjNlLTIwIiB5PSIxNSI+MjwvdHNwYW4+CiAgICAgICAgPC90ZXh0PgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzE0OSI+CiAgICAgICAgPHRleHQgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNzkzLjczODggMTc4NykiIGZpbGw9ImJsYWNrIj4KICAgICAgICAgIDx0c3BhbiBmb250LWZhbWlseT0iSGVsdmV0aWNhIE5ldWUiIGZvbnQtc2l6ZT0iMTYiIGZpbGw9ImJsYWNrIiB4PSI2LjY4Mzg3NyIgeT0iMTUiPjM8L3RzcGFuPgogICAgICAgIDwvdGV4dD4KICAgICAgPC9nPgogICAgPC9nPgogIDwvZz4KPC9zdmc+Cg==) Création d'un répertoire node\_modules non uniforme[​](https://pnpm.io/fr/motivation#cr%C3%A9ation-dun-r%C3%A9pertoire-node_modules-non-uniforme "Direct link to Création d'un répertoire node_modules non uniforme") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Lors de l'installation de dépendances avec npm ou Yarn, tous les packages sont hissés à la racine du dossier des modules. Par conséquent, le code source a accès aux dépendances qui ne sont pas ajoutées en tant que dépendances au projet. Par défaut, pnpm utilise des liens symboliques pour n'ajouter que les dépendances directes du projet à la racine du dossier des modules. ![An illustration of a node_modules directory created by pnpm. Packages in the root node_modules are symlinks to directories inside the node_modules/.pnpm directory](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgeG1sbnM6eGw9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjE1Ny40NTMxMiAxNjQgMjI0Ljc2NTYzIDMyMy4zNTkzOCIgd2lkdGg9IjIyNC43NjU2MyIgaGVpZ2h0PSIzMjMuMzU5MzgiPgogIDxkZWZzPgogICAgPG1hcmtlciBvcmllbnQ9ImF1dG8iIG92ZXJmbG93PSJ2aXNpYmxlIiBtYXJrZXJVbml0cz0ic3Ryb2tlV2lkdGgiIGlkPSJGaWxsZWRBcnJvd19NYXJrZXIiIHN0cm9rZS1saW5lam9pbj0ibWl0ZXIiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgdmlld0JveD0iLTEgLTQgMTAgOCIgbWFya2VyV2lkdGg9IjEwIiBtYXJrZXJIZWlnaHQ9IjgiIGNvbG9yPSIjN2Y4MDgwIj4KICAgICAgPGc+CiAgICAgICAgPHBhdGggZD0iTSA4IDAgTCAwIC0zIEwgMCAzIFoiIGZpbGw9ImN1cnJlbnRDb2xvciIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMSIvPgogICAgICA8L2c+CiAgICA8L21hcmtlcj4KICA8L2RlZnM+CiAgPGcgaWQ9IkNhbnZhc18xIiBzdHJva2UtZGFzaGFycmF5PSJub25lIiBmaWxsPSJub25lIiBzdHJva2Utb3BhY2l0eT0iMSIgZmlsbC1vcGFjaXR5PSIxIiBzdHJva2U9Im5vbmUiPgogICAgPHRpdGxlPkNhbnZhcyAxPC90aXRsZT4KICAgIDxyZWN0IGZpbGw9IndoaXRlIiB4PSIxNTcuNDUzMTIiIHk9IjE2NCIgd2lkdGg9IjIyNC43NjU2MyIgaGVpZ2h0PSIzMjMuMzU5MzgiLz4KICAgIDxnIGlkPSJDYW52YXNfMV9MYXllcl8xIj4KICAgICAgPHRpdGxlPkxheWVyIDE8L3RpdGxlPgogICAgICA8ZyBpZD0iR3JhcGhpY18yIj4KICAgICAgICA8dGV4dCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNjcuNDUzMTIgMTc0KSIgZmlsbD0iYmxhY2siPgogICAgICAgICAgPHRzcGFuIGZvbnQtZmFtaWx5PSJNb25hY28iIGZvbnQtc2l6ZT0iMTYiIGZpbGw9ImJsYWNrIiB4PSIwIiB5PSIxNiI+bm9kZV9tb2R1bGVzPC90c3Bhbj4KICAgICAgICA8L3RleHQ+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfMyI+CiAgICAgICAgPHRleHQgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTk3IDIwNS4zMzU5NCkiIGZpbGw9IiMwMDk2ZmYiPgogICAgICAgICAgPHRzcGFuIGZvbnQtZmFtaWx5PSJNb25hY28iIGZvbnQtc2l6ZT0iMTYiIGZpbGw9IiMwMDk2ZmYiIHg9IjAiIHk9IjE2Ij5leHByZXNzPC90c3Bhbj4KICAgICAgICA8L3RleHQ+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfNCI+CiAgICAgICAgPHRleHQgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTk3IDIzNi42NzE4OCkiIGZpbGw9ImJsYWNrIj4KICAgICAgICAgIDx0c3BhbiBmb250LWZhbWlseT0iTW9uYWNvIiBmb250LXNpemU9IjE2IiBmaWxsPSJibGFjayIgeD0iMCIgeT0iMTYiPi5wbnBtPC90c3Bhbj4KICAgICAgICA8L3RleHQ+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfNSI+CiAgICAgICAgPHRleHQgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMjI3IDI2OC4wMDc4KSIgZmlsbD0iYmxhY2siPgogICAgICAgICAgPHRzcGFuIGZvbnQtZmFtaWx5PSJNb25hY28iIGZvbnQtc2l6ZT0iMTYiIGZpbGw9ImJsYWNrIiB4PSIwIiB5PSIxNiI+ZXhwcmVzc0A0LjE3LjM8L3RzcGFuPgogICAgICAgIDwvdGV4dD4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY182Ij4KICAgICAgICA8dGV4dCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyNTcgMjk5LjM0Mzc1KSIgZmlsbD0iYmxhY2siPgogICAgICAgICAgPHRzcGFuIGZvbnQtZmFtaWx5PSJNb25hY28iIGZvbnQtc2l6ZT0iMTYiIGZpbGw9ImJsYWNrIiB4PSIwIiB5PSIxNiI+bm9kZV9tb2R1bGVzPC90c3Bhbj4KICAgICAgICA8L3RleHQ+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfNyI+CiAgICAgICAgPHRleHQgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMjg3IDMzMC42Nzk3KSIgZmlsbD0iYmxhY2siPgogICAgICAgICAgPHRzcGFuIGZvbnQtZmFtaWx5PSJNb25hY28iIGZvbnQtc2l6ZT0iMTYiIGZpbGw9ImJsYWNrIiB4PSIwIiB5PSIxNiI+ZXhwcmVzczwvdHNwYW4+CiAgICAgICAgPC90ZXh0PgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzgiPgogICAgICAgIDx0ZXh0IHRyYW5zZm9ybT0idHJhbnNsYXRlKDI4NyAzNjIuMDE1NjIpIiBmaWxsPSIjMDA5NmZmIj4KICAgICAgICAgIDx0c3BhbiBmb250LWZhbWlseT0iTW9uYWNvIiBmb250LXNpemU9IjE2IiBmaWxsPSIjMDA5NmZmIiB4PSIwIiB5PSIxNiI+Y29va2llPC90c3Bhbj4KICAgICAgICA8L3RleHQ+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfOSI+CiAgICAgICAgPHRleHQgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMjI3IDM5My4zNTE1NikiIGZpbGw9ImJsYWNrIj4KICAgICAgICAgIDx0c3BhbiBmb250LWZhbWlseT0iTW9uYWNvIiBmb250LXNpemU9IjE2IiBmaWxsPSJibGFjayIgeD0iMCIgeT0iMTYiPmNvb2tpZUAwLjQuMjwvdHNwYW4+CiAgICAgICAgPC90ZXh0PgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzEwIj4KICAgICAgICA8dGV4dCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyNTcgNDI0LjY4NzUpIiBmaWxsPSJibGFjayI+CiAgICAgICAgICA8dHNwYW4gZm9udC1mYW1pbHk9Ik1vbmFjbyIgZm9udC1zaXplPSIxNiIgZmlsbD0iYmxhY2siIHg9IjAiIHk9IjE2Ij5ub2RlX21vZHVsZXM8L3RzcGFuPgogICAgICAgIDwvdGV4dD4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xMSI+CiAgICAgICAgPHRleHQgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMjg3IDQ1Ni4wMjM0NCkiIGZpbGw9ImJsYWNrIj4KICAgICAgICAgIDx0c3BhbiBmb250LWZhbWlseT0iTW9uYWNvIiBmb250LXNpemU9IjE2IiBmaWxsPSJibGFjayIgeD0iMCIgeT0iMTYiPmNvb2tpZTwvdHNwYW4+CiAgICAgICAgPC90ZXh0PgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJMaW5lXzIwIj4KICAgICAgICA8cGF0aCBkPSJNIDE5MiAyMTYuMDAzOSBMIDE4MiAyMTYuMDAzOSBMIDE4MC43NSAyMTYuMTI1IEwgMTc5LjUgMjE2LjEyNSBMIDE3OS41IDM0MS4zNDc2NiBMIDI3Mi4xIDM0MS4zNDc2NiIgbWFya2VyLWVuZD0idXJsKCNGaWxsZWRBcnJvd19NYXJrZXIpIiBzdHJva2U9IiM3ZjgwODAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIxIi8+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkxpbmVfMjEiPgogICAgICAgIDxwYXRoIGQ9Ik0gMjgyIDM3Mi42ODM2IEwgMjcyIDM3Mi42ODM2IEwgMjE3LjUgMzczIEwgMjE4IDQ1Ny41IEwgMjE4IDQ2Ni42OTE0IEwgMjcyLjEgNDY2LjY5MTQiIG1hcmtlci1lbmQ9InVybCgjRmlsbGVkQXJyb3dfTWFya2VyKSIgc3Ryb2tlPSIjN2Y4MDgwIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMSIvPgogICAgICA8L2c+CiAgICA8L2c+CiAgPC9nPgo8L3N2Zz4K) If you'd like more details about the unique `node_modules` structure that pnpm creates and why it works fine with the Node.js ecosystem, read: * [Flat node\_modules is not the only way](https://pnpm.io/fr/blog/2020/05/27/flat-node-modules-is-not-the-only-way) * [Symlinked node\_modules structure](https://pnpm.io/fr/symlinked-node-modules-structure) astuce If your tooling doesn't work well with symlinks, you may still use pnpm and set the [nodeLinker](https://pnpm.io/fr/settings#nodeLinker) setting to `hoisted`. Cela indiquera à pnpm de créer un répertoire node\_modules similaire à ceux créés par npm et Yarn Classic. * [Saving disk space](https://pnpm.io/fr/motivation#saving-disk-space) * [Boosting installation speed](https://pnpm.io/fr/motivation#boosting-installation-speed) * [Création d'un répertoire node\_modules non uniforme](https://pnpm.io/fr/motivation#cr%C3%A9ation-dun-r%C3%A9pertoire-node_modules-non-uniforme) --- # The year 2021 for pnpm | pnpm [Skip to main content](https://pnpm.io/blog/2021/12/29/yearly-update#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** It is the end of the year and it was a good year for pnpm, so let's see how it went. Usage[​](https://pnpm.io/blog/2021/12/29/yearly-update#usage "Direct link to Usage") ------------------------------------------------------------------------------------- ### Download Stats[​](https://pnpm.io/blog/2021/12/29/yearly-update#download-stats "Direct link to Download Stats") My goal this year was to beat Bower by the number of downloads. We were able to achieve this goal [in November](https://npm-stat.com/charts.html?package=pnpm&package=bower&from=2021-01-01&to=2021-12-29) : ![](https://pnpm.io/assets/images/pnpm-vs-bower-stats-6ec69a7308f5fbc1433420b1b2f7457f.png) pnpm was downloaded about [3 times more](https://npm-stat.com/charts.html?package=pnpm&from=2016-12-01&to=2021-12-29) in 2021 than in 2020: ![](https://pnpm.io/assets/images/download-stats-2021-1418562cb03abd558c4a6b4b17155227.png) note These stats don't even measure all the different ways that pnpm may be installed! They only measure the downloads of the [pnpm npm package](https://www.npmjs.com/package/pnpm) . This year we also added compiled binary versions of pnpm, which are shipped differently. ### Docs visits[​](https://pnpm.io/blog/2021/12/29/yearly-update#docs-visits "Direct link to Docs visits") We collect some unpersonalized stats from our docs using Google Analytics. In 2021, sometimes we had more than 2,000 unique visitors a week. ![](https://pnpm.io/assets/images/ga-unique-visits-2021-b8bc3649f680565127696c85bdd4b701.png) Most of our users are from the United States and China. ![](https://pnpm.io/assets/images/countries-2021-8eb9625e1798649ee04451dfb10ac851.png) ### GitHub stars[​](https://pnpm.io/blog/2021/12/29/yearly-update#github-stars "Direct link to GitHub stars") Our [main GitHub repository](https://github.com/pnpm/pnpm) received +5,000 stars this year. ![](https://pnpm.io/assets/images/stars-2021-0061c16f424e33ba0db224d82bcb53f3.png) ### New users[​](https://pnpm.io/blog/2021/12/29/yearly-update#new-users "Direct link to New users") Our biggest new user this year is [Bytedance](https://github.com/pnpm/pnpm.io/pull/89) (the company behind TikTok). Also, many great open-source projects started to use pnpm. Some switched to pnpm because of its great support of monorepos: * [Vue](https://github.com/vuejs/vue-next) * [Vite](https://github.com/vitejs/vite) * and [others](https://pnpm.io/workspaces#usage-examples) Some switched because they like how efficient, fast, and beautiful pnpm is: * [Autoprefixer](https://twitter.com/Autoprefixer/status/1476226146488692736) * [PostCSS](https://twitter.com/PostCSS/status/1470438664006258701) * [Browserslist](https://twitter.com/Browserslist/status/1468264308308156419) Feature Highlights[​](https://pnpm.io/blog/2021/12/29/yearly-update#feature-highlights "Direct link to Feature Highlights") ---------------------------------------------------------------------------------------------------------------------------- ### New lockfile format (since [v6.0.0](https://github.com/pnpm/pnpm/releases/tag/v6.0.0) )[​](https://pnpm.io/blog/2021/12/29/yearly-update#new-lockfile-format-since-v600 "Direct link to new-lockfile-format-since-v600") One of the first and most important changes this year was the new `pnpm-lock.yaml` format. This was a breaking change, so we had to release v6. But it was a success. The old lockfile was causing Git conflicts frequently. Since the new format was introduced, we did not receive any complaints about Git conflicts. ### Managing Node.js versions (since [v6.12.0](https://github.com/pnpm/pnpm/releases/tag/v6.12.0) )[​](https://pnpm.io/blog/2021/12/29/yearly-update#managing-nodejs-versions-since-v6120 "Direct link to managing-nodejs-versions-since-v6120") We shipped a new command (`pnpm env`) that allows to manage Node.js versions. So you may use pnpm instead of Node.js version managers like nvm or Volta. Also, pnpm is shipped as a standalone executable, so you can run it even with no Node.js preinstalled on the system. ### Injecting local dependencies (since [v6.20.0](https://github.com/pnpm/pnpm/releases/tag/v6.20.0) )[​](https://pnpm.io/blog/2021/12/29/yearly-update#injecting-local-dependencies-since-v6200 "Direct link to injecting-local-dependencies-since-v6200") You may "inject" a local dependency. By default, local dependencies are symlinked to `node_modules` but with this new feature you may instruct pnpm to hard link the files of the package instead. ### Improved reporting of peer dependency issues (since [v6.24.0](https://github.com/pnpm/pnpm/releases/tag/v6.24.0) )[​](https://pnpm.io/blog/2021/12/29/yearly-update#improved-reporting-of-peer-dependency-issues-since-v6240 "Direct link to improved-reporting-of-peer-dependency-issues-since-v6240") Peer dependency issues used to be printed as plain text and it was hard to understand them. They are now all grouped and printed in a nice hierarchy structure. The Competition[​](https://pnpm.io/blog/2021/12/29/yearly-update#the-competition "Direct link to The Competition") ------------------------------------------------------------------------------------------------------------------- ### Yarn[​](https://pnpm.io/blog/2021/12/29/yearly-update#yarn "Direct link to Yarn") Yarn added a pnpm linker in [v3.1](https://dev.to/arcanis/yarn-31-corepack-esm-pnpm-optional-packages--3hak#new-install-mode-raw-pnpm-endraw-) . So Yarn can create a similar node-modules directory structure to the one that pnpm creates. Also, the Yarn team plans to implement a content-addressable storage to be more disk space efficient. ### npm[​](https://pnpm.io/blog/2021/12/29/yearly-update#npm "Direct link to npm") The npm team decided to also adopt the symlinked node-modules directory structure that pnpm uses (related [RFC](https://github.com/npm/rfcs/blob/main/accepted/0042-isolated-mode.md) ). ### Others[​](https://pnpm.io/blog/2021/12/29/yearly-update#others "Direct link to Others") [Bun](https://twitter.com/jarredsumner/status/1473416431291174912/photo/1) written in Zig and [Volt](https://github.com/voltpkg/volt) written in Rust both claim to be faster than npm/Yarn/pnpm. I did not benchmark these new package managers yet. Future Plans[​](https://pnpm.io/blog/2021/12/29/yearly-update#future-plans "Direct link to Future Plans") ---------------------------------------------------------------------------------------------------------- Faster, better, best. * [Usage](https://pnpm.io/blog/2021/12/29/yearly-update#usage) * [Download Stats](https://pnpm.io/blog/2021/12/29/yearly-update#download-stats) * [Docs visits](https://pnpm.io/blog/2021/12/29/yearly-update#docs-visits) * [GitHub stars](https://pnpm.io/blog/2021/12/29/yearly-update#github-stars) * [New users](https://pnpm.io/blog/2021/12/29/yearly-update#new-users) * [Feature Highlights](https://pnpm.io/blog/2021/12/29/yearly-update#feature-highlights) * [New lockfile format (since v6.0.0)](https://pnpm.io/blog/2021/12/29/yearly-update#new-lockfile-format-since-v600) * [Managing Node.js versions (since v6.12.0)](https://pnpm.io/blog/2021/12/29/yearly-update#managing-nodejs-versions-since-v6120) * [Injecting local dependencies (since v6.20.0)](https://pnpm.io/blog/2021/12/29/yearly-update#injecting-local-dependencies-since-v6200) * [Improved reporting of peer dependency issues (since v6.24.0)](https://pnpm.io/blog/2021/12/29/yearly-update#improved-reporting-of-peer-dependency-issues-since-v6240) * [The Competition](https://pnpm.io/blog/2021/12/29/yearly-update#the-competition) * [Yarn](https://pnpm.io/blog/2021/12/29/yearly-update#yarn) * [npm](https://pnpm.io/blog/2021/12/29/yearly-update#npm) * [Others](https://pnpm.io/blog/2021/12/29/yearly-update#others) * [Future Plans](https://pnpm.io/blog/2021/12/29/yearly-update#future-plans) --- # Flat node_modules is not the only way | pnpm [Skip to main content](https://pnpm.io/blog/2020/05/27/flat-node-modules-is-not-the-only-way#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** New users of pnpm frequently ask me about the weird structure of `node_modules` that pnpm creates. Why is it not flat? Where are all the sub-dependencies? > I am going to assume that readers of the article are already familiar with flat `node_modules` created by npm and Yarn. If you don't understand why npm 3 had to start using flat `node_modules` in v3, you can find some prehistory in [Why should we use pnpm?](https://www.kochan.io/nodejs/why-should-we-use-pnpm.html) > . So why is pnpm's `node_modules` unusual? Let's create two directories and run `npm add express` in one of them and `pnpm add express` in the other one. Here's the top of what you get in the first directory's `node_modules`: .binacceptsarray-flattenbody-parserbytescontent-dispositioncookie-signaturecookiedebugdepddestroyee-firstencodeurlescape-htmletagexpress You can see the whole directory [here](https://github.com/zkochan/comparing-node-modules/tree/master/npm-example/node_modules) . And this is what you get in the `node_modules` created by pnpm: .pnpm.modules.yamlexpress You can check it [here](https://github.com/zkochan/comparing-node-modules/tree/master/pnpm5-example/node_modules) . So where are all the dependencies? There is only one folder in the `node_modules` called `.pnpm` and a symlink called `express`. Well, we installed only `express`, so that is the only package that your application has to have access to > Read more about why pnpm's strictness is a good thing [here](https://medium.com/pnpm/pnpms-strictness-helps-to-avoid-silly-bugs-9a15fb306308) Let's see what is inside `express`: ▾ node_modules ▸ .pnpm ▾ express ▸ lib History.md index.js LICENSE package.json Readme.md .modules.yaml `express` has no `node_modules`? Where are all the dependencies of `express`? The trick is that `express` is just a symlink. When Node.js resolves dependencies, it uses their real locations, so it does not preserve symlinks. But where is the real location of `express`, you might ask? Here: [node\_modules/.pnpm/express@4.17.1/node\_modules/express](https://github.com/zkochan/comparing-node-modules/tree/master/pnpm5-example/node_modules/.pnpm/express@4.17.1/node_modules/express) . OK, so now we know the purpose of the `.pnpm/` folder. `.pnpm/` stores all the packages in a flat folder structure, so every package can be found in a folder named by this pattern: .pnpm/@/node_modules/ We call it the virtual store directory. This flat structure avoids the long path issues that were caused by the nested `node_modules` created by npm v2 but keeps packages isolated unlike the flat `node_modules` created by npm v3,4,5,6 or Yarn v1. Now let's look into the real location of `express`: ▾ express ▸ lib History.md index.js LICENSE package.json Readme.md Is it a scam? It still lacks `node_modules`! The second trick of pnpm's `node_modules` structure is that the dependencies of packages are on the same directory level as the real location of the dependent package. So dependencies of `express` are not in `.pnpm/express@4.17.1/node_modules/express/node_modules/` but in [.pnpm/express@4.17.1/node\_modules/](https://github.com/zkochan/comparing-node-modules/tree/master/pnpm5-example/node_modules/.pnpm/express@4.17.1/node_modules) : ▾ node_modules ▾ .pnpm ▸ accepts@1.3.5 ▸ array-flatten@1.1.1 ... ▾ express@4.16.3 ▾ node_modules ▸ accepts ▸ array-flatten ▸ body-parser ▸ content-disposition ... ▸ etag ▾ express ▸ lib History.md index.js LICENSE package.json Readme.md All the dependencies of `express` are symlinks to appropriate directories in `node_modules/.pnpm/`. Placing dependencies of `express` one level up allows avoiding circular symlinks. So as you can see, even though pnpm's `node_modules` structure seems unusual at first: 1. it is completely Node.js compatible 2. packages are nicely grouped with their dependencies The structure is a little bit [more complex](https://pnpm.io/how-peers-are-resolved) for packages with peer dependencies but the idea is the same: using symlinks to create a nesting with a flat directory structure. --- # Node-Modules configuration options with pnpm | pnpm [Skip to main content](https://pnpm.io/blog/2020/10/17/node-modules-configuration-options-with-pnpm#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** There are many ways to create a node\_modules directory. Your goal must be to create the most strict one but if that is not possible, there are options to make a loose node\_modules as well. The default setup[​](https://pnpm.io/blog/2020/10/17/node-modules-configuration-options-with-pnpm#the-default-setup "Direct link to The default setup") -------------------------------------------------------------------------------------------------------------------------------------------------------- By default, pnpm v5 will create a semi-strict node\_modules. Semi-strict means that your application will only be able to require packages that are added as dependencies to `package.json` (with a few exceptions). However, your dependencies will be able to access any packages. The default configuration looks like this: ; All packages are hoisted to node_modules/.pnpm/node_moduleshoist-pattern[]=*; All types are hoisted to the root in order to make TypeScript happypublic-hoist-pattern[]=*types*; All ESLint-related packages are hoisted to the root as wellpublic-hoist-pattern[]=*eslint* Plug'n'Play. The strictest configuration[​](https://pnpm.io/blog/2020/10/17/node-modules-configuration-options-with-pnpm#plugnplay-the-strictest-configuration "Direct link to Plug'n'Play. The strictest configuration") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- pnpm supports [Yarn's Plug'n'Play](https://yarnpkg.com/features/pnp) since v5.9. With PnP, both your application and the dependencies of your application will have access only to their declared dependencies. This is even stricter then setting `hoist=false` because inside a monorepo, your application will not be able to access even the dependencies of the root project. To use Plug'n'Play, set these settings: node-linker=pnpsymlink=false A strict, traditional modules directory[​](https://pnpm.io/blog/2020/10/17/node-modules-configuration-options-with-pnpm#a-strict-traditional-modules-directory "Direct link to A strict, traditional modules directory") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- If you are not ready to use PnP yet, you can still be strict and only allow packages to access their own dependencies by setting the hoist configuration to false: hoist=false However, if some of your dependencies are trying to access packages that they don't have in dependencies, you have two options: 1. Create a `pnpmfile.js` and use a [hook](https://pnpm.io/pnpmfile) to add the missing dependency to the package's manifest. 2. Add a pattern to the `hoist-pattern` setting. For instance, if the not found module is `babel-core`, add the following setting to `.npmrc`: hoist-pattern[]=babel-core The worst case - hoisting to the root[​](https://pnpm.io/blog/2020/10/17/node-modules-configuration-options-with-pnpm#the-worst-case---hoisting-to-the-root "Direct link to The worst case - hoisting to the root") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Some tools might not work even with the default configuration of pnpm, which hoists everything to the root of the virtual store and some packages to the root. In this case, you can hoist either everything or a subset of dependencies to the root of the modules directory. Hoisting everything to the root of node\_modules: shamefully-hoist=true Hoisting only packages that match a pattern: public-hoist-pattern[]=babel-* * [The default setup](https://pnpm.io/blog/2020/10/17/node-modules-configuration-options-with-pnpm#the-default-setup) * [Plug'n'Play. The strictest configuration](https://pnpm.io/blog/2020/10/17/node-modules-configuration-options-with-pnpm#plugnplay-the-strictest-configuration) * [A strict, traditional modules directory](https://pnpm.io/blog/2020/10/17/node-modules-configuration-options-with-pnpm#a-strict-traditional-modules-directory) * [The worst case - hoisting to the root](https://pnpm.io/blog/2020/10/17/node-modules-configuration-options-with-pnpm#the-worst-case---hoisting-to-the-root) --- # Blog | pnpm [Skip to main content](https://pnpm.io/blog#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** pnpm 10.25 improves certificate handling, adds a bare `pnpm init`, and ships several quality-of-life fixes. We got lucky with Shai-Hulud 2.0. In November 2025, a self-replicating npm worm [compromised 796 packages](https://securitylabs.datadoghq.com/articles/shai-hulud-2.0-npm-worm/) with 132 million monthly downloads. The attack used preinstall scripts to steal credentials, install persistent backdoors, and in some cases wipe entire developer environments. We weren't affected—not because we had robust defenses, but because we didn't run `npm install` or `npm update` during the attack window. Luck isn't a security strategy. pnpm now scales network concurrency automatically on high-core machines and ships several reliability fixes. Added `--lockfile-only` option to `pnpm list` and various improvements to `pnpm self-update`. Added support for excluding packages from trust policy and overriding the `engines` field on publish. Added support for Node.js runtime installation for dependencies and a setting for configuring trust policy. This release adds a `--all` flag for the `pnpm help` command to print all commands. This release adds version-scoped controls to two settings: \[`onlyBuiltDependencies`\] and \[`minimumReleaseAgeExclude`\]. ### Minor Changes[​](https://pnpm.io/blog#minor-changes "Direct link to Minor Changes") Added network performance monitoring to pnpm by implementing warnings for slow network requests, including both metadata fetches and tarball downloads. Added configuration options for warning thresholds: `fetchWarnTimeoutMs` and `fetchMinSpeedKiBps`. Warning messages are displayed when requests exceed time thresholds or fall below speed minimums Related PR: [#10025](https://github.com/pnpm/pnpm/pull/10025) . ### Patch Changes[​](https://pnpm.io/blog#patch-changes "Direct link to Patch Changes") * Retry filesystem operations on EAGAIN errors [#9959](https://github.com/pnpm/pnpm/pull/9959) . * Outdated command respects `minimumReleaseAge` configuration [#10030](https://github.com/pnpm/pnpm/pull/10030) . * Correctly apply the `cleanupUnusedCatalogs` configuration when removing dependent packages. * Don't fail with a meaningless error when `scriptShell` is set to `false` [#8748](https://github.com/pnpm/pnpm/issues/8748) . * `pnpm dlx` should not fail when `minimumReleaseAge` is set [#10037](https://github.com/pnpm/pnpm/issues/10037) . ### Minor Changes[​](https://pnpm.io/blog#minor-changes "Direct link to Minor Changes") The `minimumReleaseAgeExclude` setting now supports patterns. --- # The year 2022 for pnpm | pnpm [Skip to main content](https://pnpm.io/blog/2022/12/30/yearly-update#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** It is the end of the year. A really hard year. As you may know, I live in Ukraine, so due to Russia's war against us, it was harder to lead this project than in previous years. Nevertheless, it was a good year for pnpm. We've got a lot of new users, contributors, and we have implemented many great features. ![](https://pnpm.io/assets/images/2022-review-092f8f0dfe82b760c2e90fd776d82f75.png) (the above illustration was generated by Midjourney. The tiger symolizes the year of the tiger) Usage[​](https://pnpm.io/blog/2022/12/30/yearly-update#usage "Direct link to Usage") ------------------------------------------------------------------------------------- ### Download Stats[​](https://pnpm.io/blog/2022/12/30/yearly-update#download-stats "Direct link to Download Stats") My goal this year was to beat Lerna by the number of downloads. We were able to achieve this goal [in August](https://npm-stat.com/charts.html?package=pnpm&package=lerna&from=2022-01-01&to=2022-12-30) : ![](https://pnpm.io/assets/images/pnpm-vs-lerna-stats-cad28f3b9685ef684c864f919f7f9c5e.png) pnpm was downloaded more than [5 times more](https://npm-stat.com/charts.html?package=pnpm&from=2016-12-01&to=2022-12-30) in 2022 than in 2021: ![](https://pnpm.io/assets/images/download-stats-2022-e4de79bf61e1066802166f9d97cb36ac.png) ### Docs visits[​](https://pnpm.io/blog/2022/12/30/yearly-update#docs-visits "Direct link to Docs visits") We collect some unpersonalized stats from our docs using Google Analytics. In 2022, sometimes we had more than 20,000 unique visitors a week. This is 10 times more than in 2021! ![](https://pnpm.io/assets/images/ga-unique-visits-2022-b2e9bf0b6c559a5c59fdbfd8bb1861f0.png) ### GitHub stars[​](https://pnpm.io/blog/2022/12/30/yearly-update#github-stars "Direct link to GitHub stars") Our [main GitHub repository](https://github.com/pnpm/pnpm) received almost +7,000 stars this year. ![](https://pnpm.io/assets/images/stars-2022-434ca95e6da688fdff1bb1bf89d6a2d9.png) ### Our contributors[​](https://pnpm.io/blog/2022/12/30/yearly-update#our-contributors "Direct link to Our contributors") We had a lot of new and active contributors this year. These are the people the merge at least one PR in 2022: * [Zoltan Kochan](https://github.com/zkochan) * [chlorine](https://github.com/lvqq) * [await-ovo](https://github.com/await-ovo) * [Brandon Cheng](https://github.com/gluxon) * [Dominic Elm](https://github.com/d3lm) * [MCMXC](https://github.com/mcmxcdev) * [那里好脏不可以](https://github.com/dev-itsheng) * [Homyee King](https://github.com/HomyeeKing) * [Shinobu Hayashi](https://github.com/Shinyaigeek) * [Black-Hole](https://github.com/BlackHole1) * [Kenrick](https://github.com/kenrick95) * [Weyert de Boer](https://github.com/weyert) * [Glen Whitney](https://github.com/gwhitney) * [Cheng](https://github.com/chengcyber) * [zoomdong](https://github.com/fireairforce) * [thinkhalo](https://github.com/ufec) * [子瞻 Luci](https://github.com/LuciNyan) * [spencer17x](https://github.com/Spencer17x) * [liuxingbaoyu](https://github.com/liuxingbaoyu) * [장지훈](https://github.com/WhiteKiwi) * [Jon de la Motte](https://github.com/jondlm) * [Jack Works](https://github.com/Jack-Works) * [milahu](https://github.com/milahu) * [David Collins](https://github.com/David-Collins) * [nikoladev](https://github.com/nikoladev) * [Igor Bezkrovnyi](https://github.com/ibezkrovnyi) * [Lev Chelyadinov](https://github.com/illright) * [javier-garcia-meteologica](https://github.com/javier-garcia-meteologica) Feature Highlights[​](https://pnpm.io/blog/2022/12/30/yearly-update#feature-highlights "Direct link to Feature Highlights") ---------------------------------------------------------------------------------------------------------------------------- ### Supporting a symlinkless hoisted `node_modules` (since [v6.25.0](https://github.com/pnpm/pnpm/releases/tag/v6.25.0) )[​](https://pnpm.io/blog/2022/12/30/yearly-update#supporting-a-symlinkless-hoisted-node_modules-since-v6250 "Direct link to supporting-a-symlinkless-hoisted-node_modules-since-v6250") Right at the beginning of 2022, we have added support for the "traditional" hoisted (a.k.a flat `node_modules`). We use Yarn's hoisting algorithm to create a proper hoisted `node_modules`. This new setting has basically made pnpm compatible with all Node.js stack that are compatible with npm CLI. To use the hoisted `node_modules` directory structure, use the `node-linker=hoisted` setting in an `.npmrc` file. ### Side effects cache (since [v7.0.0](https://github.com/pnpm/pnpm/releases/tag/v7.0.0) )[​](https://pnpm.io/blog/2022/12/30/yearly-update#side-effects-cache-since-v700 "Direct link to side-effects-cache-since-v700") Since v7, [side-effect-cache](https://pnpm.io/npmrc#side-effects-cache) is enabled by default, so dependencies that should be built are only built once on a machine. This improves installation speed by a lot in projects that have dependencies with build scripts. ### Dependencies patching (since [v7.4.0](https://github.com/pnpm/pnpm/releases/tag/v7.4.0) )[​](https://pnpm.io/blog/2022/12/30/yearly-update#dependencies-patching-since-v740 "Direct link to dependencies-patching-since-v740") The [`pnpm patch`](https://pnpm.io/cli/patch) command have been added for patching dependencies in your `node_modules`. ### Time-based resolution strategy (since [v7.10.0](https://github.com/pnpm/pnpm/releases/tag/v7.10.0) )[​](https://pnpm.io/blog/2022/12/30/yearly-update#time-based-resolution-strategy-since-v7100 "Direct link to time-based-resolution-strategy-since-v7100") A new resolution mode was added to pnpm, which should make updating dependencies more secure. You can change the resolution mode with the [resolution-mode](https://pnpm.io/npmrc#resolution-mode) setting. ### Listing licenses of dependencies (since [v7.17.0](https://github.com/pnpm/pnpm/releases/tag/v7.17.0) )[​](https://pnpm.io/blog/2022/12/30/yearly-update#listing-licenses-of-dependencies-since-v7170 "Direct link to listing-licenses-of-dependencies-since-v7170") You may now use the [`pnpm licenses list`](https://pnpm.io/cli/licenses) command to check the licenses of the installed packages. * [Usage](https://pnpm.io/blog/2022/12/30/yearly-update#usage) * [Download Stats](https://pnpm.io/blog/2022/12/30/yearly-update#download-stats) * [Docs visits](https://pnpm.io/blog/2022/12/30/yearly-update#docs-visits) * [GitHub stars](https://pnpm.io/blog/2022/12/30/yearly-update#github-stars) * [Our contributors](https://pnpm.io/blog/2022/12/30/yearly-update#our-contributors) * [Feature Highlights](https://pnpm.io/blog/2022/12/30/yearly-update#feature-highlights) * [Supporting a symlinkless hoisted `node_modules` (since v6.25.0)](https://pnpm.io/blog/2022/12/30/yearly-update#supporting-a-symlinkless-hoisted-node_modules-since-v6250) * [Side effects cache (since v7.0.0)](https://pnpm.io/blog/2022/12/30/yearly-update#side-effects-cache-since-v700) * [Dependencies patching (since v7.4.0)](https://pnpm.io/blog/2022/12/30/yearly-update#dependencies-patching-since-v740) * [Time-based resolution strategy (since v7.10.0)](https://pnpm.io/blog/2022/12/30/yearly-update#time-based-resolution-strategy-since-v7100) * [Listing licenses of dependencies (since v7.17.0)](https://pnpm.io/blog/2022/12/30/yearly-update#listing-licenses-of-dependencies-since-v7170) --- # How We're Protecting Our Newsroom from npm Supply Chain Attacks | pnpm [Skip to main content](https://pnpm.io/blog/2025/12/05/newsroom-npm-supply-chain-security#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** We got lucky with Shai-Hulud 2.0. In November 2025, a self-replicating npm worm [compromised 796 packages](https://securitylabs.datadoghq.com/articles/shai-hulud-2.0-npm-worm/) with 132 million monthly downloads. The attack used preinstall scripts to steal credentials, install persistent backdoors, and in some cases wipe entire developer environments. We weren't affected—not because we had robust defenses, but because we didn't run `npm install` or `npm update` during the attack window. Luck isn't a security strategy. Who We Are[​](https://pnpm.io/blog/2025/12/05/newsroom-npm-supply-chain-security#who-we-are "Direct link to Who We Are") ------------------------------------------------------------------------------------------------------------------------- I'm Ryan Sobol, Principal Software Engineer at the Seattle Times. We've been using npm as our default package manager for years, with some brief experimentation with Yarn that never gained traction. Now we're piloting pnpm specifically for its client-side security controls that complement the registry-level improvements npm has been rolling out. Trust is paramount for news organizations, especially these days. A supply chain compromise could expose customer data, employee credentials, production infrastructure, and source code—all things that could take weeks to recover from and potentially require breach notifications to our readers. We understand how expensive these incidents can be in both time and money. That's a path we don't want to go down. Despite the organizational inertia that comes with sticking to npm, we think pnpm has a real chance here. It's a true drop-in replacement—same commands, same workflows, same registry. That makes the transition achievable in a way previous alternatives weren't. This isn't a polished case study. It's a real-world data point from a team that's just starting to figure out supply chain security. The challenges we're encountering and how we're thinking about these controls might be useful as you consider implementing them yourself. Why Client-Side Controls Matter[​](https://pnpm.io/blog/2025/12/05/newsroom-npm-supply-chain-security#why-client-side-controls-matter "Direct link to Why Client-Side Controls Matter") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- npm has made tremendous progress on supply chain security. [Trusted publishing](https://docs.npmjs.com/trusted-publishers/) , [provenance attestations](https://docs.npmjs.com/generating-provenance-statements/) , and [granular access tokens](https://docs.npmjs.com/about-access-tokens/) are all significant improvements that make it substantially harder to publish malicious packages after compromising maintainer accounts. But here's the gap: these registry improvements protect the _**publishing**_ side. They don't prevent _**consuming**_ malicious packages. When you run `npm install` or `npm update`, lifecycle scripts (e.g., preinstall and postinstall) execute arbitrary code from the internet with full developer privileges—before the package has been evaluated for safety. These scripts can access your credentials (npm, GitHub, AWS, databases), your source code, your cloud infrastructure, and your entire filesystem. This is the fundamental vulnerability that attacks like Shai-Hulud exploit. Even with these registry improvements, if a legitimate maintainer's account is compromised, attackers can publish a version with malicious lifecycle scripts that execute immediately upon installation—before the community detects the compromise. That's why we felt we needed defense on both sides: npm's improvements make it harder to _**publish**_ malicious packages; pnpm's client-side controls make it harder to _**consume**_ them. These approaches are complementary, not competitive. pnpm uses npm's registry and benefits from all of npm's security improvements while adding an additional layer of protection on the client side. This is defense-in-depth. The Three Layers We're Using[​](https://pnpm.io/blog/2025/12/05/newsroom-npm-supply-chain-security#the-three-layers-were-using "Direct link to The Three Layers We're Using") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ For our pilot, we're using three pnpm security controls that work together. Each control addresses a different attack vector, and each has escape hatches for legitimate exceptions. We knew going in that we'd need those exceptions—the real world is messy. ### Control 1: Lifecycle Script Management[​](https://pnpm.io/blog/2025/12/05/newsroom-npm-supply-chain-security#control-1-lifecycle-script-management "Direct link to Control 1: Lifecycle Script Management") One of the main reasons we considered pnpm was learning that it **blocks lifecycle scripts by default**. Unlike other package managers, it doesn't implicitly trust and execute arbitrary code from packages. In practice, when a package has preinstall or postinstall scripts, pnpm blocks them but installation continues with a warning. This already provides significant protection—malicious scripts won't execute without you explicitly allowing them. However, we were concerned that warnings would be too easy to ignore, especially since installation appears to succeed. We wanted stricter control with `strictDepBuilds: true`: pnpm-workspace.yaml strictDepBuilds: trueonlyBuiltDependencies: - package-with-necessary-build-scriptsignoredBuiltDependencies: - package-with-unnecessary-build-scripts By "necessary," we mean packages that genuinely need their lifecycle scripts to function—things like native extensions that compile from source or database drivers that link against platform-specific libraries. By "unnecessary," we mean scripts that are optional optimizations or setup steps that don't affect whether the package functions in our use case. With `strictDepBuilds: true`, installation fails immediately when it encounters lifecycle scripts, forcing us to: 1. Identify which packages have lifecycle scripts—pnpm tells you exactly which ones 2. Research what each script does, which can be as easy as feeding the self-contained preinstall or postinstall script into a generative AI for interpretation 3. Use human judgment to make a conscious, documented decision about whether to allow or block it For our team, this ensures we're making deliberate choices upfront rather than potentially discovering issues later. **Note:** The pnpm team is considering making `strictDepBuilds: true` the default behavior in v11, and is also exploring clearer naming for the allow/deny syntax based on feedback from teams implementing these controls in practice. ### Control 2: Release Cooldown[​](https://pnpm.io/blog/2025/12/05/newsroom-npm-supply-chain-security#control-2-release-cooldown "Direct link to Control 2: Release Cooldown") This control blocks installation of package versions published within a cooldown period. The idea is to give the community time to detect and remove malicious packages before they reach your environment. pnpm-workspace.yaml minimumReleaseAge: minimumReleaseAgeExclude: - package-with-critical-hotfix@1.2.3 **Our mindset shift:** We had to retrain ourselves to stop thinking "newest is best." What we're learning is that from a supply chain security perspective, that's not always the case—slightly older can often be safer. A package that's been available for a period of time gives the community and security researchers time to detect potential issues. Looking at recent attacks, malicious packages have been detected and removed in varying timeframes. The [September 2025 npm supply chain attack](https://www.wiz.io/blog/widespread-npm-supply-chain-attack-breaking-down-impact-scope-across-debug-chalk) that compromised debug, chalk, and 16 other packages saw removal within about 2.5 hours, while [Shai-Hulud 2.0](https://securitylabs.datadoghq.com/articles/shai-hulud-2.0-npm-worm/) (November 2025) took about 12 hours. Every attack is different and every recovery timeline will vary, but the appropriate cooldown period depends on your organization's risk tolerance—it could be measured in hours, days, or weeks. Either way, a cooldown period would have blocked these attacks. **The trade-off we accepted:** Given the scale of our organization and our priorities, we're not always on the absolute latest versions of packages—despite best efforts. So this cooldown policy aligns more with our reality than it disrupts it. When we genuinely need a newer version (critical security patches, breaking bugs), we can temporarily exempt it after review. ### Control 3: Trust Policy[​](https://pnpm.io/blog/2025/12/05/newsroom-npm-supply-chain-security#control-3-trust-policy "Direct link to Control 3: Trust Policy") This control blocks installation when a package version has weaker authentication than previously published versions—often a sign that an attacker compromised maintainer credentials and published from their own machine instead of the official CI/CD pipeline. pnpm-workspace.yaml trustPolicy: no-downgradetrustPolicyExclude: - package-that-migrated-cicd@1.2.3 **How it works:** npm tracks three trust levels for published packages (strongest to weakest): 1. **Trusted Publisher:** Published via GitHub Actions with OIDC tokens and npm provenance 2. **Provenance:** Signed attestation from a CI/CD system 3. **No Trust Evidence:** Published with username/password or token authentication If a newer version has weaker authentication than an older version, installation fails. For example, if v1.0.0 was published with Trusted Publisher but v1.0.1 was published with basic auth, pnpm blocks v1.0.1. In the [s1ngularity attack](https://www.wiz.io/blog/s1ngularity-supply-chain-attack) in August 2025, attackers compromised maintainer credentials and published malicious versions from their own machines. Because they didn't have CI/CD access, the malicious versions had no provenance—a clear trust downgrade. This control would have blocked installation. **When trust downgrades might be legitimate:** New maintainer who hasn't set up provenance yet, CI/CD system migration, emergency hotfix published manually while CI/CD was down. In these cases, we'd investigate why the trust level decreased, verify it's safe, then add to `trustPolicyExclude`. **Note:** This feature was added to pnpm in November 2025 and is quite new. We're still learning how often legitimate trust downgrades occur in practice. How They Work Together: The React Example[​](https://pnpm.io/blog/2025/12/05/newsroom-npm-supply-chain-security#how-they-work-together-the-react-example "Direct link to How They Work Together: The React Example") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- We don't see any of these controls as a silver bullet. They work as layers of defense—when we need to make an exception for one control, the other layers continue protecting us. Let's look at a real scenario: the [critical React vulnerability](https://react.dev/blog/2025/12/03/critical-security-vulnerability-in-react-server-components) disclosed in December 2025. This was a serious security issue that required immediate patching. Normally, our release cooldown would prevent us from installing a package version published so recently. But this was a critical security patch—we couldn't wait. Here's how the layered defense would work in this scenario: **What you'd do:** Add the specific React version to `minimumReleaseAgeExclude` after reviewing the vulnerability disclosure and verifying the patch was legitimate. **What still protects you:** * **Lifecycle Script Management** is still active—if an attacker had injected malicious lifecycle scripts into the React patch, they would be blocked (React normally has no lifecycle scripts, so any scripts would be immediately suspicious) * **Trust Policy** is still active—if an attacker had compromised React's publishing credentials and pushed a malicious "patch" from their own machine, the trust downgrade would be blocked This is why we think exceptions are expected and okay. You make a conscious, documented decision to bypass one control for a legitimate reason, but you still have robust protection from the other layers. No single point of failure. This is what defense-in-depth looks like in practice for us. Our Pilot Experience[​](https://pnpm.io/blog/2025/12/05/newsroom-npm-supply-chain-security#our-pilot-experience "Direct link to Our Pilot Experience") ------------------------------------------------------------------------------------------------------------------------------------------------------- We implemented all three security controls in one of our backend services as a proof of concept. Total setup time: a few hours to research, understand, and define our approach. During setup, pnpm identified three packages with lifecycle scripts: * **esbuild:** Optimizes CLI tool startup by milliseconds—not needed since we only use the JavaScript API * **@firebase/util:** Auto-configures client SDK—not needed since we only use the server SDK * **protobufjs:** Checks version schema compatibility—not needed since it's a transitive dependency We researched what each script did (reading documentation and feeding the scripts to AI for interpretation), determined none were necessary for our use case, and blocked them. Zero impact on functionality. That was it. A few hours of initial investment for ongoing protection against Shai-Hulud-style attacks. **What the friction feels like:** These controls create friction by design—and for us, that's a feature, not a bug. The friction forces conscious decisions about what code runs in our environment rather than implicitly trusting everything. When new dependencies have scripts, we anticipate it will take around 15 minutes to review and document the decision. We expect that the friction will become more intuitive with practice as we get more familiar with the process. What We're Learning[​](https://pnpm.io/blog/2025/12/05/newsroom-npm-supply-chain-security#what-were-learning "Direct link to What We're Learning") --------------------------------------------------------------------------------------------------------------------------------------------------- A few things we've learned from our pilot: **The defense-in-depth model actually works.** Having multiple layers on the client side—plus the benefits from npm's publishing-side improvements—means we can be pragmatic about exceptions. When we need to bypass one control for a legitimate reason, the others are still protecting us. This removes the anxiety of making exceptions—they're not security failures, they're the system working as designed. **The mental model takes time.** There's a learning curve to thinking "security-first" rather than "convenience-first." But once the mental model clicks—that slightly older packages are safer, that explicit decisions are better than implicit trust—the workflow feels natural. **These controls are practical for mid-sized teams.** We're not a large tech company with a dedicated security team. We're a mid-sized news media organization with limited engineering resources. If we can implement these controls successfully, they're accessible to most teams. **We're still learning.** The threat landscape evolves, and our approach will too. The trust policy feature is only a few weeks old, and we don't yet know how often legitimate trust downgrades will occur in practice. We're planning to expand these controls to other codebases in the near future, which will give us more data on how they scale with applications with different dependency graphs. For Other Teams Considering This[​](https://pnpm.io/blog/2025/12/05/newsroom-npm-supply-chain-security#for-other-teams-considering-this "Direct link to For Other Teams Considering This") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- If you're considering pnpm's security controls, here's what worked for us: **Start with one project.** Piloting on a single codebase first let us get comfortable with the workflow, understand the friction points, and build confidence before considering a broader rollout. **Plan for exceptions upfront.** Go in expecting you'll need exceptions for lifecycle scripts (packages that need compilation), release cooldowns (critical security patches), and trust downgrades (CI/CD migrations). This isn't failure—it's how the system is designed to work. **Use `strictDepBuilds: true` from day one.** Relying on warnings felt too risky for us. We wanted installation to fail immediately and force the decision. This prevents packages from potentially misbehaving later and ensures deliberate choices. **Document every exception.** Write down why you allowed a lifecycle script or exempted a package. This creates an audit trail, helps future team members understand the reasoning, and makes it easy to clean up exceptions later. **Trust the layers.** When you make an exception for one control, remember the other two are still protecting you. The defense-in-depth model gives you room to be pragmatic. Share Your Experience[​](https://pnpm.io/blog/2025/12/05/newsroom-npm-supply-chain-security#share-your-experience "Direct link to Share Your Experience") ---------------------------------------------------------------------------------------------------------------------------------------------------------- We'd love to hear from other teams implementing these controls or considering them. What's working? What's challenging? What have you learned? Join the conversation in the [pnpm GitHub Discussions](https://github.com/orgs/pnpm/discussions) or share your experiences on social media—we're all learning together. Thank You[​](https://pnpm.io/blog/2025/12/05/newsroom-npm-supply-chain-security#thank-you "Direct link to Thank You") ---------------------------------------------------------------------------------------------------------------------- Thanks to the pnpm team for building these controls and for the thoughtful way they've approached making them both powerful and practical. And thanks for inviting us to share our story. The work you're doing matters. These controls provide real protection that complements npm's registry improvements. Together, they give teams like ours a fighting chance against increasingly sophisticated supply chain attacks. * * * _Ryan Sobol is a Principal Software Engineer at the Seattle Times, where he works on mobile and web development, cloud infrastructure, and developer tooling. The views expressed here are his own and based on the Seattle Times' pilot implementation of pnpm's security controls._ * [Who We Are](https://pnpm.io/blog/2025/12/05/newsroom-npm-supply-chain-security#who-we-are) * [Why Client-Side Controls Matter](https://pnpm.io/blog/2025/12/05/newsroom-npm-supply-chain-security#why-client-side-controls-matter) * [The Three Layers We're Using](https://pnpm.io/blog/2025/12/05/newsroom-npm-supply-chain-security#the-three-layers-were-using) * [Control 1: Lifecycle Script Management](https://pnpm.io/blog/2025/12/05/newsroom-npm-supply-chain-security#control-1-lifecycle-script-management) * [Control 2: Release Cooldown](https://pnpm.io/blog/2025/12/05/newsroom-npm-supply-chain-security#control-2-release-cooldown) * [Control 3: Trust Policy](https://pnpm.io/blog/2025/12/05/newsroom-npm-supply-chain-security#control-3-trust-policy) * [How They Work Together: The React Example](https://pnpm.io/blog/2025/12/05/newsroom-npm-supply-chain-security#how-they-work-together-the-react-example) * [Our Pilot Experience](https://pnpm.io/blog/2025/12/05/newsroom-npm-supply-chain-security#our-pilot-experience) * [What We're Learning](https://pnpm.io/blog/2025/12/05/newsroom-npm-supply-chain-security#what-were-learning) * [For Other Teams Considering This](https://pnpm.io/blog/2025/12/05/newsroom-npm-supply-chain-security#for-other-teams-considering-this) * [Share Your Experience](https://pnpm.io/blog/2025/12/05/newsroom-npm-supply-chain-security#share-your-experience) * [Thank You](https://pnpm.io/blog/2025/12/05/newsroom-npm-supply-chain-security#thank-you) --- # Archive | pnpm [Skip to main content](https://pnpm.io/blog/archive#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** ### 2025[​](https://pnpm.io/blog/archive#2025 "Direct link to 2025") * [July 31 - pnpm 10.14](https://pnpm.io/blog/releases/10.14) * [August 19 - pnpm 10.15](https://pnpm.io/blog/releases/10.15) * [September 12 - pnpm 10.16](https://pnpm.io/blog/releases/10.16) * [September 17 - pnpm 10.17](https://pnpm.io/blog/releases/10.17) * [October 2 - pnpm 10.18](https://pnpm.io/blog/releases/10.18) * [October 21 - pnpm 10.19](https://pnpm.io/blog/releases/10.19) * [October 28 - pnpm 10.20](https://pnpm.io/blog/releases/10.20) * [November 10 - pnpm 10.21](https://pnpm.io/blog/releases/10.21) * [November 12 - pnpm 10.22](https://pnpm.io/blog/releases/10.22) * [November 20 - pnpm 10.23](https://pnpm.io/blog/releases/10.23) * [November 27 - pnpm 10.24](https://pnpm.io/blog/releases/10.24) * [December 5 - How We're Protecting Our Newsroom from npm Supply Chain Attacks](https://pnpm.io/blog/2025/12/05/newsroom-npm-supply-chain-security) * [December 8 - pnpm 10.25](https://pnpm.io/blog/releases/10.25) ### 2022[​](https://pnpm.io/blog/archive#2022 "Direct link to 2022") * [December 30 - The year 2022 for pnpm](https://pnpm.io/blog/2022/12/30/yearly-update) ### 2021[​](https://pnpm.io/blog/archive#2021 "Direct link to 2021") * [December 29 - The year 2021 for pnpm](https://pnpm.io/blog/2021/12/29/yearly-update) ### 2020[​](https://pnpm.io/blog/archive#2020 "Direct link to 2020") * [May 27 - Flat node\_modules is not the only way](https://pnpm.io/blog/2020/05/27/flat-node-modules-is-not-the-only-way) * [October 17 - Node-Modules configuration options with pnpm](https://pnpm.io/blog/2020/10/17/node-modules-configuration-options-with-pnpm) --- # Authors | pnpm [Skip to main content](https://pnpm.io/blog/authors#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** Authors ======= * [![Zoltan Kochan](https://gravatar.com/avatar/1f59f040fb37d5799e3879fa678c2373?s=48)](https://www.kochan.io/) [Zoltan Kochan\ -------------](https://www.kochan.io/) 16 Lead maintainer of pnpm [](https://x.com/ZoltanKochan "X") [](https://github.com/zkochan "GitHub") * Ryan Sobol ---------- 1 Principal Software Engineer at the Seattle Times [](https://github.com/ryansobol "GitHub") --- # Blog | pnpm [Skip to main content](https://pnpm.io/blog/page/2#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** Minor Changes[​](https://pnpm.io/blog/page/2#minor-changes "Direct link to Minor Changes") ------------------------------------------------------------------------------------------- ### New setting for delayed dependency updates[​](https://pnpm.io/blog/page/2#new-setting-for-delayed-dependency-updates "Direct link to New setting for delayed dependency updates") There have been several incidents recently where popular packages were successfully attacked. To reduce the risk of installing a compromised version, we are introducing a new setting that delays the installation of newly released dependencies. In most cases, such attacks are discovered quickly and the malicious versions are removed from the registry within an hour. Minor Changes[​](https://pnpm.io/blog/page/2#minor-changes "Direct link to Minor Changes") ------------------------------------------------------------------------------------------- ### New setting for catalogs[​](https://pnpm.io/blog/page/2#new-setting-for-catalogs "Direct link to New setting for catalogs") Added the [`cleanupUnusedCatalogs`](https://pnpm.io/settings#cleanupunusedcatalogs) configuration. When set to `true`, pnpm will remove unused catalog entries during installation [#9793](https://github.com/pnpm/pnpm/pull/9793) . Added support for JavaScript runtime installation[​](https://pnpm.io/blog/page/2#added-support-for-javascript-runtime-installation "Direct link to Added support for JavaScript runtime installation") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Declare Node.js, Deno, or Bun in [`devEngines.runtime`](https://github.com/openjs-foundation/package-metadata-interoperability-collab-space/issues/15) (inside `package.json`) and let pnpm download and pin it automatically. It is the end of the year. A really hard year. As you may know, I live in Ukraine, so due to Russia's war against us, it was harder to lead this project than in previous years. Nevertheless, it was a good year for pnpm. We've got a lot of new users, contributors, and we have implemented many great features. ![](https://pnpm.io/assets/images/2022-review-092f8f0dfe82b760c2e90fd776d82f75.png) (the above illustration was generated by Midjourney. The tiger symolizes the year of the tiger) It is the end of the year and it was a good year for pnpm, so let's see how it went. There are many ways to create a node\_modules directory. Your goal must be to create the most strict one but if that is not possible, there are options to make a loose node\_modules as well. New users of pnpm frequently ask me about the weird structure of `node_modules` that pnpm creates. Why is it not flat? Where are all the sub-dependencies? --- # pnpm 10.15 | pnpm [Skip to main content](https://pnpm.io/blog/releases/10.15#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** Minor Changes[​](https://pnpm.io/blog/releases/10.15#minor-changes "Direct link to Minor Changes") --------------------------------------------------------------------------------------------------- ### New setting for catalogs[​](https://pnpm.io/blog/releases/10.15#new-setting-for-catalogs "Direct link to New setting for catalogs") Added the [`cleanupUnusedCatalogs`](https://pnpm.io/settings#cleanupunusedcatalogs) configuration. When set to `true`, pnpm will remove unused catalog entries during installation [#9793](https://github.com/pnpm/pnpm/pull/9793) . ### Config dependency improvement[​](https://pnpm.io/blog/releases/10.15#config-dependency-improvement "Direct link to Config dependency improvement") pnpm will now automatically load pnpmfiles from [config dependencies](https://pnpm.io/config-dependencies) that are named `@*/pnpm-plugin-*` [#9780](https://github.com/pnpm/pnpm/issues/9780) . ### Changes to the config get/set commands[​](https://pnpm.io/blog/releases/10.15#changes-to-the-config-getset-commands "Direct link to Changes to the config get/set commands") * `pnpm config get` now prints an INI string for an object value [#9797](https://github.com/pnpm/pnpm/issues/9797) . * `pnpm config get` now accepts property paths. For example: pnpm config get catalog.reactpnpm config get .catalog.reactpnpm config get 'packageExtensions["@babel/parser"].peerDependencies["@babel/types"]' `pnpm config set` now accepts dot-leading or subscripted keys. For example: pnpm config set .ignoreScripts true * `pnpm config get --json` now prints a JSON serialization of config value, and `pnpm config set --json` now parses the input value as JSON. Patch Changes[​](https://pnpm.io/blog/releases/10.15#patch-changes "Direct link to Patch Changes") --------------------------------------------------------------------------------------------------- * **Semi-breaking.** When automatically installing missing peer dependencies, prefer versions that are already present in the direct dependencies of the root workspace package [#9835](https://github.com/pnpm/pnpm/pull/9835) . * When executing the `pnpm create` command, must verify whether the node version is supported even if a cache already exists [#9775](https://github.com/pnpm/pnpm/pull/9775) . * When making requests for the non-abbreviated packument, add `*/*` to the `Accept` header to avoid getting a 406 error on AWS CodeArtifact [#9862](https://github.com/pnpm/pnpm/issues/9862) . * The standalone exe version of pnpm works with glibc 2.26 again [#9734](https://github.com/pnpm/pnpm/issues/9734) . * Fix a regression in which `pnpm dlx pkg --help` doesn't pass `--help` to `pkg` [#9823](https://github.com/pnpm/pnpm/issues/9823) . * [Minor Changes](https://pnpm.io/blog/releases/10.15#minor-changes) * [New setting for catalogs](https://pnpm.io/blog/releases/10.15#new-setting-for-catalogs) * [Config dependency improvement](https://pnpm.io/blog/releases/10.15#config-dependency-improvement) * [Changes to the config get/set commands](https://pnpm.io/blog/releases/10.15#changes-to-the-config-getset-commands) * [Patch Changes](https://pnpm.io/blog/releases/10.15#patch-changes) --- # pnpm 10.14 | pnpm [Skip to main content](https://pnpm.io/blog/releases/10.14#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** Added support for JavaScript runtime installation[​](https://pnpm.io/blog/releases/10.14#added-support-for-javascript-runtime-installation "Direct link to Added support for JavaScript runtime installation") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Declare Node.js, Deno, or Bun in [`devEngines.runtime`](https://github.com/openjs-foundation/package-metadata-interoperability-collab-space/issues/15) (inside `package.json`) and let pnpm download and pin it automatically. Usage example: { "devEngines": { "runtime": { "name": "node", "version": "^24.4.0", "onFail": "download" // we only support the "download" value for now } }} How it works: 1. `pnpm install` resolves your specified range to the latest matching runtime version. 2. The exact version (and checksum) is saved in the lockfile. 3. Scripts use the local runtime, ensuring consistency across environments. Why this is better: 1. This new setting supports also Deno and Bun (vs. our Node-only settings `useNodeVersion` and `executionEnv.nodeVersion`) 2. Supports version ranges (not just a fixed version). 3. The resolved version is stored in the pnpm lockfile, along with an integrity checksum for future validation of the Node.js content's validity. 4. It can be used on any workspace project (like `executionEnv.nodeVersion`). So, different projects in a workspace can use different runtimes. 5. For now `devEngines.runtime` setting will install the runtime locally, which we will improve in future versions of pnpm by using a shared location on the computer. Related PR: [#9755](https://github.com/pnpm/pnpm/pull/9755) . Other new features[​](https://pnpm.io/blog/releases/10.14#other-new-features "Direct link to Other new features") ------------------------------------------------------------------------------------------------------------------ * Added `--cpu`, `--libc`, and `--os` to `pnpm install`, `pnpm add`, and `pnpm dlx` to customize `supportedArchitectures` via the CLI [#7510](https://github.com/pnpm/pnpm/issues/7510) . Bug Fixes[​](https://pnpm.io/blog/releases/10.14#bug-fixes "Direct link to Bug Fixes") --------------------------------------------------------------------------------------- * Fix a bug in which `pnpm add` downloads packages whose `libc` differ from `pnpm.supportedArchitectures.libc`. * The integrities of the downloaded Node.js artifacts are verified [#9750](https://github.com/pnpm/pnpm/pull/9750) . * Allow `dlx` to parse CLI flags and options between the `dlx` command and the command to run or between the `dlx` command and `--` [#9719](https://github.com/pnpm/pnpm/issues/9719) . * `pnpm install --prod` should removing hoisted dev dependencies [#9782](https://github.com/pnpm/pnpm/issues/9782) . * Fix an edge case bug causing local tarballs to not re-link into the virtual store. This bug would happen when changing the contents of the tarball without renaming the file and running a filtered install. * Fix a bug causing `pnpm install` to incorrectly assume the lockfile is up to date after changing a local tarball that has peers dependencies. * [Added support for JavaScript runtime installation](https://pnpm.io/blog/releases/10.14#added-support-for-javascript-runtime-installation) * [Other new features](https://pnpm.io/blog/releases/10.14#other-new-features) * [Bug Fixes](https://pnpm.io/blog/releases/10.14#bug-fixes) --- # pnpm 10.17 | pnpm [Skip to main content](https://pnpm.io/blog/releases/10.17#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** ### Minor Changes[​](https://pnpm.io/blog/releases/10.17#minor-changes "Direct link to Minor Changes") The `minimumReleaseAgeExclude` setting now supports patterns. For instance: minimumReleaseAge: 1440minimumReleaseAgeExclude:- "@eslint/*" Related PR: [#9984](https://github.com/pnpm/pnpm/pull/9984) . ### Patch Changes[​](https://pnpm.io/blog/releases/10.17#patch-changes "Direct link to Patch Changes") * Don't ignore the `minimumReleaseAge` check, when the package is requested by exact version and the packument is loaded from cache [#9978](https://github.com/pnpm/pnpm/issues/9978) . * When `minimumReleaseAge` is set and the active version under a dist-tag is not mature enough, do not downgrade to a prerelease version in case the original version wasn't a prerelease one [#9979](https://github.com/pnpm/pnpm/issues/9979) . * [Minor Changes](https://pnpm.io/blog/releases/10.17#minor-changes) * [Patch Changes](https://pnpm.io/blog/releases/10.17#patch-changes) --- # pnpm 10.16 | pnpm [Skip to main content](https://pnpm.io/blog/releases/10.16#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** Minor Changes[​](https://pnpm.io/blog/releases/10.16#minor-changes "Direct link to Minor Changes") --------------------------------------------------------------------------------------------------- ### New setting for delayed dependency updates[​](https://pnpm.io/blog/releases/10.16#new-setting-for-delayed-dependency-updates "Direct link to New setting for delayed dependency updates") There have been several incidents recently where popular packages were successfully attacked. To reduce the risk of installing a compromised version, we are introducing a new setting that delays the installation of newly released dependencies. In most cases, such attacks are discovered quickly and the malicious versions are removed from the registry within an hour. The new setting is called [`minimumReleaseAge`](https://pnpm.io/settings#minimumreleaseage) . It specifies the number of minutes that must pass after a version is published before pnpm will install it. For example, setting `minimumReleaseAge: 1440` ensures that only packages released at least one day ago can be installed. If you set `minimumReleaseAge` but need to disable this restriction for certain dependencies, you can list them under the [`minimumReleaseAgeExclude`](https://pnpm.io/settings#minimumreleaseageexclude) setting. For instance, with the following configuration pnpm will always install the latest version of webpack, regardless of its release time: minimumReleaseAgeExclude:- webpack Related issue: [#9921](https://github.com/pnpm/pnpm/issues/9921) . ### Advanced dependency filtering with finder functions[​](https://pnpm.io/blog/releases/10.16#advanced-dependency-filtering-with-finder-functions "Direct link to Advanced dependency filtering with finder functions") Added support for [`finders`](https://pnpm.io/finders) . In the past, `pnpm list` and `pnpm why` could only search for dependencies by **name** (and optionally version). For example: pnpm why minimist prints the chain of dependencies to any installed instance of `minimist`: verdaccio 5.20.1├─┬ handlebars 4.7.7│ └── minimist 1.2.8└─┬ mv 2.1.1└─┬ mkdirp 0.5.6 └── minimist 1.2.8 What if we want to search by **other properties** of a dependency, not just its name? For instance, find all packages that have `react@17` in their peer dependencies? This is now possible with "finder functions". Finder functions can be declared in `.pnpmfile.cjs` and invoked with the `--find-by=` flag when running `pnpm list` or `pnpm why`. Let's say we want to find any dependencies that have React 17 in peer dependencies. We can add this finder to our `.pnpmfile.cjs`: module.exports = {finders: { react17: (ctx) => { return ctx.readManifest().peerDependencies?.react === "^17.0.0"; },},}; Now we can use this finder function by running: pnpm why --find-by=react17 pnpm will find all dependencies that have this React in peer dependencies and print their exact locations in the dependency graph. @apollo/client 4.0.4├── @graphql-typed-document-node/core 3.2.0└── graphql-tag 2.12.6 It is also possible to print out some additional information in the output by returning a string from the finder. For example, with the following finder: module.exports = {finders: { react17: (ctx) => { const manifest = ctx.readManifest(); if (manifest.peerDependencies?.react === "^17.0.0") { return `license: ${manifest.license}`; } return false; },},}; Every matched package will also print out the license from its `package.json`: @apollo/client 4.0.4├── @graphql-typed-document-node/core 3.2.0│ license: MIT└── graphql-tag 2.12.6 license: MIT Related PR: [#9946](https://github.com/pnpm/pnpm/pull/9946) . Patch Changes[​](https://pnpm.io/blog/releases/10.16#patch-changes "Direct link to Patch Changes") --------------------------------------------------------------------------------------------------- * Fix deprecation warning printed when executing pnpm with Node.js 24 [#9529](https://github.com/pnpm/pnpm/issues/9529) . * Throw an error if `nodeVersion` is not set to an exact semver version [#9934](https://github.com/pnpm/pnpm/issues/9934) . * `pnpm publish` should be able to publish a `.tar.gz` file [#9927](https://github.com/pnpm/pnpm/pull/9927) . * Canceling a running process with Ctrl-C should make `pnpm run` return a non-zero exit code [#9626](https://github.com/pnpm/pnpm/issues/9626) . * [Minor Changes](https://pnpm.io/blog/releases/10.16#minor-changes) * [New setting for delayed dependency updates](https://pnpm.io/blog/releases/10.16#new-setting-for-delayed-dependency-updates) * [Advanced dependency filtering with finder functions](https://pnpm.io/blog/releases/10.16#advanced-dependency-filtering-with-finder-functions) * [Patch Changes](https://pnpm.io/blog/releases/10.16#patch-changes) --- # pnpm 10.18 | pnpm [Skip to main content](https://pnpm.io/blog/releases/10.18#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** ### Minor Changes[​](https://pnpm.io/blog/releases/10.18#minor-changes "Direct link to Minor Changes") Added network performance monitoring to pnpm by implementing warnings for slow network requests, including both metadata fetches and tarball downloads. Added configuration options for warning thresholds: `fetchWarnTimeoutMs` and `fetchMinSpeedKiBps`. Warning messages are displayed when requests exceed time thresholds or fall below speed minimums Related PR: [#10025](https://github.com/pnpm/pnpm/pull/10025) . ### Patch Changes[​](https://pnpm.io/blog/releases/10.18#patch-changes "Direct link to Patch Changes") * Retry filesystem operations on EAGAIN errors [#9959](https://github.com/pnpm/pnpm/pull/9959) . * Outdated command respects `minimumReleaseAge` configuration [#10030](https://github.com/pnpm/pnpm/pull/10030) . * Correctly apply the `cleanupUnusedCatalogs` configuration when removing dependent packages. * Don't fail with a meaningless error when `scriptShell` is set to `false` [#8748](https://github.com/pnpm/pnpm/issues/8748) . * `pnpm dlx` should not fail when `minimumReleaseAge` is set [#10037](https://github.com/pnpm/pnpm/issues/10037) . * [Minor Changes](https://pnpm.io/blog/releases/10.18#minor-changes) * [Patch Changes](https://pnpm.io/blog/releases/10.18#patch-changes) --- # pnpm 10.19 | pnpm [Skip to main content](https://pnpm.io/blog/releases/10.19#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This release adds version-scoped controls to two settings: [`onlyBuiltDependencies`](https://pnpm.io/settings#onlybuiltdependencies) and [`minimumReleaseAgeExclude`](https://pnpm.io/settings#minimumreleaseageexclude) . ### Minor Changes[​](https://pnpm.io/blog/releases/10.19#minor-changes "Direct link to Minor Changes") #### Versions in `onlyBuiltDependencies`[​](https://pnpm.io/blog/releases/10.19#versions-in-onlybuiltdependencies "Direct link to versions-in-onlybuiltdependencies") You can now allow specific versions of dependencies to run postinstall scripts. [`onlyBuiltDependencies`](https://pnpm.io/settings#onlybuiltdependencies) accepts package names with exact versions (and disjunctions via `||`). For example: onlyBuiltDependencies:- nx@21.6.4 || 21.6.5- esbuild@0.25.1 Related PR: [#10104](https://github.com/pnpm/pnpm/pull/10104) . #### Versions in `minimumReleaseAgeExclude`[​](https://pnpm.io/blog/releases/10.19#versions-in-minimumreleaseageexclude "Direct link to versions-in-minimumreleaseageexclude") Added support for exact versions in [`minimumReleaseAgeExclude`](https://pnpm.io/settings#minimumreleaseageexclude) . This lets you opt specific versions out of the maturity window enforced by [`minimumReleaseAge`](https://pnpm.io/settings#minimumreleaseage) . You can list one or more specific versions that pnpm should allow to install, even if those versions don’t satisfy the maturity requirement set by [`minimumReleaseAge`](https://pnpm.io/settings#minimumreleaseage) . For example: minimumReleaseAge: 1440minimumReleaseAgeExclude:- nx@21.6.5- webpack@4.47.0 || 5.102.1 Related issue: [#9985](https://github.com/pnpm/pnpm/issues/9985) . * [Minor Changes](https://pnpm.io/blog/releases/10.19#minor-changes) --- # pnpm 10.20 | pnpm [Skip to main content](https://pnpm.io/blog/releases/10.20#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This release adds a `--all` flag for the `pnpm help` command to print all commands. ### Minor Changes[​](https://pnpm.io/blog/releases/10.20#minor-changes "Direct link to Minor Changes") #### `pnpm help --all`[​](https://pnpm.io/blog/releases/10.20#pnpm-help---all "Direct link to pnpm-help---all") Added support for `--all` option in `pnpm help` to list all commands [#8628](https://github.com/pnpm/pnpm/pull/8628) . ### Patch Changes[​](https://pnpm.io/blog/releases/10.20#patch-changes "Direct link to Patch Changes") * When the `latest` version doesn't satisfy the maturity requirement configured by `minimumReleaseAge`, pick the highest version that is mature enough, even if it has a different major version [#10100](https://github.com/pnpm/pnpm/issues/10100) . * `create` command should not verify patch info. * Set `managePackageManagerVersions` to `false`, when switching to a different version of pnpm CLI, in order to avoid subsequent switches [#10063](https://github.com/pnpm/pnpm/issues/10063) . * [Minor Changes](https://pnpm.io/blog/releases/10.20#minor-changes) * [Patch Changes](https://pnpm.io/blog/releases/10.20#patch-changes) --- # Articles | pnpm [Skip to main content](https://pnpm.io/community/articles#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** * `2024-06-16`: [How to decrease deployment time by 44% with pnpm](https://shramko.dev/blog/pnpm) * `2023-08-22`: [Phantom Dependencies In Node.js And How PNPM Prevents Them](https://broadcrunch.com/technology/computing/phantom-dependencies-in-nodejs-and-how-pnpm-prevents-them/) * `2022-09-01`: [What is pnpm & why you should try it as a frontend developer](https://javascript.plainenglish.io/what-is-pnpm-why-you-should-try-it-as-a-frontend-developer-69a3a7b34f5b) * `2022-07-22`: [Managing a full-stack, multi-package monorepo using pnpm](https://blog.logrocket.com/managing-full-stack-monorepo-pnpm/) * `2022-06-09`: [pnpm: Because to work more flexible we start from the bottom](https://medium.com/jobtome-engineering/pnpm-because-to-work-more-flexible-we-start-from-the-bottom-5a9c3a9c2af4) * `2022-02-16`: [JavaScript package managers compared: npm, Yarn, or pnpm?](https://blog.logrocket.com/javascript-package-managers-compared/) * `2022-01-18`: [A story of how we migrated to pnpm](https://divriots.com/blog/switching-to-pnpm) * `2022-01-17`: [Yarn, npm, or pnpm?](https://www.pixelmatters.com/blog/yarn-npm-or-pnpm) * `2021-11-17`: [Replacing Lerna + Yarn with pnpm workspaces](https://www.raulmelo.dev/blog/replacing-lerna-and-yarn-with-pnpm-workspaces) * `2021-03-22`: [How to Use pnpm in Netlify build](https://www.seancdavis.com/blog/use-pnpm-with-netlify/) * `2020-11-23`: [Cleaner ESLint config and pnpm support and more with Nx 10.4](https://blog.nrwl.io/cleaner-eslint-config-and-pnpm-compatibility-with-nx-10-4-3f6faa3cdd19) * `2020-09-27`: [pnpm: a space-efficient JavaScript package manager](https://medium.com/javascript-in-plain-english/what-is-pnpm-a-space-efficient-javascript-package-manager-2876b623b81d) * `2020-07-12`: [Mono repository done right!](https://blog.ghaiklor.com/2020/07/12/mono-repository-done-right/comment-page-1/) * `2020-06-09`: [Why we switched from Yarn to pnpm](https://www.takeshape.io/articles/why-we-switched-from-yarn-to-pnpm/) * `2020-06-09`: [Using pnpm with private registries in Bytesafe](https://bytesafe.dev/posts/pnpm-package-manager/) * `2020-06-01`: [pnpm: a space-efficient JavaScript package manager](https://www.infoq.com/news/2020/06/pnpm-javascript-package-manager/?utm_campaign=infoq_content&utm_source=twitter&utm_medium=feed&utm_term=Web-Development) * `2020-03-19`: [The case for pnpm over npm or Yarn](https://medium.com/better-programming/the-case-for-pnpm-over-npm-or-yarn-2b221607119) * `2019-12-28`: [An abbreviated history of JavaScript package managers](https://medium.com/@MattGoldwater/an-abbreviated-history-of-javascript-package-managers-f9797be7cf0e) * `2019-05-19`: [npm vs Yarn vs pnpm: a package manager comparison](https://smddzcy.com/posts/2019-05-19/npm-vs-yarn-vs-pnpm-package-manager-comparison) * `2019-04-03`: [I reclaimed 10GB of disk space from node\_modules](https://dev.to/irreverentmike/i-reclaimed-10gb-of-disk-space-from-node-modules-oal) * `2019-02-10`: [pnpm - fast performant replacement Of npm](https://www.zeptobook.com/pnpm-fast-performant-replacement-of-npm/) * `2019-02-02`: [What is pnpm?](https://flaviocopes.com/pnpm/) * `2018-06-13`: [npm, Yarn and pnpm: which package manager should you use for SharePoint framework projects?](http://www.andrewconnell.com/blog/npm-yarn-pnpm-which-package-manager-should-you-use-for-sharepoint-framework-projects) * `2018-05-24`: [Rush ~ npm vs pnpm vs Yarn](https://rushjs.io/pages/maintainer/package_managers/) * `2018-03-27`: [Package manager rumble](https://www.telerik.com/blogs/package-manager-rumble) * `2018-02-01`: [Trying pnpm on the JustAnswer multi-package repository](https://www.justanswer.com/blog/engineering/pnpm-on-justanswer-multi-package-repository) * `2017-06-12`: [Why I still don't use Yarn](https://intoli.com/blog/node-package-manager-benchmarks/) * `2017-05-14`: [pnpm’s strictness helps to avoid silly bugs](https://www.kochan.io/nodejs/pnpms-strictness-helps-to-avoid-silly-bugs.html) * `2017-05-01`: [Overview of differences between npm, yarn and pnpm](https://hackernoon.com/understanding-differences-between-npm-yarn-and-pnpm-31bb6b0c87b3) * `2017-03-19`: [Why should we use pnpm?](https://www.kochan.io/nodejs/why-should-we-use-pnpm.html) In German: * `2019-10-10`: [JavaScript-Paketmanager pnpm 4 überarbeitet die Verzeichnisstruktur](https://www.heise.de/developer/meldung/JavaScript-Paketmanager-pnpm-4-ueberarbeitet-die-Verzeichnisstruktur-4550827.html) * `2019-10-09`: [pnpm 4.0 veröffentlicht: Eine Alternative zu npm mit überarbeitetem Konzept](https://entwickler.de/online/javascript/pnpm-4-0-package-manager-579910357.html) In French: * `2021-06-01`: [On a changé notre gestionnaire de dépendances front](https://blog.yousign.io/posts/on-a-change-notre-gestionnaire-de-dependances-front?utm_source=twitter&utm_medium=social&utm_campaign=blogep) * `2021-03-19`: [Migration pnpm chez Malt](https://medium.com/nerds-malt/migration-pnpm-chez-malt-4464e5e8069c) In Chinese: * `2023-10-13`: [pnpm包管理的高效存储机制解析](https://juejin.cn/post/7288963210954555448) * `2022-10-24`: [pnpm 原理解析](https://github.com/lvqq/blog/issues/60) * `2022-01-28`: [新一代包管理工具 pnpm](https://www.qjidea.com/pnpm/) * `2022-01-28`: [都2022年了,pnpm快到碗里来!](https://juejin.cn/post/7053340250210795557) * `2021-12-11`: [npm/yarn的设计缺陷,以及pnpm是如何改进的](https://xingyahao.com/c/pnpm-npm-yarn.html) * `2021-12-07`: [为什么 Vue 源码及生态仓库要迁移 pnpm?](https://mp.weixin.qq.com/s/0PfyRfv23aTF2sV_RY11Fw) * `2021-08-28`: [pnpm: 最先进的包管理工具](https://mp.weixin.qq.com/s/5Zo576QFpdAfwXmhfTwWZQ) In Japanese: * `2021-12-11`: [npm/yarnの不足点とpnpmの解決法](https://engineering.meetsmore.com/entry/2021/12/06/112931) --- # Podcasts | pnpm [Skip to main content](https://pnpm.io/community/podcasts#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** * What makes pnpm performant with Zoltan Kochan * [Google Podcasts](https://podcasts.google.com/feed/aHR0cHM6Ly9wb2Ryb2NrZXQubG9ncm9ja2V0LmNvbS9yc3M/episode/N2VhNWEyNDYtMjNkNy00OTc4LWFlOWItNWZmOGE0NGYzYjdl?sa=X&ved=0CAUQkfYCahcKEwigzdmM3Oz7AhUAAAAAHQAAAAAQAQ) * [Apple Podcasts](https://podcasts.apple.com/us/podcast/what-makes-pnpm-performant-with-zoltan-kochan/id1539945251?i=1000589597021) * [Spotify](https://open.spotify.com/episode/653ja7yX66UK9JwF2I6FTA) * [Hasty Treat - How to Setup a pnpm Monorepo](https://syntax.fm/show/401/hasty-treat-how-to-setup-a-pnpm-monorepo) * [Package Management Showdown](https://anchor.fm/opensourcedeveloperpod/episodes/Package-Management-Showdown-e4fnss) --- # Videos | pnpm [Skip to main content](https://pnpm.io/community/videos#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** In English: * `2022-09-01`: [Monorepros with PnPM - Course Drop Party](https://youtu.be/QNaiKN4AaHw) * `2022-04-25`: [Why I Switched From NPM/Yarn to PNPM And Why You Should Too!](https://youtu.be/d1E31WPR70g) * `2022-04-07`: [pnpm – a Fast, Disk Space Efficient Package Manager for JavaScript - Zoltan Kochan, DevOps.js Conf](https://youtu.be/pLI41kHi3AM) * `2022-04-01`: [Get Started with pnpm](https://youtu.be/MvbReZDSKHI) * `2021-12-02`: [Use pnpm instead of npm or yarn for JavaScript & TypeScript](https://youtu.be/uJqqddyzN3s) * `2021-10-13`: [What is pnpm](https://youtu.be/hiTmX2dW84E) * `2019-08-20`: [Reduce SPFX Node Modules from 50,000 files to 1,000](https://vimeo.com/355016928) * `2017-12-20`: [Why I stopped using npm for pnpm And You should too!](https://youtu.be/7L7nBtaGAlM) In Russian: * `2021-12-06`: [Доклад: Пакетные менеджеры: есть ли жизнь за пределами npm? / Валентин Семирульник (Авиасейлс)](https://youtu.be/RAFFHpjrwAs) * [About pnpm v1](https://www.youtube.com/watch?v=rMb4OHL9tWI&feature=youtu.be&t=2m52s) * [npm v5, Yarn или pnpm, что круче?](https://youtu.be/TIeMLwH9SEU) - [slides](http://piterjs.org/events/16/Mike_Bashurov.pdf?utm_source=twitter.com&utm_medium=social&utm_campaign=vystupaet-maykl-bashurov--npm-v5--yarn) In French: * [npm, Yarn et si la vérité était ailleurs?](https://youtu.be/0hq38OWt0EM) - [slides](https://speakerdeck.com/vincent_piard/npm-yarn-et-si-la-verite-etait-ailleurs) - by [@lynchmaniac](https://github.com/lynchmaniac) In Ukrainian: * [pnpm - пакетний менеджер для Node.js](http://bit.ly/pnpm-pr-ukr-1) - by [@zkochan](https://github.com/zkochan) In Spanish: * [Introdución a pnpm](https://youtu.be/rE0_hlG0ifw?t=854) ([Slides](https://docs.google.com/presentation/d/1x2X6EE4yf9V-5xExe1_RMXlCWcurzL1rGi9kc8COEDQ/edit?usp=sharing) ) ([Demo](https://github.com/juanpicado/pnpm-workspace-example) ) by [@jotadeveloper](https://github.com/juanpicado) --- # Tools | pnpm [Skip to main content](https://pnpm.io/community/tools#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** On this page Packages[​](https://pnpm.io/community/tools#packages "Direct link to Packages") -------------------------------------------------------------------------------- * [gatsby-plugin-pnpm](https://github.com/Js-Brecht/gatsby-plugin-pnpm) - Provides pnpm compatible module resolvers to Webpack for Gatsby. * [which-pm](https://github.com/zkochan/which-pm) - Detects what package manager was used for installation. Tools with pnpm support[​](https://pnpm.io/community/tools#tools-with-pnpm-support "Direct link to Tools with pnpm support") ----------------------------------------------------------------------------------------------------------------------------- * [Bazel](https://bazel.build/) (via [rules\_js](https://github.com/aspect-build/rules_js) ) - Google's massively scalable multi-language build tool. * [Bit](https://bit.dev/) - A toolchain for component-driven development. * [changesets](https://github.com/changesets/changesets) - A way to manage your versioning and changelogs with a focus on monorepos. * [handpick](https://github.com/redaxmedia/handpick) - Handpick conditional dependencies like a boss. * [Kretes](https://kretes.dev/) - A programming environment for building full-stack apps in TypeScript. * [Lockfile Explorer](https://lfx.rushstack.io/) - A desktop app for visualizing pnpm lockfiles and troubleshooting version conflicts. * [Meterian](https://meterian.io/) - Ensure your dependencies are not vulnerable, out of date, or with a license you do not want to use. * [Nx](https://nx.dev/) - Next generation build system with first class monorepo support and powerful integrations. * [Renovate](https://docs.renovatebot.com/) - Automated dependency updates, for humans. * [Rush](https://rushjs.io/) - A scalable monorepo manager for the web. * [syncpack](https://github.com/JamieMason/syncpack) - Consistent dependency versions in large JavaScript Monorepos. * [Turborepo](https://turborepo.org/) - A high-performance build system for JavaScript and TypeScript codebases. * [yarnhook](https://github.com/frontsideair/yarnhook) - yarnhook keeps your node\_modules up-to-date when your yarn.lock, package-lock.json or shrinkwrap.yaml changes due to git operations like checkout, merge, rebase, pull etc. * [Packages](https://pnpm.io/community/tools#packages) * [Tools with pnpm support](https://pnpm.io/community/tools#tools-with-pnpm-support) --- # Fast, disk space efficient package manager | pnpm [Skip to main content](https://pnpm.io/#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** ### Fast pnpm is up to 2x faster than npm ### Efficient Files inside node\_modules are cloned or hard linked from a single content-addressable storage ### Supports monorepos pnpm has built-in support for multiple packages in a repository ### Strict pnpm creates a non-flat node\_modules by default, so code has no access to arbitrary packages Sponsored By ============ [![bit](https://pnpm.io/img/users/bit.svg)](https://bit.dev/?utm_source=pnpm&utm_medium=home_page) [![Discord](https://pnpm.io/img/users/discord.svg)](https://discord.com/?utm_source=pnpm&utm_medium=home_page) [![CodeRabbit](https://pnpm.io/img/users/coderabbit.svg)](https://coderabbit.ai/?utm_source=pnpm&utm_medium=home_page) [![Workleap](https://pnpm.io/img/users/workleap.svg)](https://workleap.com/?utm_source=pnpm&utm_medium=home_page) [![vite](https://pnpm.io/img/users/vitejs.svg)](https://vite.dev/?utm_source=pnpm&utm_medium=home_page) [![Stackblitz](https://pnpm.io/img/users/stackblitz.svg)](https://stackblitz.com/?utm_source=pnpm&utm_medium=home_page) [![u|screen](https://pnpm.io/img/users/uscreen.svg)](https://uscreen.de/?utm_source=pnpm&utm_medium=home_page) [![Leniolabs_](https://pnpm.io/img/users/leniolabs.jpg)](https://www.leniolabs.com/?utm_source=pnpm&utm_medium=home_page) [![Vercel](https://pnpm.io/img/users/vercel.svg)](https://vercel.com/?utm_source=pnpm&utm_medium=home_page) [![Depot](https://pnpm.io/img/users/depot_dynamic.svg)](https://depot.dev/?utm_source=pnpm&utm_medium=home_page) [![devowl](https://pnpm.io/img/users/devowlio.svg)](https://devowl.io/?utm_source=pnpm&utm_medium=home_page) [![Cerbos](https://pnpm.io/img/users/cerbos.svg)](https://cerbos.dev/?utm_source=pnpm&utm_medium=home_page) [![vlt](https://pnpm.io/img/users/vlt.svg)](https://vlt.sh/?utm_source=pnpm&utm_medium=home_page) [![OOMOL Studio](https://pnpm.io/img/users/oomol.svg)](https://oomol.com/?utm_source=pnpm&utm_medium=home_page) --- # Catalogs | pnpm [Skip to main content](https://pnpm.io/9.x/catalogs#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/catalogs) ** (10.x). Version: 9.x On this page Added in: v9.5.0 "_Catalogs_" are a [workspace feature](https://pnpm.io/9.x/workspaces) for defining dependency version ranges as reusable constants. Constants defined in catalogs can later be referenced in `package.json` files. The Catalog Protocol (`catalog:`)[​](https://pnpm.io/9.x/catalogs#the-catalog-protocol-catalog "Direct link to the-catalog-protocol-catalog") ---------------------------------------------------------------------------------------------------------------------------------------------- Once a catalog is defined in `pnpm-workspace.yaml`, pnpm-workspace.yaml packages: - packages/*# Define a catalog of version ranges.catalog: react: ^18.3.1 redux: ^5.0.1 The `catalog:` protocol can be used instead of the version range itself. packages/example-app/package.json { "name": "@example/app", "dependencies": { "react": "catalog:", "redux": "catalog:" }} This is equivalent to writing a version range (e.g. `^18.3.1`) directly. packages/example-app/package.json { "name": "@example/app", "dependencies": { "react": "^18.3.1", "redux": "^5.0.1" }} You may use the `catalog:` protocol in the next fields of your `package.json`: * `dependencies` * `devDependencies` * `peerDependencies` * `optionalDependencies` * `pnpm.overrides` The `catalog:` protocol allows an optional name after the colon (ex: `catalog:name`) to specify which catalog should be used. When a name is omitted, the default catalog is used. Depending on the scenario, the `catalog:` protocol offers a few [advantages](https://pnpm.io/9.x/catalogs#advantages) compared to writing version ranges directly that are detailed next. Advantages[​](https://pnpm.io/9.x/catalogs#advantages "Direct link to Advantages") ----------------------------------------------------------------------------------- In a workspace (i.e. monorepo or multi-package repo) it's common for the same dependency to be used by many packages. Catalogs reduce duplication when authoring `package.json` files and provide a few benefits in doing so: * **Maintain unique versions** — It's usually desirable to have only one version of a dependency in a workspace. Catalogs make this easier to maintain. Duplicated dependencies can conflict at runtime and cause bugs. Duplicates also increase size when using a bundler. * **Easier upgrades** — When upgrading a dependency, only the catalog entry in `pnpm-workspace.yaml` needs to be edited rather than all `package.json` files using that dependency. This saves time — only one line needs to be changed instead of many. * **Fewer merge conflicts** — Since `package.json` files do not need to be edited when upgrading a dependency, git merge conflicts no longer happen in these files. Defining Catalogs[​](https://pnpm.io/9.x/catalogs#defining-catalogs "Direct link to Defining Catalogs") -------------------------------------------------------------------------------------------------------- Catalogs are defined in the `pnpm-workspace.yaml` file. There are two ways to define catalogs. 1. Using the (singular) `catalog` field to create a catalog named `default`. 2. Using the (plural) `catalogs` field to create arbitrarily named catalogs. tip If you have an existing workspace that you want to migrate to using catalogs, you can use the following [codemod](https://go.codemod.com/pnpm-catalog) : pnpx codemod pnpm/catalog ### Default Catalog[​](https://pnpm.io/9.x/catalogs#default-catalog "Direct link to Default Catalog") The top-level `catalog` field allows users to define a catalog named `default`. pnpm-workspace.yaml catalog: react: ^18.2.0 react-dom: ^18.2.0 These version ranges can be referenced through `catalog:default`. For the default catalog only, a special `catalog:` shorthand can also be used. Think of `catalog:` as a shorthand that expands to `catalog:default`. ### Named Catalogs[​](https://pnpm.io/9.x/catalogs#named-catalogs "Direct link to Named Catalogs") Multiple catalogs with arbitrarily chosen names can be configured under the `catalogs` key. pnpm-workspace.yaml catalogs: # Can be referenced through "catalog:react17" react17: react: ^17.0.2 react-dom: ^17.0.2 # Can be referenced through "catalog:react18" react18: react: ^18.2.0 react-dom: ^18.2.0 A default catalog can be defined alongside multiple named catalogs. This might be useful in a large multi-package repo that's migrating to a newer version of a dependency piecemeal. pnpm-workspace.yaml catalog: react: ^16.14.0 react-dom: ^16.14.0catalogs: # Can be referenced through "catalog:react17" react17: react: ^17.0.2 react-dom: ^17.0.2 # Can be referenced through "catalog:react18" react18: react: ^18.2.0 react-dom: ^18.2.0 Publishing[​](https://pnpm.io/9.x/catalogs#publishing "Direct link to Publishing") ----------------------------------------------------------------------------------- The `catalog:` protocol is removed when running `pnpm publish` or `pnpm pack`. This is similar to the [`workspace:` protocol](https://pnpm.io/9.x/workspaces#workspace-protocol-workspace) , which is [also replaced on publish](https://pnpm.io/9.x/workspaces#publishing-workspace-packages) . For example, packages/example-components/package.json { "name": "@example/components", "dependencies": { "react": "catalog:react18", }} Will become the following on publish. packages/example-components/package.json { "name": "@example/components", "dependencies": { "react": "^18.3.1", }} The `catalog:` protocol replacement process allows the `@example/components` package to be used by other workspaces or package managers. Caveats[​](https://pnpm.io/9.x/catalogs#caveats "Direct link to Caveats") -------------------------------------------------------------------------- The `pnpm update` command does not yet support catalogs. To update dependencies defined in `pnpm-workspace.yaml`, newer version ranges will need to be chosen manually until a future version of pnpm handles this. * [The Catalog Protocol (`catalog:`)](https://pnpm.io/9.x/catalogs#the-catalog-protocol-catalog) * [Advantages](https://pnpm.io/9.x/catalogs#advantages) * [Defining Catalogs](https://pnpm.io/9.x/catalogs#defining-catalogs) * [Default Catalog](https://pnpm.io/9.x/catalogs#default-catalog) * [Named Catalogs](https://pnpm.io/9.x/catalogs#named-catalogs) * [Publishing](https://pnpm.io/9.x/catalogs#publishing) * [Caveats](https://pnpm.io/9.x/catalogs#caveats) --- # pnpm cache | pnpm [Skip to main content](https://pnpm.io/9.x/cli/cache#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/cache) ** (10.x). Version: 9.x Commands: * [cache list](https://pnpm.io/9.x/cli/cache-list) * [cache list-registries](https://pnpm.io/9.x/cli/cache-list-registries) * [cache delete](https://pnpm.io/9.x/cli/cache-delete) * [cache view](https://pnpm.io/9.x/cli/cache-view) --- # Aliases | pnpm [Skip to main content](https://pnpm.io/9.x/aliases#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/aliases) ** (10.x). Version: 9.x Aliases let you install packages with custom names. Let's assume you use `lodash` all over your project. There is a bug in `lodash` that breaks your project. You have a fix but `lodash` won't merge it. Normally you would either install `lodash` from your fork directly (as a git-hosted dependency) or publish it with a different name. If you use the second solution you have to replace all the requires in your project with the new dependency name (`require('lodash')` => `require('awesome-lodash')`). With aliases, you have a third option. Publish a new package called `awesome-lodash` and install it using `lodash` as its alias: pnpm add lodash@npm:awesome-lodash No changes in code are needed. All the requires of `lodash` will now resolve to `awesome-lodash`. Sometimes you'll want to use two different versions of a package in your project. Easy: pnpm add lodash1@npm:lodash@1pnpm add lodash2@npm:lodash@2 Now you can require the first version of lodash via `require('lodash1')` and the second via `require('lodash2')`. This gets even more powerful when combined with hooks. Maybe you want to replace `lodash` with `awesome-lodash` in all the packages in `node_modules`. You can easily achieve that with the following `.pnpmfile.cjs`: function readPackage(pkg) { if (pkg.dependencies && pkg.dependencies.lodash) { pkg.dependencies.lodash = 'npm:awesome-lodash@^1.0.0' } return pkg}module.exports = { hooks: { readPackage }} --- # pnpm add | pnpm [Skip to main content](https://pnpm.io/9.x/cli/add#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/add) ** (10.x). Version: 9.x On this page Installs a package and any packages that it depends on. By default, any new package is installed as a production dependency. TL;DR[​](https://pnpm.io/9.x/cli/add#tldr "Direct link to TL;DR") ------------------------------------------------------------------ | Command | Meaning | | --- | --- | | `pnpm add sax` | Save to `dependencies` | | `pnpm add -D sax` | Save to `devDependencies` | | `pnpm add -O sax` | Save to `optionalDependencies` | | `pnpm add -g sax` | Install package globally | | `pnpm add sax@next` | Install from the `next` tag | | `pnpm add sax@3.0.0` | Specify version `3.0.0` | Supported package locations[​](https://pnpm.io/9.x/cli/add#supported-package-locations "Direct link to Supported package locations") ------------------------------------------------------------------------------------------------------------------------------------- ### Install from npm registry[​](https://pnpm.io/9.x/cli/add#install-from-npm-registry "Direct link to Install from npm registry") `pnpm add package-name` will install the latest version of `package-name` from the [npm registry](https://www.npmjs.com/) by default. If executed in a workspace, the command will first try to check whether other projects in the workspace use the specified package. If so, the already used version range will be installed. You may also install packages by: * tag: `pnpm add express@nightly` * version: `pnpm add express@1.0.0` * version range: `pnpm add express@2 react@">=0.1.0 <0.2.0"` ### Install from the workspace[​](https://pnpm.io/9.x/cli/add#install-from-the-workspace "Direct link to Install from the workspace") Note that when adding dependencies and working within a [workspace](https://pnpm.io/9.x/workspaces) , packages will be installed from the configured sources, depending on whether or not [`link-workspace-packages`](https://pnpm.io/9.x/workspaces#link-workspace-packages) is set, and use of the [`workspace: range protocol`](https://pnpm.io/9.x/workspaces#workspace-ranges-workspace) . ### Install from local file system[​](https://pnpm.io/9.x/cli/add#install-from-local-file-system "Direct link to Install from local file system") There are two ways to install from the local file system: 1. from a tarball file (`.tar`, `.tar.gz`, or `.tgz`) 2. from a directory Examples: pnpm add ./package.tar.gzpnpm add ./some-directory When you install from a directory, a symlink will be created in the current project's `node_modules`, so it is the same as running `pnpm link`. ### Install from remote tarball[​](https://pnpm.io/9.x/cli/add#install-from-remote-tarball "Direct link to Install from remote tarball") The argument must be a fetchable URL starting with "http://" or "https://". Example: pnpm add https://github.com/indexzero/forever/tarball/v0.5.6 ### Install from Git repository[​](https://pnpm.io/9.x/cli/add#install-from-git-repository "Direct link to Install from Git repository") pnpm add Installs the package from the hosted Git provider, cloning it with Git. You may install packages from Git by: * Latest commit from default branch: pnpm add kevva/is-positive * Git commit hash: pnpm add kevva/is-positive#97edff6f525f192a3f83cea1944765f769ae2678 * Git branch: pnpm add kevva/is-positive#master * Git branch relative to refs: pnpm add zkochan/is-negative#heads/canary * Git tag: pnpm add zkochan/is-negative#2.0.1 * V-prefixed Git tag: pnpm add andreineculau/npm-publish-git#v0.0.7 #### Install from a Git repository using semver[​](https://pnpm.io/9.x/cli/add#install-from-a-git-repository-using-semver "Direct link to Install from a Git repository using semver") You can specify version (range) to install using the `semver:` parameter. For example: * Strict semver: pnpm add zkochan/is-negative#semver:1.0.0 * V-prefixed strict semver: pnpm add andreineculau/npm-publish-git#semver:v0.0.7 * Semver version range: pnpm add kevva/is-positive#semver:^2.0.0 * V-prefixed semver version range: pnpm add andreineculau/npm-publish-git#semver:<=v0.0.7 #### Install from a subdirectory of a Git repository[​](https://pnpm.io/9.x/cli/add#install-from-a-subdirectory-of-a-git-repository "Direct link to Install from a subdirectory of a Git repository") You may also install just a subdirectory from a Git-hosted monorepo using the `path:` parameter. For instance: pnpm add RexSkz/test-git-subdir-fetch#path:/packages/simple-react-app #### Install from a Git repository via a full URL[​](https://pnpm.io/9.x/cli/add#install-from-a-git-repository-via-a-full-url "Direct link to Install from a Git repository via a full URL") If you want to be more explicit or are using alternative Git hosting, you might want to spell out full Git URL: # git+sshpnpm add git+ssh://git@github.com:zkochan/is-negative.git#2.0.1# httpspnpm add https://github.com/zkochan/is-negative.git#2.0.1 #### Install from a Git repository using hosting providers shorthand[​](https://pnpm.io/9.x/cli/add#install-from-a-git-repository-using-hosting-providers-shorthand "Direct link to Install from a Git repository using hosting providers shorthand") You can use a protocol shorthand `[provier]:` for certain Git providers: pnpm add github:zkochan/is-negativepnpm add bitbucket:pnpmjs/git-resolverpnpm add gitlab:pnpm/git-resolver If `[provider]:` is omited, it defaults to `github:`. #### Install from a Git repository combining different parameters[​](https://pnpm.io/9.x/cli/add#install-from-a-git-repository-combining-different-parameters "Direct link to Install from a Git repository combining different parameters") It is possible to combine multiple parameters by separating them with `&`. This can be useful for forks of monorepos: pnpm add RexSkz/test-git-subdir-fetch.git#beta&path:/packages/simple-react-app Installs from the `beta` branch and only the subdirectory at `/packages/simple-react-app`. Options[​](https://pnpm.io/9.x/cli/add#options "Direct link to Options") ------------------------------------------------------------------------- ### \--save-prod, -P[​](https://pnpm.io/9.x/cli/add#--save-prod--p "Direct link to --save-prod, -P") Install the specified packages as regular `dependencies`. ### \--save-dev, -D[​](https://pnpm.io/9.x/cli/add#--save-dev--d "Direct link to --save-dev, -D") Install the specified packages as `devDependencies`. ### \--save-optional, -O[​](https://pnpm.io/9.x/cli/add#--save-optional--o "Direct link to --save-optional, -O") Install the specified packages as `optionalDependencies`. ### \--save-exact, -E[​](https://pnpm.io/9.x/cli/add#--save-exact--e "Direct link to --save-exact, -E") Saved dependencies will be configured with an exact version rather than using pnpm's default semver range operator. ### \--save-peer[​](https://pnpm.io/9.x/cli/add#--save-peer "Direct link to --save-peer") Using `--save-peer` will add one or more packages to `peerDependencies` and install them as dev dependencies. ### \--ignore-workspace-root-check[​](https://pnpm.io/9.x/cli/add#--ignore-workspace-root-check "Direct link to --ignore-workspace-root-check") Adding a new dependency to the root workspace package fails, unless the `--ignore-workspace-root-check` or `-w` flag is used. For instance, `pnpm add debug -w`. ### \--global, -g[​](https://pnpm.io/9.x/cli/add#--global--g "Direct link to --global, -g") Install a package globally. ### \--workspace[​](https://pnpm.io/9.x/cli/add#--workspace "Direct link to --workspace") Only adds the new dependency if it is found in the workspace. ### \--filter [​](https://pnpm.io/9.x/cli/add#--filter-package_selector "Direct link to --filter ") [Read more about filtering.](https://pnpm.io/9.x/filtering) * [TL;DR](https://pnpm.io/9.x/cli/add#tldr) * [Supported package locations](https://pnpm.io/9.x/cli/add#supported-package-locations) * [Install from npm registry](https://pnpm.io/9.x/cli/add#install-from-npm-registry) * [Install from the workspace](https://pnpm.io/9.x/cli/add#install-from-the-workspace) * [Install from local file system](https://pnpm.io/9.x/cli/add#install-from-local-file-system) * [Install from remote tarball](https://pnpm.io/9.x/cli/add#install-from-remote-tarball) * [Install from Git repository](https://pnpm.io/9.x/cli/add#install-from-git-repository) * [Options](https://pnpm.io/9.x/cli/add#options) * [\--save-prod, -P](https://pnpm.io/9.x/cli/add#--save-prod--p) * [\--save-dev, -D](https://pnpm.io/9.x/cli/add#--save-dev--d) * [\--save-optional, -O](https://pnpm.io/9.x/cli/add#--save-optional--o) * [\--save-exact, -E](https://pnpm.io/9.x/cli/add#--save-exact--e) * [\--save-peer](https://pnpm.io/9.x/cli/add#--save-peer) * [\--ignore-workspace-root-check](https://pnpm.io/9.x/cli/add#--ignore-workspace-root-check) * [\--global, -g](https://pnpm.io/9.x/cli/add#--global--g) * [\--workspace](https://pnpm.io/9.x/cli/add#--workspace) * [\--filter ](https://pnpm.io/9.x/cli/add#--filter-package_selector) --- # pnpm audit | pnpm [Skip to main content](https://pnpm.io/9.x/cli/audit#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/audit) ** (10.x). Version: 9.x On this page Checks for known security issues with the installed packages. If security issues are found, try to update your dependencies via `pnpm update`. If a simple update does not fix all the issues, use [overrides](https://pnpm.io/9.x/package_json#pnpmoverrides) to force versions that are not vulnerable. For instance, if `lodash@<2.1.0` is vulnerable, use this overrides to force `lodash@^2.1.0`: package.json { "pnpm": { "overrides": { "lodash@<2.1.0": "^2.1.0" } }} Or alternatively, run `pnpm audit --fix`. If you want to tolerate some vulnerabilities as they don't affect your project, you may use the [`pnpm.auditConfig.ignoreCves`](https://pnpm.io/9.x/package_json#pnpmauditconfigignorecves) setting. Options[​](https://pnpm.io/9.x/cli/audit#options "Direct link to Options") --------------------------------------------------------------------------- ### \--audit-level [​](https://pnpm.io/9.x/cli/audit#--audit-level-severity "Direct link to --audit-level ") * Type: **low**, **moderate**, **high**, **critical** * Default: **low** Only print advisories with severity greater than or equal to ``. ### \--fix[​](https://pnpm.io/9.x/cli/audit#--fix "Direct link to --fix") Add overrides to the `package.json` file in order to force non-vulnerable versions of the dependencies. ### \--json[​](https://pnpm.io/9.x/cli/audit#--json "Direct link to --json") Output audit report in JSON format. ### \--dev, -D[​](https://pnpm.io/9.x/cli/audit#--dev--d "Direct link to --dev, -D") Only audit dev dependencies. ### \--prod, -P[​](https://pnpm.io/9.x/cli/audit#--prod--p "Direct link to --prod, -P") Only audit production dependencies. ### \--no-optional[​](https://pnpm.io/9.x/cli/audit#--no-optional "Direct link to --no-optional") Don't audit `optionalDependencies`. ### \--ignore-registry-errors[​](https://pnpm.io/9.x/cli/audit#--ignore-registry-errors "Direct link to --ignore-registry-errors") If the registry responds with a non-200 status code, the process should exit with 0. So the process will fail only if the registry actually successfully responds with found vulnerabilities. * [Options](https://pnpm.io/9.x/cli/audit#options) * [\--audit-level ](https://pnpm.io/9.x/cli/audit#--audit-level-severity) * [\--fix](https://pnpm.io/9.x/cli/audit#--fix) * [\--json](https://pnpm.io/9.x/cli/audit#--json) * [\--dev, -D](https://pnpm.io/9.x/cli/audit#--dev--d) * [\--prod, -P](https://pnpm.io/9.x/cli/audit#--prod--p) * [\--no-optional](https://pnpm.io/9.x/cli/audit#--no-optional) * [\--ignore-registry-errors](https://pnpm.io/9.x/cli/audit#--ignore-registry-errors) --- # pnpm bin | pnpm [Skip to main content](https://pnpm.io/9.x/cli/bin#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/bin) ** (10.x). Version: 9.x On this page Prints the directory into which the executables of dependencies are linked. Options[​](https://pnpm.io/9.x/cli/bin#options "Direct link to Options") ------------------------------------------------------------------------- ### \--global, -g[​](https://pnpm.io/9.x/cli/bin#--global--g "Direct link to --global, -g") Prints the location of the globally installed executables. * [Options](https://pnpm.io/9.x/cli/bin#options) * [\--global, -g](https://pnpm.io/9.x/cli/bin#--global--g) --- # pnpm cache delete | pnpm [Skip to main content](https://pnpm.io/9.x/cli/cache-delete#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/cache-delete) ** (10.x). Version: 9.x Added in: v9.11.0 warning This command is experimental Deletes metadata cache for the specified package(s). Supports patterns. --- # pnpm cache list-registries | pnpm [Skip to main content](https://pnpm.io/9.x/cli/cache-list-registries#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/cache-list-registries) ** (10.x). Version: 9.x Added in: v9.11.0 warning This command is experimental Lists all registries that have their metadata cache locally. --- # pnpm cache list | pnpm [Skip to main content](https://pnpm.io/9.x/cli/cache-list#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/cache-list) ** (10.x). Version: 9.x Added in: v9.11.0 warning This command is experimental Lists the available packages metadata cache. Supports filtering by glob. --- # pnpm cache view | pnpm [Skip to main content](https://pnpm.io/9.x/cli/cache-view#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/cache-view) ** (10.x). Version: 9.x Added in: v9.11.0 warning This command is experimental Views information from the specified package's cache. --- # pnpm cat-index | pnpm [Skip to main content](https://pnpm.io/9.x/cli/cat-index#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/cat-index) ** (10.x). Version: 9.x Prints the index file of a specific package from the store. The package is specified by its name and version: pnpm cat-index @ --- # pnpm cat-file | pnpm [Skip to main content](https://pnpm.io/9.x/cli/cat-file#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/cat-file) ** (10.x). Version: 9.x Prints the contents of a file based on the hash value stored in the index file. For example: pnpm cat-file sha512-mvavhfVcEREI7d8dfvfvIkuBLnx7+rrkHHnPi8mpEDUlNpY4CUY+CvJ5mrrLl18iQYo1odFwBV7z/cOypG7xxQ== --- # pnpm config | pnpm [Skip to main content](https://pnpm.io/9.x/cli/config#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/config) ** (10.x). Version: 9.x On this page Aliases: `c` Manage the configuration files. The configuration files are in `INI` format. The local configuration file is located in the root of the project and is named `.npmrc`. The global configuration file is located at one of the following locations: * If the **$XDG\_CONFIG\_HOME** env variable is set, then **$XDG\_CONFIG\_HOME/pnpm/rc** * On Windows: **~/AppData/Local/pnpm/config/rc** * On macOS: **~/Library/Preferences/pnpm/rc** * On Linux: **~/.config/pnpm/rc** Commands[​](https://pnpm.io/9.x/cli/config#commands "Direct link to Commands") ------------------------------------------------------------------------------- ### set [​](https://pnpm.io/9.x/cli/config#set-key-value "Direct link to set ") Set the config key to the value provided. ### get [​](https://pnpm.io/9.x/cli/config#get-key "Direct link to get ") Print the config value for the provided key. ### delete [​](https://pnpm.io/9.x/cli/config#delete-key "Direct link to delete ") Remove the config key from the config file. ### list[​](https://pnpm.io/9.x/cli/config#list "Direct link to list") Show all the config settings. Options[​](https://pnpm.io/9.x/cli/config#options "Direct link to Options") ---------------------------------------------------------------------------- ### \--global, -g[​](https://pnpm.io/9.x/cli/config#--global--g "Direct link to --global, -g") Set the configuration in the global config file. ### \--location[​](https://pnpm.io/9.x/cli/config#--location "Direct link to --location") When set to `project`, the `.npmrc` file at the nearest `package.json` will be used. When set to `global`, the performance is the same as setting the `--global` option. ### \--json[​](https://pnpm.io/9.x/cli/config#--json "Direct link to --json") Show all the config settings in JSON format. * [Commands](https://pnpm.io/9.x/cli/config#commands) * [set ](https://pnpm.io/9.x/cli/config#set-key-value) * [get ](https://pnpm.io/9.x/cli/config#get-key) * [delete ](https://pnpm.io/9.x/cli/config#delete-key) * [list](https://pnpm.io/9.x/cli/config#list) * [Options](https://pnpm.io/9.x/cli/config#options) * [\--global, -g](https://pnpm.io/9.x/cli/config#--global--g) * [\--location](https://pnpm.io/9.x/cli/config#--location) * [\--json](https://pnpm.io/9.x/cli/config#--json) --- # pnpm create | pnpm [Skip to main content](https://pnpm.io/9.x/cli/create#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/create) ** (10.x). Version: 9.x On this page Create a project from a `create-*` or `@foo/create-*` starter kit. Examples[​](https://pnpm.io/9.x/cli/create#examples "Direct link to Examples") ------------------------------------------------------------------------------- pnpm create react-app my-app * [Examples](https://pnpm.io/9.x/cli/create#examples) --- # pnpm dedupe | pnpm [Skip to main content](https://pnpm.io/9.x/cli/dedupe#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/dedupe) ** (10.x). Version: 9.x On this page Perform an install removing older dependencies in the lockfile if a newer version can be used. Options[​](https://pnpm.io/9.x/cli/dedupe#options "Direct link to Options") ---------------------------------------------------------------------------- ### `--check`[​](https://pnpm.io/9.x/cli/dedupe#--check "Direct link to --check") Check if running dedupe would result in changes without installing packages or editing the lockfile. Exits with a non-zero status code if changes are possible. * [Options](https://pnpm.io/9.x/cli/dedupe#options) * [`--check`](https://pnpm.io/9.x/cli/dedupe#--check) --- # pnpm dlx | pnpm [Skip to main content](https://pnpm.io/9.x/cli/dlx#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/dlx) ** (10.x). Version: 9.x On this page Aliases: `pnpx` is an alias for `pnpm dlx` Fetches a package from the registry without installing it as a dependency, hotloads it, and runs whatever default command binary it exposes. For example, to use `create-react-app` anywhere to bootstrap a react app without needing to install it under another project, you can run: pnpm dlx create-react-app ./my-app This will fetch `create-react-app` from the registry and run it with the given arguments. You may also specify which exact version of the package you'd like to use: pnpm dlx create-react-app@next ./my-app Options[​](https://pnpm.io/9.x/cli/dlx#options "Direct link to Options") ------------------------------------------------------------------------- ### \--package [​](https://pnpm.io/9.x/cli/dlx#--package-name "Direct link to --package ") The package to install before running the command. Example: pnpm --package=@pnpm/meta-updater dlx meta-updater --helppnpm --package=@pnpm/meta-updater@0 dlx meta-updater --help Multiple packages can be provided for installation: pnpm --package=yo --package=generator-webapp dlx yo webapp --skip-install ### \--shell-mode, -c[​](https://pnpm.io/9.x/cli/dlx#--shell-mode--c "Direct link to --shell-mode, -c") Runs the command inside of a shell. Uses `/bin/sh` on UNIX and `\cmd.exe` on Windows. Example: pnpm --package cowsay --package lolcatjs -c dlx 'echo "hi pnpm" | cowsay | lolcatjs' ### \--silent, -s[​](https://pnpm.io/9.x/cli/dlx#--silent--s "Direct link to --silent, -s") Only the output of the executed command is printed. * [Options](https://pnpm.io/9.x/cli/dlx#options) * [\--package ](https://pnpm.io/9.x/cli/dlx#--package-name) * [\--shell-mode, -c](https://pnpm.io/9.x/cli/dlx#--shell-mode--c) * [\--silent, -s](https://pnpm.io/9.x/cli/dlx#--silent--s) --- # pnpm deploy | pnpm [Skip to main content](https://pnpm.io/9.x/cli/deploy#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/deploy) ** (10.x). Version: 9.x On this page Deploy a package from a workspace. During deployment, the files of the deployed package are copied to the target directory. All dependencies of the deployed package, including dependencies from the workspace, are installed inside an isolated `node_modules` directory at the target directory. The target directory will contain a portable package that can be copied to a server and executed without additional steps. Usage: pnpm --filter= deploy In case you build your project before deployment, also use the `--prod` option to skip `devDependencies` installation. pnpm --filter= --prod deploy Usage in a docker image. After building everything in your monorepo, do this in a second image that uses your monorepo base image as a build context or in an additional build stage: # syntax=docker/dockerfile:1.4FROM workspace as prunedRUN pnpm --filter --prod deploy prunedFROM node:18-alpineWORKDIR /appENV NODE_ENV=productionCOPY --from=pruned /app/pruned .ENTRYPOINT ["node", "index.js"] Options[​](https://pnpm.io/9.x/cli/deploy#options "Direct link to Options") ---------------------------------------------------------------------------- ### \--dev, -D[​](https://pnpm.io/9.x/cli/deploy#--dev--d "Direct link to --dev, -D") Only `devDependencies` are installed regardless of the `NODE_ENV`. ### \--no-optional[​](https://pnpm.io/9.x/cli/deploy#--no-optional "Direct link to --no-optional") `optionalDependencies` are not installed. ### \--prod, -P[​](https://pnpm.io/9.x/cli/deploy#--prod--p "Direct link to --prod, -P") Packages in `devDependencies` won't be installed. ### \--filter [​](https://pnpm.io/9.x/cli/deploy#--filter-package_selector "Direct link to --filter ") [Read more about filtering.](https://pnpm.io/9.x/filtering) Files included in the deployed project[​](https://pnpm.io/9.x/cli/deploy#files-included-in-the-deployed-project "Direct link to Files included in the deployed project") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- By default, all the files of the project are copied during deployment but this can be modified in _one_ of the following ways which are resolved in order: 1. The project's `package.json` may contain a "files" field to list the files and directories that should be copied. 2. If there is an `.npmignore` file in the application directory then any files listed here are ignored. 3. If there is a `.gitignore` file in the application directory then any files listed here are ignored. * [Options](https://pnpm.io/9.x/cli/deploy#options) * [\--dev, -D](https://pnpm.io/9.x/cli/deploy#--dev--d) * [\--no-optional](https://pnpm.io/9.x/cli/deploy#--no-optional) * [\--prod, -P](https://pnpm.io/9.x/cli/deploy#--prod--p) * [\--filter ](https://pnpm.io/9.x/cli/deploy#--filter-package_selector) * [Files included in the deployed project](https://pnpm.io/9.x/cli/deploy#files-included-in-the-deployed-project) --- # pnpm doctor | pnpm [Skip to main content](https://pnpm.io/9.x/cli/doctor#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/doctor) ** (10.x). Version: 9.x Checks for known common issues with pnpm configuration. --- # pnpm env | pnpm [Skip to main content](https://pnpm.io/9.x/cli/env#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/env) ** (10.x). Version: 9.x On this page Manages the Node.js environment. danger `pnpm env` does not include the binaries for Corepack. If you want to use Corepack to install other package managers, you need to install it separately (e.g. `pnpm add -g corepack`). Commands[​](https://pnpm.io/9.x/cli/env#commands "Direct link to Commands") ---------------------------------------------------------------------------- ### use[​](https://pnpm.io/9.x/cli/env#use "Direct link to use") Install and use the specified version of Node.js Install the LTS version of Node.js: pnpm env use --global lts Install Node.js v16: pnpm env use --global 16 Install a prerelease version of Node.js: pnpm env use --global nightlypnpm env use --global rcpnpm env use --global 16.0.0-rc.0pnpm env use --global rc/14 Install the latest version of Node.js: pnpm env use --global latest Install an LTS version of Node.js using its [codename](https://github.com/nodejs/Release/blob/main/CODENAMES.md) : pnpm env use --global argon ### add[​](https://pnpm.io/9.x/cli/env#add "Direct link to add") Installs the specified version(s) of Node.js without activating them as the current version. Example: pnpm env add --global lts 18 20.0.1 ### remove, rm[​](https://pnpm.io/9.x/cli/env#remove-rm "Direct link to remove, rm") Removes the specified version(s) of Node.JS. Usage example: pnpm env remove --global 14.0.0pnpm env remove --global 14.0.0 16.2.3 ### list, ls[​](https://pnpm.io/9.x/cli/env#list-ls "Direct link to list, ls") List Node.js versions available locally or remotely. Print locally installed versions: pnpm env list Print remotely available Node.js versions: pnpm env list --remote Print remotely available Node.js v16 versions: pnpm env list --remote 16 Options[​](https://pnpm.io/9.x/cli/env#options "Direct link to Options") ------------------------------------------------------------------------- ### \--global, -g[​](https://pnpm.io/9.x/cli/env#--global--g "Direct link to --global, -g") The changes are made systemwide. * [Commands](https://pnpm.io/9.x/cli/env#commands) * [use](https://pnpm.io/9.x/cli/env#use) * [add](https://pnpm.io/9.x/cli/env#add) * [remove, rm](https://pnpm.io/9.x/cli/env#remove-rm) * [list, ls](https://pnpm.io/9.x/cli/env#list-ls) * [Options](https://pnpm.io/9.x/cli/env#options) * [\--global, -g](https://pnpm.io/9.x/cli/env#--global--g) --- # pnpm exec | pnpm [Skip to main content](https://pnpm.io/9.x/cli/exec#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/exec) ** (10.x). Version: 9.x On this page Execute a shell command in scope of a project. `node_modules/.bin` is added to the `PATH`, so `pnpm exec` allows executing commands of dependencies. Examples[​](https://pnpm.io/9.x/cli/exec#examples "Direct link to Examples") ----------------------------------------------------------------------------- If you have Jest as a dependency of your project, there is no need to install Jest globally, just run it with `pnpm exec`: pnpm exec jest The `exec` part is actually optional when the command is not in conflict with a builtin pnpm command, so you may also just run: pnpm jest Options[​](https://pnpm.io/9.x/cli/exec#options "Direct link to Options") -------------------------------------------------------------------------- Any options for the `exec` command should be listed before the `exec` keyword. Options listed after the `exec` keyword are passed to the executed command. Good. pnpm will run recursively: pnpm -r exec jest Bad, pnpm will not run recursively but `jest` will be executed with the `-r` option: pnpm exec jest -r ### \--recursive, -r[​](https://pnpm.io/9.x/cli/exec#--recursive--r "Direct link to --recursive, -r") Execute the shell command in every project of the workspace. The name of the current package is available through the environment variable `PNPM_PACKAGE_NAME`. #### Examples[​](https://pnpm.io/9.x/cli/exec#examples-1 "Direct link to Examples") Prune `node_modules` installations for all packages: pnpm -r exec rm -rf node_modules View package information for all packages. This should be used with the `--shell-mode` (or `-c`) option for the environment variable to work. pnpm -rc exec pnpm view \$PNPM_PACKAGE_NAME ### \--no-reporter-hide-prefix[​](https://pnpm.io/9.x/cli/exec#--no-reporter-hide-prefix "Direct link to --no-reporter-hide-prefix") Do not hide prefix when running commands in parallel. ### \--resume-from [​](https://pnpm.io/9.x/cli/exec#--resume-from-package_name "Direct link to --resume-from ") Resume execution from a particular project. This can be useful if you are working with a large workspace and you want to restart a build at a particular project without running through all of the projects that precede it in the build order. ### \--parallel[​](https://pnpm.io/9.x/cli/exec#--parallel "Direct link to --parallel") Completely disregard concurrency and topological sorting, running a given script immediately in all matching packages. This is the preferred flag for long-running processes over many packages, for instance, a lengthy build process. ### \--shell-mode, -c[​](https://pnpm.io/9.x/cli/exec#--shell-mode--c "Direct link to --shell-mode, -c") Runs the command inside of a shell. Uses `/bin/sh` on UNIX and `\cmd.exe` on Windows. ### \--report-summary[​](https://pnpm.io/9.x/cli/exec#--report-summary "Direct link to --report-summary") [Read about this option in the run command docs](https://pnpm.io/9.x/cli/run#--report-summary) ### \--filter [​](https://pnpm.io/9.x/cli/exec#--filter-package_selector "Direct link to --filter ") [Read more about filtering.](https://pnpm.io/9.x/filtering) * [Examples](https://pnpm.io/9.x/cli/exec#examples) * [Options](https://pnpm.io/9.x/cli/exec#options) * [\--recursive, -r](https://pnpm.io/9.x/cli/exec#--recursive--r) * [\--no-reporter-hide-prefix](https://pnpm.io/9.x/cli/exec#--no-reporter-hide-prefix) * [\--resume-from ](https://pnpm.io/9.x/cli/exec#--resume-from-package_name) * [\--parallel](https://pnpm.io/9.x/cli/exec#--parallel) * [\--shell-mode, -c](https://pnpm.io/9.x/cli/exec#--shell-mode--c) * [\--report-summary](https://pnpm.io/9.x/cli/exec#--report-summary) * [\--filter ](https://pnpm.io/9.x/cli/exec#--filter-package_selector) --- # pnpm fetch | pnpm [Skip to main content](https://pnpm.io/9.x/cli/fetch#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/fetch) ** (10.x). Version: 9.x On this page Fetch packages from a lockfile into virtual store, package manifest is ignored. Usage scenario[​](https://pnpm.io/9.x/cli/fetch#usage-scenario "Direct link to Usage scenario") ------------------------------------------------------------------------------------------------ This command is specifically designed to improve building a docker image. You may have read the [official guide](https://github.com/nodejs/docker-node#readme) to writing a Dockerfile for a Node.js app, if you haven't read it yet, you may want to read it first. From that guide, we learn to write an optimized Dockerfile for projects using pnpm, which looks like FROM node:20WORKDIR /path/to/somewhereRUN corepack enable pnpm && corepack install -g pnpm@latest-9# Files required by pnpm installCOPY .npmrc package.json pnpm-lock.yaml .pnpmfile.cjs ./# If you patched any package, include patches before install tooCOPY patches patchesRUN pnpm install --frozen-lockfile --prod# Bundle app sourceCOPY . .EXPOSE 8080CMD [ "node", "server.js" ] As long as there are no changes to `.npmrc`, `package.json`, `pnpm-lock.yaml`, `.pnpmfile.cjs`, docker build cache is still valid up to the layer of `RUN pnpm install --frozen-lockfile --prod`, which cost most of the time when building a docker image. However, modification to `package.json` may happen much more frequently than we expect, because it does not only contain dependencies, but may also contain the version number, scripts, and arbitrary configuration for any other tool. It's also hard to maintain a Dockerfile that builds a monorepo project, it may look like FROM node:20WORKDIR /path/to/somewhereRUN corepack enable pnpm && corepack install -g pnpm@latest-9# Files required by pnpm installCOPY .npmrc package.json pnpm-lock.yaml .pnpmfile.cjs ./# If you patched any package, include patches before install tooCOPY patches patches# for each sub-package, we have to add one extra step to copy its manifest# to the right place, as docker have no way to filter out only package.json with# single instructionCOPY packages/foo/package.json packages/foo/COPY packages/bar/package.json packages/bar/RUN pnpm install --frozen-lockfile --prod# Bundle app sourceCOPY . .EXPOSE 8080CMD [ "node", "server.js" ] As you can see, the Dockerfile has to be updated when you add or remove sub-packages. `pnpm fetch` solves the above problem perfectly by providing the ability to load packages into the virtual store using only information from a lockfile. FROM node:20WORKDIR /path/to/somewhereRUN corepack enable pnpm && corepack install -g pnpm@latest-9# pnpm fetch does require only lockfileCOPY pnpm-lock.yaml ./# If you patched any package, include patches before running pnpm fetchCOPY patches patchesRUN pnpm fetch --prodADD . ./RUN pnpm install -r --offline --prodEXPOSE 8080CMD [ "node", "server.js" ] It works for both simple and monorepo projects, `--offline` enforces pnpm not to communicate with the package registry as all needed packages are already present in the virtual store. As long as the lockfile is not changed, the build cache is valid up to the layer, so `RUN pnpm install -r --offline --prod`, will save you much time. Options[​](https://pnpm.io/9.x/cli/fetch#options "Direct link to Options") --------------------------------------------------------------------------- ### \--dev, -D[​](https://pnpm.io/9.x/cli/fetch#--dev--d "Direct link to --dev, -D") Only development packages will be fetched ### \--prod, -P[​](https://pnpm.io/9.x/cli/fetch#--prod--p "Direct link to --prod, -P") Development packages will not be fetched * [Usage scenario](https://pnpm.io/9.x/cli/fetch#usage-scenario) * [Options](https://pnpm.io/9.x/cli/fetch#options) * [\--dev, -D](https://pnpm.io/9.x/cli/fetch#--dev--d) * [\--prod, -P](https://pnpm.io/9.x/cli/fetch#--prod--p) --- # pnpm 10.21 | pnpm [Skip to main content](https://pnpm.io/blog/releases/10.21#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** Added support for Node.js runtime installation for dependencies and a setting for configuring trust policy. ### Minor Changes[​](https://pnpm.io/blog/releases/10.21#minor-changes "Direct link to Minor Changes") #### Node.js runtime installation for dependencies[​](https://pnpm.io/blog/releases/10.21#nodejs-runtime-installation-for-dependencies "Direct link to Node.js runtime installation for dependencies") Added support for automatic Node.js runtime installation for dependencies. pnpm will now install the Node.js version required by a dependency if that dependency declares a Node.js runtime in the [`engines.runtime`](https://pnpm.io/package_json#enginesruntime) field. For example: {"engines": { "runtime": { "name": "node", "version": "^24.11.0", "onFail": "download" }}} If the package with the Node.js runtime dependency is a CLI app, pnpm will bind the CLI app to the required Node.js version. This ensures that, regardless of the globally installed Node.js instance, the CLI will use the compatible version of Node.js. If the package has a `postinstall` script, that script will be executed using the specified Node.js version. Related PR: [#10141](https://github.com/pnpm/pnpm/pull/10141) #### Trust policy[​](https://pnpm.io/blog/releases/10.21#trust-policy "Direct link to Trust policy") Added a new setting: [`trustPolicy`](https://pnpm.io/settings#trustpolicy) . When set to `no-downgrade`, pnpm will fail if a package's trust level has decreased compared to previous releases. For example, if a package was previously published by a trusted publisher but now only has provenance or no trust evidence, installation will fail. This helps prevent installing potentially compromised versions. Related issue: [#8889](https://github.com/pnpm/pnpm/issues/8889) . #### Other features[​](https://pnpm.io/blog/releases/10.21#other-features "Direct link to Other features") * Added support for `pnpm config get globalconfig` to retrieve the global config file path [#9977](https://github.com/pnpm/pnpm/issues/9977) . ### Patch Changes[​](https://pnpm.io/blog/releases/10.21#patch-changes "Direct link to Patch Changes") * When a user runs `pnpm update` on a dependency that is not directly listed in `package.json`, none of the direct dependencies should be updated [#10155](https://github.com/pnpm/pnpm/pull/10155) . * Don't crash when two processes of pnpm are hardlinking the contents of a directory to the same destination simultaneously [#10160](https://github.com/pnpm/pnpm/pull/10160) . * Setting `gitBranchLockfile` and related settings via `pnpm-workspace.yaml` should work [#9651](https://github.com/pnpm/pnpm/issues/9651) . * [Minor Changes](https://pnpm.io/blog/releases/10.21#minor-changes) * [Patch Changes](https://pnpm.io/blog/releases/10.21#patch-changes) --- # pnpm [Skip to main content](https://pnpm.io/users#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** Who's Using This? ================= This project is used by many folks Are you using this project? [Add your company](https://github.com/pnpm/pnpm.io/edit/main/users.json) ![](https://pnpm.io/img/users/alova.svg "Alova")![](https://pnpm.io/img/users/compass.svg "Compass")![](https://pnpm.io/img/users/prisma.svg "Prisma")![](https://pnpm.io/img/users/microsoft.svg "Microsoft")![](https://pnpm.io/img/users/prezi.svg "Prezi")![](https://pnpm.io/img/users/bytedance.png "ByteDance")![](https://pnpm.io/img/users/justanswer.svg "JustAnswer")![](https://pnpm.io/img/users/tokopedia.svg "Tokopedia")![](https://pnpm.io/img/users/telia.png "Telia Company")![](https://pnpm.io/img/users/wix.svg "Wix")![](https://pnpm.io/img/users/shopee.svg "Shopee")![](https://pnpm.io/img/users/files.svg "Files")![](https://pnpm.io/img/users/takeshape.svg "TakeShape")![](https://pnpm.io/img/users/cyclejs.svg "Cycle.js")![](https://pnpm.io/img/users/glitch.svg "Glitch")![](https://pnpm.io/img/users/rush.svg "Rush")![](https://pnpm.io/img/users/enuma.svg "Enuma Technologies")![](https://pnpm.io/img/users/oax.svg "OAX Foundation")![](https://pnpm.io/img/users/panascais.svg "Panascais")![](https://pnpm.io/img/users/swissdev-javascript-jobs.svg "SwissDev Jobs")![](https://pnpm.io/img/users/tradie-training.png "Tradie Training")![](https://pnpm.io/img/users/kretes.svg "Kretes")![](https://media.securecodewarrior.com/images/current_logo_v.png "Secure Code Warrior")![](https://pnpm.io/img/users/jublia.png "Jublia")![](https://artsolution.de/wp-content/uploads/2020/10/logo.jpg "art solution")![](https://pnpm.io/img/users/sheetjs.png "SheetJS")![](https://pnpm.io/img/users/telescoope.png "Telescoope")![](https://pnpm.io/img/users/netlicensing.png "NetLicensing")![](https://pnpm.io/img/users/fonkel.svg "Fonkel")![](https://pnpm.io/img/users/verdaccio.svg "Verdaccio")![](https://pnpm.io/img/users/sveltekit.svg "SvelteKit")![](https://pnpm.io/img/users/syntaxphoenix.svg "SyntaxPhoenix IT-Solutions")![](https://pnpm.io/img/users/codecarrot.svg "CodeCarrot")![](https://pnpm.io/img/users/vue.svg "Vue")![](https://pnpm.io/img/users/bytesafe.svg "Bytesafe")![](https://pnpm.io/img/users/jike.svg "Jike")![](https://pnpm.io/img/users/pabio.svg "Pabio")![](https://pnpm.io/img/users/peakactivity.png "PeakActivity")![](https://pnpm.io/img/users/yonghui.png "Yonghui")![](https://pnpm.io/img/users/netease-avg.png "NetEase Avg")![](https://pnpm.io/img/users/element-plus.svg "Element Plus")![](https://pnpm.io/img/users/agora-flat.svg "Agora Flat")![](https://pnpm.io/img/users/maze.png "Maze")![](https://pnpm.io/img/users/nhost.svg "Nhost")![](https://pnpm.io/img/users/shipber.png "Shipber")![](https://pnpm.io/img/users/adber.svg "Adber")![](https://pnpm.io/img/users/qwik.svg "Qwik")![](https://pnpm.io/img/users/tinyhttp.svg "Tinyhttp")![](https://pnpm.io/img/users/lodine.svg "Lodine")![](https://pnpm.io/img/users/emberjs.svg "Ember")![](https://pnpm.io/img/users/mui.svg "MUI")![](https://pnpm.io/img/users/realgolf.png "RealGolf")![](https://pnpm.io/img/users/macpaw.svg "MacPaw")![](https://pnpm.io/img/users/flashproxy.svg "FlashProxy")![](https://pnpm.io/img/users/osmos.svg "Osmos") --- # pnpm publish | pnpm [Skip to main content](https://pnpm.io/9.x/cli/publish#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/publish) ** (10.x). Version: 9.x On this page Publishes a package to the registry. pnpm [-r] publish [] [--tag ] [--access ] [options] When publishing a package inside a [workspace](https://pnpm.io/9.x/workspaces) , the LICENSE file from the root of the workspace is packed with the package (unless the package has a license of its own). You may override some fields before publish, using the [publishConfig](https://pnpm.io/9.x/package_json#publishconfig) field in `package.json`. You also can use the [`publishConfig.directory`](https://pnpm.io/9.x/package_json#publishconfigdirectory) to customize the published subdirectory (usually using third party build tools). When running this command recursively (`pnpm -r publish`), pnpm will publish all the packages that have versions not yet published to the registry. Options[​](https://pnpm.io/9.x/cli/publish#options "Direct link to Options") ----------------------------------------------------------------------------- ### \--recursive, -r[​](https://pnpm.io/9.x/cli/publish#--recursive--r "Direct link to --recursive, -r") Publish all packages from the workspace. ### \--json[​](https://pnpm.io/9.x/cli/publish#--json "Direct link to --json") Show information in JSON format. ### \--tag [​](https://pnpm.io/9.x/cli/publish#--tag-tag "Direct link to --tag ") Publishes the package with the given tag. By default, `pnpm publish` updates the `latest` tag. For example: # inside the foo package directorypnpm publish --tag next# in a project where you want to use the next version of foopnpm add foo@next ### \--access [​](https://pnpm.io/9.x/cli/publish#--access-publicrestricted "Direct link to --access ") Tells the registry whether the published package should be public or restricted. ### \--no-git-checks[​](https://pnpm.io/9.x/cli/publish#--no-git-checks "Direct link to --no-git-checks") Don't check if current branch is your publish branch, clean, and up-to-date with remote. ### \--publish-branch [​](https://pnpm.io/9.x/cli/publish#--publish-branch-branch "Direct link to --publish-branch ") * Default: **master** and **main** * Types: **String** The primary branch of the repository which is used for publishing the latest changes. ### \--force[​](https://pnpm.io/9.x/cli/publish#--force "Direct link to --force") Try to publish packages even if their current version is already found in the registry. ### \--report-summary[​](https://pnpm.io/9.x/cli/publish#--report-summary "Direct link to --report-summary") Save the list of published packages to `pnpm-publish-summary.json`. Useful when some other tooling is used to report the list of published packages. An example of a `pnpm-publish-summary.json` file: { "publishedPackages": [ { "name": "foo", "version": "1.0.0" }, { "name": "bar", "version": "2.0.0" } ]} ### \--dry-run[​](https://pnpm.io/9.x/cli/publish#--dry-run "Direct link to --dry-run") Does everything a publish would do except actually publishing to the registry. ### \--otp[​](https://pnpm.io/9.x/cli/publish#--otp "Direct link to --otp") When publishing packages that require two-factor authentication, this option can specify a one-time password. ### \--filter [​](https://pnpm.io/9.x/cli/publish#--filter-package_selector "Direct link to --filter ") [Read more about filtering.](https://pnpm.io/9.x/filtering) Configuration[​](https://pnpm.io/9.x/cli/publish#configuration "Direct link to Configuration") ----------------------------------------------------------------------------------------------- You can also set `git-checks`, `publish-branch` options in the `.npmrc` file. For example: .npmrc git-checks=falsepublish-branch=production Life Cycle Scripts[​](https://pnpm.io/9.x/cli/publish#life-cycle-scripts "Direct link to Life Cycle Scripts") -------------------------------------------------------------------------------------------------------------- * `prepublishOnly` * `prepublish` * `prepack` * `prepare` * `postpack` * `publish` * `postpublish` * [Options](https://pnpm.io/9.x/cli/publish#options) * [\--recursive, -r](https://pnpm.io/9.x/cli/publish#--recursive--r) * [\--json](https://pnpm.io/9.x/cli/publish#--json) * [\--tag ](https://pnpm.io/9.x/cli/publish#--tag-tag) * [\--access ](https://pnpm.io/9.x/cli/publish#--access-publicrestricted) * [\--no-git-checks](https://pnpm.io/9.x/cli/publish#--no-git-checks) * [\--publish-branch ](https://pnpm.io/9.x/cli/publish#--publish-branch-branch) * [\--force](https://pnpm.io/9.x/cli/publish#--force) * [\--report-summary](https://pnpm.io/9.x/cli/publish#--report-summary) * [\--dry-run](https://pnpm.io/9.x/cli/publish#--dry-run) * [\--otp](https://pnpm.io/9.x/cli/publish#--otp) * [\--filter ](https://pnpm.io/9.x/cli/publish#--filter-package_selector) * [Configuration](https://pnpm.io/9.x/cli/publish#configuration) * [Life Cycle Scripts](https://pnpm.io/9.x/cli/publish#life-cycle-scripts) --- # pnpm import | pnpm [Skip to main content](https://pnpm.io/9.x/cli/import#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/import) ** (10.x). Version: 9.x `pnpm import` generates a `pnpm-lock.yaml` from another package manager's lockfile. Supported source files: * `package-lock.json` * `npm-shrinkwrap.json` * `yarn.lock` Note that if you have workspaces you wish to import dependencies for, they will need to be declared in a [pnpm-workspace.yaml](https://pnpm.io/9.x/pnpm-workspace_yaml) file beforehand. --- # pnpm 10.22 | pnpm [Skip to main content](https://pnpm.io/blog/releases/10.22#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** Added support for excluding packages from trust policy and overriding the `engines` field on publish. ### Minor Changes[​](https://pnpm.io/blog/releases/10.22#minor-changes "Direct link to Minor Changes") #### Trust policy exclusions[​](https://pnpm.io/blog/releases/10.22#trust-policy-exclusions "Direct link to Trust policy exclusions") Added support for [`trustPolicyExclude`](https://pnpm.io/settings#trustpolicyexclude) . You can now list one or more specific packages or versions that pnpm should allow to install, even if those packages don't satisfy the trust policy requirement. For example: trustPolicy: no-downgradetrustPolicyExclude: - chokidar@4.0.3 - webpack@4.47.0 || 5.102.1 Related issue: [#10164](https://github.com/pnpm/pnpm/issues/10164) #### Override engines field on publish[​](https://pnpm.io/blog/releases/10.22#override-engines-field-on-publish "Direct link to Override engines field on publish") Allow to override the `engines` field on publish by the `publishConfig.engines` field. This allows you to specify different engine requirements for your published package than what you use during development. ### Patch Changes[​](https://pnpm.io/blog/releases/10.22#patch-changes "Direct link to Patch Changes") * Don't crash when two processes of pnpm are hardlinking the contents of a directory to the same destination simultaneously [#10179](https://github.com/pnpm/pnpm/issues/10179) . * [Minor Changes](https://pnpm.io/blog/releases/10.22#minor-changes) * [Patch Changes](https://pnpm.io/blog/releases/10.22#patch-changes) --- # pnpm 10.23 | pnpm [Skip to main content](https://pnpm.io/blog/releases/10.23#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** Added `--lockfile-only` option to `pnpm list` and various improvements to `pnpm self-update`. ### Minor Changes[​](https://pnpm.io/blog/releases/10.23#minor-changes "Direct link to Minor Changes") #### `pnpm list --lockfile-only`[​](https://pnpm.io/blog/releases/10.23#pnpm-list---lockfile-only "Direct link to pnpm-list---lockfile-only") Added `--lockfile-only` option to `pnpm list` [#10020](https://github.com/pnpm/pnpm/issues/10020) . When specified, `pnpm list` will read package information from the lockfile instead of checking the actual `node_modules` directory. This is useful for quickly inspecting what would be installed without requiring a full installation. ### Patch Changes[​](https://pnpm.io/blog/releases/10.23#patch-changes "Direct link to Patch Changes") * `pnpm self-update` should download pnpm from the configured npm registry [#10205](https://github.com/pnpm/pnpm/pull/10205) . * `pnpm self-update` should always install the non-executable pnpm package (pnpm in the registry) and never the `@pnpm/exe` package, when installing v11 or newer. We currently cannot ship `@pnpm/exe` as `pkg` doesn't work with ESM [#10190](https://github.com/pnpm/pnpm/pull/10190) . * Node.js runtime is not added to "dependencies" on `pnpm add`, if there's a `engines.runtime` setting declared in `package.json` [#10209](https://github.com/pnpm/pnpm/issues/10209) . * The installation should fail if an optional dependency cannot be installed due to a trust policy check failure [#10208](https://github.com/pnpm/pnpm/issues/10208) . * `pnpm list` and `pnpm why` now display npm: protocol for aliased packages (e.g., `foo npm:is-odd@3.0.1`) [#8660](https://github.com/pnpm/pnpm/issues/8660) . * Don't add an extra slash to the Node.js mirror URL [#10204](https://github.com/pnpm/pnpm/pull/10204) . * `pnpm store prune` should not fail if the store contains Node.js packages [#10131](https://github.com/pnpm/pnpm/issues/10131) . * [Minor Changes](https://pnpm.io/blog/releases/10.23#minor-changes) * [Patch Changes](https://pnpm.io/blog/releases/10.23#patch-changes) --- # pnpm -r, --recursive | pnpm [Skip to main content](https://pnpm.io/9.x/cli/recursive#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/recursive) ** (10.x). Version: 9.x On this page Aliases: `m`, `multi`, `recursive`, ` -r` Runs a command in every project of a workspace, when used with the following commands: * `install` * `list` * `outdated` * `publish` * `rebuild` * `remove` * `unlink` * `update` * `why` Runs a command in every project of a workspace, excluding the root project, when used with the following commands: * `exec` * `run` * `test` * `add` If you want the root project be included even when running scripts, set the [include-workspace-root](https://pnpm.io/9.x/npmrc#include-workspace-root) setting to `true`. Usage example: pnpm -r publish Options[​](https://pnpm.io/9.x/cli/recursive#options "Direct link to Options") ------------------------------------------------------------------------------- ### \--link-workspace-packages[​](https://pnpm.io/9.x/cli/recursive#--link-workspace-packages "Direct link to --link-workspace-packages") * Default: **false** * Type: **true, false, deep** Link locally available packages in workspaces of a monorepo into `node_modules` instead of re-downloading them from the registry. This emulates functionality similar to `yarn workspaces`. When this is set to deep, local packages can also be linked to subdependencies. Be advised that it is encouraged instead to use [npmrc](https://pnpm.io/9.x/workspaces#link-workspace-packages) for this setting, to enforce the same behaviour in all environments. This option exists solely so you may override that if necessary. ### \--workspace-concurrency[​](https://pnpm.io/9.x/cli/recursive#--workspace-concurrency "Direct link to --workspace-concurrency") * Default: **4** * Type: **Number** Set the maximum number of tasks to run simultaneously. For unlimited concurrency use `Infinity`. You can set the `workspace-concurrency` as `<= 0` and it will use amount of cores of the host as: `max(1, (number of cores) - abs(workspace-concurrency))` ### \--\[no-\]bail[​](https://pnpm.io/9.x/cli/recursive#--no-bail "Direct link to --[no-]bail") * Default: **true** * Type: **Boolean** If true, stops when a task throws an error. This config does not affect the exit code. Even if `--no-bail` is used, all tasks will finish but if any of the tasks fail, the command will exit with a non-zero code. Example (run tests in every package, continue if tests fail in one of them): pnpm -r --no-bail test ### \--\[no-\]sort[​](https://pnpm.io/9.x/cli/recursive#--no-sort "Direct link to --[no-]sort") * Default: **true** * Type: **Boolean** When `true`, packages are sorted topologically (dependencies before dependents). Pass `--no-sort` to disable. Example: pnpm -r --no-sort test ### \--reverse[​](https://pnpm.io/9.x/cli/recursive#--reverse "Direct link to --reverse") * Default: **false** * Type: **boolean** When `true`, the order of packages is reversed. pnpm -r --reverse run clean ### \--filter [​](https://pnpm.io/9.x/cli/recursive#--filter-package_selector "Direct link to --filter ") [Read more about filtering.](https://pnpm.io/9.x/filtering) * [Options](https://pnpm.io/9.x/cli/recursive#options) * [\--link-workspace-packages](https://pnpm.io/9.x/cli/recursive#--link-workspace-packages) * [\--workspace-concurrency](https://pnpm.io/9.x/cli/recursive#--workspace-concurrency) * [\--\[no-\]bail](https://pnpm.io/9.x/cli/recursive#--no-bail) * [\--\[no-\]sort](https://pnpm.io/9.x/cli/recursive#--no-sort) * [\--reverse](https://pnpm.io/9.x/cli/recursive#--reverse) * [\--filter ](https://pnpm.io/9.x/cli/recursive#--filter-package_selector) --- # pnpm 10.24 | pnpm [Skip to main content](https://pnpm.io/blog/releases/10.24#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** pnpm now scales network concurrency automatically on high-core machines and ships several reliability fixes. ### Minor Changes[​](https://pnpm.io/blog/releases/10.24#minor-changes "Direct link to Minor Changes") #### Adaptive network concurrency[​](https://pnpm.io/blog/releases/10.24#adaptive-network-concurrency "Direct link to Adaptive network concurrency") Network concurrency now scales automatically between 16 and 64 based on the number of pnpm workers (workers × 3). This increases throughput on machines with many CPU cores while keeping resource usage predictable on smaller setups [#10068](https://github.com/pnpm/pnpm/issues/10068) . ### Patch Changes[​](https://pnpm.io/blog/releases/10.24#patch-changes "Direct link to Patch Changes") * `trustPolicy` now ignores trust evidences from prerelease versions when you install a non-prerelease version, so a trusted prerelease cannot block installing a stable release that lacks trust evidence. * Handle `ENOENT` errors thrown by `fs.linkSync()`, which can occur in containerized environments (OverlayFS) instead of `EXDEV`. pnpm now gracefully falls back to `fs.copyFileSync()` in these cases [#10217](https://github.com/pnpm/pnpm/issues/10217) . * Reverted: `pnpm self-update` downloading pnpm from the configured npm registry [#10205](https://github.com/pnpm/pnpm/pull/10205) . * Packages that don't have a `package.json` file (like Node.js) are no longer reimported from the store on every install. pnpm now checks an additional file to verify the package in `node_modules`. * Correctly read auth tokens for URLs that contain underscores [#17](https://github.com/pnpm/npm-conf/pull/17) . * [Minor Changes](https://pnpm.io/blog/releases/10.24#minor-changes) * [Patch Changes](https://pnpm.io/blog/releases/10.24#patch-changes) --- # pnpm 10.25 | pnpm [Skip to main content](https://pnpm.io/blog/releases/10.25#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** pnpm 10.25 improves certificate handling, adds a bare `pnpm init`, and ships several quality-of-life fixes. ### Minor Changes[​](https://pnpm.io/blog/releases/10.25#minor-changes "Direct link to Minor Changes") #### Per-registry certificates[​](https://pnpm.io/blog/releases/10.25#per-registry-certificates "Direct link to Per-registry certificates") You can now load inline certificates from the `cert`, `ca`, and `key` settings for specific registry URLs (for example, `//registry.example.com/:ca=-----BEGIN CERTIFICATE-----...`). Previously, pnpm only respected the `certfile`, `cafile`, and `keyfile` entries. This aligns pnpm with npm's `.npmrc` behavior [#10230](https://github.com/pnpm/pnpm/pull/10230) . #### `pnpm init --bare`[​](https://pnpm.io/blog/releases/10.25#pnpm-init---bare "Direct link to pnpm-init---bare") Added a `--bare` flag to `pnpm init` for creating a `package.json` with only the required fields [#10226](https://github.com/pnpm/pnpm/issues/10226) . ### Patch Changes[​](https://pnpm.io/blog/releases/10.25#patch-changes "Direct link to Patch Changes") * Improved reporting of ignored dependency scripts [#10276](https://github.com/pnpm/pnpm/pull/10276) . * `pnpm install` now builds any dependencies that were added to `onlyBuiltDependencies` but have not run their builds yet [#10256](https://github.com/pnpm/pnpm/pull/10256) . * `pnpm publish -r --force` will publish even if the version already exists in the registry, matching the intent of the flag [#10272](https://github.com/pnpm/pnpm/issues/10272) . * Avoid `ERR_PNPM_MISSING_TIME` errors when a package excluded from trust policy checks lacks the `time` field in its metadata. * [Minor Changes](https://pnpm.io/blog/releases/10.25#minor-changes) * [Patch Changes](https://pnpm.io/blog/releases/10.25#patch-changes) --- # Tags | pnpm [Skip to main content](https://pnpm.io/blog/tags#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** Tags ==== R[​](https://pnpm.io/blog/tags#R "Direct link to R") ----------------------------------------------------- * [release12](https://pnpm.io/blog/tags/release) * * * --- # Crypto Donations | pnpm [Skip to main content](https://pnpm.io/crypto-donations#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** If your crypto of choice is not in the list below, feel free to contact us, and we will set up a wallet for it. Bitcoin (BTC)[​](https://pnpm.io/crypto-donations#bitcoin-btc "Direct link to Bitcoin (BTC)") ---------------------------------------------------------------------------------------------- bc1qpym6epeakpkv8qcq9ev7259jsd4mkmnlq7g0er Ethereum (ETH)[​](https://pnpm.io/crypto-donations#ethereum-eth "Direct link to Ethereum (ETH)") ------------------------------------------------------------------------------------------------- 0x0F9524B7a9431CAe344f599d4583A4E0CBcdE579 Solana (SOL)[​](https://pnpm.io/crypto-donations#solana-sol "Direct link to Solana (SOL)") ------------------------------------------------------------------------------------------- Ah4ej6nwhov8edie9SVp5nTPyFYzRWUjjGGgtyEieGfm Litecoin (LTC)[​](https://pnpm.io/crypto-donations#litecoin-ltc "Direct link to Litecoin (LTC)") ------------------------------------------------------------------------------------------------- LNcpNmEnBMm6pY5N9j9yryk1yfmP7UWHfJ Bitcoin Cash (BCH)[​](https://pnpm.io/crypto-donations#bitcoin-cash-bch "Direct link to Bitcoin Cash (BCH)") ------------------------------------------------------------------------------------------------------------- qz4v4qvjzc0g43jz4a7jjuzr65a8dlnc9sc4763ecl * [Bitcoin (BTC)](https://pnpm.io/crypto-donations#bitcoin-btc) * [Ethereum (ETH)](https://pnpm.io/crypto-donations#ethereum-eth) * [Solana (SOL)](https://pnpm.io/crypto-donations#solana-sol) * [Litecoin (LTC)](https://pnpm.io/crypto-donations#litecoin-ltc) * [Bitcoin Cash (BCH)](https://pnpm.io/crypto-donations#bitcoin-cash-bch) --- # 12 posts tagged with "release" | pnpm [Skip to main content](https://pnpm.io/blog/tags/release/page/2#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** Minor Changes[​](https://pnpm.io/blog/tags/release/page/2#minor-changes "Direct link to Minor Changes") -------------------------------------------------------------------------------------------------------- ### New setting for catalogs[​](https://pnpm.io/blog/tags/release/page/2#new-setting-for-catalogs "Direct link to New setting for catalogs") Added the [`cleanupUnusedCatalogs`](https://pnpm.io/settings#cleanupunusedcatalogs) configuration. When set to `true`, pnpm will remove unused catalog entries during installation [#9793](https://github.com/pnpm/pnpm/pull/9793) . Added support for JavaScript runtime installation[​](https://pnpm.io/blog/tags/release/page/2#added-support-for-javascript-runtime-installation "Direct link to Added support for JavaScript runtime installation") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Declare Node.js, Deno, or Bun in [`devEngines.runtime`](https://github.com/openjs-foundation/package-metadata-interoperability-collab-space/issues/15) (inside `package.json`) and let pnpm download and pin it automatically. --- # Search the documentation | pnpm [Skip to main content](https://pnpm.io/search#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** Search the documentation ======================== Powered by Algolia[](https://www.algolia.com/) --- # 12 posts tagged with "release" | pnpm [Skip to main content](https://pnpm.io/blog/tags/release#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** pnpm 10.25 improves certificate handling, adds a bare `pnpm init`, and ships several quality-of-life fixes. pnpm now scales network concurrency automatically on high-core machines and ships several reliability fixes. Added `--lockfile-only` option to `pnpm list` and various improvements to `pnpm self-update`. Added support for excluding packages from trust policy and overriding the `engines` field on publish. Added support for Node.js runtime installation for dependencies and a setting for configuring trust policy. This release adds a `--all` flag for the `pnpm help` command to print all commands. This release adds version-scoped controls to two settings: \[`onlyBuiltDependencies`\] and \[`minimumReleaseAgeExclude`\]. ### Minor Changes[​](https://pnpm.io/blog/tags/release#minor-changes "Direct link to Minor Changes") Added network performance monitoring to pnpm by implementing warnings for slow network requests, including both metadata fetches and tarball downloads. Added configuration options for warning thresholds: `fetchWarnTimeoutMs` and `fetchMinSpeedKiBps`. Warning messages are displayed when requests exceed time thresholds or fall below speed minimums Related PR: [#10025](https://github.com/pnpm/pnpm/pull/10025) . ### Patch Changes[​](https://pnpm.io/blog/tags/release#patch-changes "Direct link to Patch Changes") * Retry filesystem operations on EAGAIN errors [#9959](https://github.com/pnpm/pnpm/pull/9959) . * Outdated command respects `minimumReleaseAge` configuration [#10030](https://github.com/pnpm/pnpm/pull/10030) . * Correctly apply the `cleanupUnusedCatalogs` configuration when removing dependent packages. * Don't fail with a meaningless error when `scriptShell` is set to `false` [#8748](https://github.com/pnpm/pnpm/issues/8748) . * `pnpm dlx` should not fail when `minimumReleaseAge` is set [#10037](https://github.com/pnpm/pnpm/issues/10037) . ### Minor Changes[​](https://pnpm.io/blog/tags/release#minor-changes "Direct link to Minor Changes") The `minimumReleaseAgeExclude` setting now supports patterns. Minor Changes[​](https://pnpm.io/blog/tags/release#minor-changes "Direct link to Minor Changes") ------------------------------------------------------------------------------------------------- ### New setting for delayed dependency updates[​](https://pnpm.io/blog/tags/release#new-setting-for-delayed-dependency-updates "Direct link to New setting for delayed dependency updates") There have been several incidents recently where popular packages were successfully attacked. To reduce the risk of installing a compromised version, we are introducing a new setting that delays the installation of newly released dependencies. In most cases, such attacks are discovered quickly and the malicious versions are removed from the registry within an hour. --- # pnpm remove | pnpm [Skip to main content](https://pnpm.io/9.x/cli/remove#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/remove) ** (10.x). Version: 9.x On this page Aliases: `rm`, `uninstall`, `un` Removes packages from `node_modules` and from the project's `package.json`. Options[​](https://pnpm.io/9.x/cli/remove#options "Direct link to Options") ---------------------------------------------------------------------------- ### \--recursive, -r[​](https://pnpm.io/9.x/cli/remove#--recursive--r "Direct link to --recursive, -r") When used inside a [workspace](https://pnpm.io/9.x/workspaces) , removes a dependency (or dependencies) from every workspace package. When used not inside a workspace, removes a dependency (or dependencies) from every package found in subdirectories. ### \--global, -g[​](https://pnpm.io/9.x/cli/remove#--global--g "Direct link to --global, -g") Remove a global package. ### \--save-dev, -D[​](https://pnpm.io/9.x/cli/remove#--save-dev--d "Direct link to --save-dev, -D") Only remove the dependency from `devDependencies`. ### \--save-optional, -O[​](https://pnpm.io/9.x/cli/remove#--save-optional--o "Direct link to --save-optional, -O") Only remove the dependency from `optionalDependencies`. ### \--save-prod, -P[​](https://pnpm.io/9.x/cli/remove#--save-prod--p "Direct link to --save-prod, -P") Only remove the dependency from `dependencies`. ### \--filter [​](https://pnpm.io/9.x/cli/remove#--filter-package_selector "Direct link to --filter ") [Read more about filtering.](https://pnpm.io/9.x/filtering) * [Options](https://pnpm.io/9.x/cli/remove#options) * [\--recursive, -r](https://pnpm.io/9.x/cli/remove#--recursive--r) * [\--global, -g](https://pnpm.io/9.x/cli/remove#--global--g) * [\--save-dev, -D](https://pnpm.io/9.x/cli/remove#--save-dev--d) * [\--save-optional, -O](https://pnpm.io/9.x/cli/remove#--save-optional--o) * [\--save-prod, -P](https://pnpm.io/9.x/cli/remove#--save-prod--p) * [\--filter ](https://pnpm.io/9.x/cli/remove#--filter-package_selector) --- # pnpm rebuild | pnpm [Skip to main content](https://pnpm.io/9.x/cli/rebuild#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/rebuild) ** (10.x). Version: 9.x On this page Aliases: `rb` Rebuild a package. Options[​](https://pnpm.io/9.x/cli/rebuild#options "Direct link to Options") ----------------------------------------------------------------------------- ### \--recursive, -r[​](https://pnpm.io/9.x/cli/rebuild#--recursive--r "Direct link to --recursive, -r") This command runs the **pnpm rebuild** command in every package of the monorepo. ### \--filter [​](https://pnpm.io/9.x/cli/rebuild#--filter-package_selector "Direct link to --filter ") [Read more about filtering.](https://pnpm.io/9.x/filtering) * [Options](https://pnpm.io/9.x/cli/rebuild#options) * [\--recursive, -r](https://pnpm.io/9.x/cli/rebuild#--recursive--r) * [\--filter ](https://pnpm.io/9.x/cli/rebuild#--filter-package_selector) --- # pnpm find-hash | pnpm [Skip to main content](https://pnpm.io/9.x/cli/find-hash#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/find-hash) ** (10.x). Version: 9.x warning This command is experimental Lists the packages that include the file with the specified hash. For example: pnpm find-hash sha512-mvavhfVcEREI7d8dfvfvIkuBLnx7+rrkHHnPi8mpEDUlNpY4CUY+CvJ5mrrLl18iQYo1odFwBV7z/cOypG7xxQ== --- # pnpm init | pnpm [Skip to main content](https://pnpm.io/9.x/cli/init#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/init) ** (10.x). Version: 9.x Create a `package.json` file. --- # pnpm install | pnpm [Skip to main content](https://pnpm.io/9.x/cli/install#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/install) ** (10.x). Version: 9.x On this page Aliases: `i` `pnpm install` is used to install all dependencies for a project. In a CI environment, installation fails if a lockfile is present but needs an update. Inside a [workspace](https://pnpm.io/9.x/workspaces) , `pnpm install` installs all dependencies in all the projects. If you want to disable this behavior, set the `recursive-install` setting to `false`. ![](https://pnpm.io/assets/images/pnpm-install-922fbb8bb4d96b8f602a40e6cd07ee13.svg) TL;DR[​](https://pnpm.io/9.x/cli/install#tldr "Direct link to TL;DR") ---------------------------------------------------------------------- | Command | Meaning | | --- | --- | | `pnpm i --offline` | Install offline from the store only | | `pnpm i --frozen-lockfile` | `pnpm-lock.yaml` is not updated | | `pnpm i --lockfile-only` | Only `pnpm-lock.yaml` is updated | Options[​](https://pnpm.io/9.x/cli/install#options "Direct link to Options") ----------------------------------------------------------------------------- ### \--force[​](https://pnpm.io/9.x/cli/install#--force "Direct link to --force") Force reinstall dependencies: refetch packages modified in store, recreate a lockfile and/or modules directory created by a non-compatible version of pnpm. Install all optionalDependencies even they don't satisfy the current environment(cpu, os, arch). ### \--offline[​](https://pnpm.io/9.x/cli/install#--offline "Direct link to --offline") * Default: **false** * Type: **Boolean** If `true`, pnpm will use only packages already available in the store. If a package won't be found locally, the installation will fail. ### \--prefer-offline[​](https://pnpm.io/9.x/cli/install#--prefer-offline "Direct link to --prefer-offline") * Default: **false** * Type: **Boolean** If `true`, staleness checks for cached data will be bypassed, but missing data will be requested from the server. To force full offline mode, use `--offline`. ### \--prod, -P[​](https://pnpm.io/9.x/cli/install#--prod--p "Direct link to --prod, -P") * Default: * If `NODE_ENV` is `production`: `true` * If `NODE_ENV` is **not** `production`: `false` * Type: Boolean If set, pnpm will ignore `NODE_ENV` and instead use this boolean value for determining the environment. If `true`, pnpm will not install any package listed in `devDependencies` and will remove those insofar they were already installed. If `false`, pnpm will install all packages listed in `devDependencies` and `dependencies`. ### \--dev, -D[​](https://pnpm.io/9.x/cli/install#--dev--d "Direct link to --dev, -D") Only `devDependencies` are installed and `dependencies` are removed insofar they were already installed, regardless of the `NODE_ENV`. ### \--no-optional[​](https://pnpm.io/9.x/cli/install#--no-optional "Direct link to --no-optional") `optionalDependencies` are not installed. ### \--lockfile-only[​](https://pnpm.io/9.x/cli/install#--lockfile-only "Direct link to --lockfile-only") * Default: **false** * Type: **Boolean** When used, only updates `pnpm-lock.yaml` and `package.json`. Nothing gets written to the `node_modules` directory. ### \--fix-lockfile[​](https://pnpm.io/9.x/cli/install#--fix-lockfile "Direct link to --fix-lockfile") Fix broken lockfile entries automatically. ### \--frozen-lockfile[​](https://pnpm.io/9.x/cli/install#--frozen-lockfile "Direct link to --frozen-lockfile") * Default: * For non-CI: **false** * For CI: **true**, if a lockfile is present * Type: **Boolean** If `true`, pnpm doesn't generate a lockfile and fails to install if the lockfile is out of sync with the manifest / an update is needed or no lockfile is present. This setting is `true` by default in [CI environments](https://github.com/watson/ci-info#supported-ci-tools) . The following code is used to detect CI environments: https://github.com/watson/ci-info/blob/44e98cebcdf4403f162195fbcf90b1f69fc6e047/index.js#L54-L61 exports.isCI = !!( env.CI || // Travis CI, CircleCI, Cirrus CI, GitLab CI, Appveyor, CodeShip, dsari env.CONTINUOUS_INTEGRATION || // Travis CI, Cirrus CI env.BUILD_NUMBER || // Jenkins, TeamCity env.RUN_ID || // TaskCluster, dsari exports.name || false) ### \--merge-git-branch-lockfiles[​](https://pnpm.io/9.x/cli/install#--merge-git-branch-lockfiles "Direct link to --merge-git-branch-lockfiles") Merge all git branch lockfiles. [Read more about git branch lockfiles.](https://pnpm.io/9.x/git_branch_lockfiles) ### \--reporter=[​](https://pnpm.io/9.x/cli/install#--reportername "Direct link to --reporter=") * Default: * For TTY stdout: **default** * For non-TTY stdout: **append-only** * Type: **default**, **append-only**, **ndjson**, **silent** Allows you to choose the reporter that will log debug info to the terminal about the installation progress. * **silent** - no output is logged to the console, not even fatal errors * **default** - the default reporter when the stdout is TTY * **append-only** - the output is always appended to the end. No cursor manipulations are performed * **ndjson** - the most verbose reporter. Prints all logs in [ndjson](https://github.com/ndjson/ndjson-spec) format If you want to change what type of information is printed, use the [loglevel](https://pnpm.io/9.x/npmrc#loglevel) setting. ### \--use-store-server[​](https://pnpm.io/9.x/cli/install#--use-store-server "Direct link to --use-store-server") * Default: **false** * Type: **Boolean** danger Deprecated feature Starts a store server in the background. The store server will keep running after installation is done. To stop the store server, run `pnpm server stop` ### \--shamefully-hoist[​](https://pnpm.io/9.x/cli/install#--shamefully-hoist "Direct link to --shamefully-hoist") * Default: **false** * Type: **Boolean** Creates a flat `node_modules` structure, similar to that of `npm` or `yarn`. **WARNING**: This is highly discouraged. ### \--ignore-scripts[​](https://pnpm.io/9.x/cli/install#--ignore-scripts "Direct link to --ignore-scripts") * Default: **false** * Type: **Boolean** Do not execute any scripts defined in the project `package.json` and its dependencies. ### \--filter [​](https://pnpm.io/9.x/cli/install#--filter-package_selector "Direct link to --filter ") warning Filter currently does not work properly with v8 default config, you have to implicitly set [dedupe-peer-dependents](https://pnpm.io/9.x/npmrc#dedupe-peer-dependents) to `false` to have that work. For more info and progress please refer to [#6300](https://github.com/pnpm/pnpm/issues/6300) [Read more about filtering.](https://pnpm.io/9.x/filtering) ### \--resolution-only[​](https://pnpm.io/9.x/cli/install#--resolution-only "Direct link to --resolution-only") Re-runs resolution: useful for printing out peer dependency issues. * [TL;DR](https://pnpm.io/9.x/cli/install#tldr) * [Options](https://pnpm.io/9.x/cli/install#options) * [\--force](https://pnpm.io/9.x/cli/install#--force) * [\--offline](https://pnpm.io/9.x/cli/install#--offline) * [\--prefer-offline](https://pnpm.io/9.x/cli/install#--prefer-offline) * [\--prod, -P](https://pnpm.io/9.x/cli/install#--prod--p) * [\--dev, -D](https://pnpm.io/9.x/cli/install#--dev--d) * [\--no-optional](https://pnpm.io/9.x/cli/install#--no-optional) * [\--lockfile-only](https://pnpm.io/9.x/cli/install#--lockfile-only) * [\--fix-lockfile](https://pnpm.io/9.x/cli/install#--fix-lockfile) * [\--frozen-lockfile](https://pnpm.io/9.x/cli/install#--frozen-lockfile) * [\--merge-git-branch-lockfiles](https://pnpm.io/9.x/cli/install#--merge-git-branch-lockfiles) * [\--reporter=](https://pnpm.io/9.x/cli/install#--reportername) * [\--use-store-server](https://pnpm.io/9.x/cli/install#--use-store-server) * [\--shamefully-hoist](https://pnpm.io/9.x/cli/install#--shamefully-hoist) * [\--ignore-scripts](https://pnpm.io/9.x/cli/install#--ignore-scripts) * [\--filter ](https://pnpm.io/9.x/cli/install#--filter-package_selector) * [\--resolution-only](https://pnpm.io/9.x/cli/install#--resolution-only) --- # pnpm install-test | pnpm [Skip to main content](https://pnpm.io/9.x/cli/install-test#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/install-test) ** (10.x). Version: 9.x Aliases: `it` Runs `pnpm install` followed immediately by `pnpm test`. It takes exactly the same arguments as [`pnpm install`](https://pnpm.io/9.x/cli/install) . --- # pnpm licenses | pnpm [Skip to main content](https://pnpm.io/9.x/cli/licenses#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/licenses) ** (10.x). Version: 9.x On this page Commands[​](https://pnpm.io/9.x/cli/licenses#commands "Direct link to Commands") --------------------------------------------------------------------------------- ### list[​](https://pnpm.io/9.x/cli/licenses#list "Direct link to list") List licenses for installed packages. Options[​](https://pnpm.io/9.x/cli/licenses#options "Direct link to Options") ------------------------------------------------------------------------------ ### \--filter [​](https://pnpm.io/9.x/cli/licenses#--filter-package_selector "Direct link to --filter ") [Read more about filtering.](https://pnpm.io/9.x/filtering) * [Commands](https://pnpm.io/9.x/cli/licenses#commands) * [list](https://pnpm.io/9.x/cli/licenses#list) * [Options](https://pnpm.io/9.x/cli/licenses#options) * [\--filter ](https://pnpm.io/9.x/cli/licenses#--filter-package_selector) --- # pnpm link | pnpm [Skip to main content](https://pnpm.io/9.x/cli/link#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/link) ** (10.x). Version: 9.x On this page Aliases: `ln` Makes the current local package accessible system-wide, or in another location. pnpm link pnpm link --globalpnpm link --global Options[​](https://pnpm.io/9.x/cli/link#options "Direct link to Options") -------------------------------------------------------------------------- ### \--dir , -C[​](https://pnpm.io/9.x/cli/link#--dir-dir--c "Direct link to --dir , -C") * **Default**: Current working directory * **Type**: Path string Changes the link location to ``. ### `pnpm link `[​](https://pnpm.io/9.x/cli/link#pnpm-link-dir "Direct link to pnpm-link-dir") Links package from `` folder to node\_modules of package from where you're executing this command or specified via `--dir` option. > For example, if you are inside `~/projects/foo` and you execute `pnpm link ../bar`, then a link to `bar` will be created in `foo/node_modules/bar`. ### `pnpm link --global`[​](https://pnpm.io/9.x/cli/link#pnpm-link---global "Direct link to pnpm-link---global") Links package from location where this command was executed or specified via `--dir` option to global `node_modules`, so it can be referred from another package with `pnpm link --global `. Also if the package has a `bin` field, then the package's binaries become available system-wide. ### `pnpm link --global `[​](https://pnpm.io/9.x/cli/link#pnpm-link---global-pkg "Direct link to pnpm-link---global-pkg") Links the specified package (``) from global `node_modules` to the `node_modules` of package from where this command was executed or specified via `--dir` option. Difference between `pnpm link ` and `pnpm link --dir `[​](https://pnpm.io/9.x/cli/link#difference-between-pnpm-link-dir-and-pnpm-link---dir-dir "Direct link to difference-between-pnpm-link-dir-and-pnpm-link---dir-dir") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- `pnpm link ` links the package from `` to the `node_modules` of the package where the command was executed. `pnpm link --dir ` links the package from the current working directory to ``. # The current directory is foopnpm link ../bar- foo - node_modules - bar -> ../../bar- bar# The current directory is barpnpm link --dir ../foo- foo - node_modules - bar -> ../../bar- bar Use Cases[​](https://pnpm.io/9.x/cli/link#use-cases "Direct link to Use Cases") -------------------------------------------------------------------------------- ### Replace an installed package with a local version of it[​](https://pnpm.io/9.x/cli/link#replace-an-installed-package-with-a-local-version-of-it "Direct link to Replace an installed package with a local version of it") Let's say you have a project that uses `foo` package. You want to make changes to `foo` and test them in your project. In this scenario, you can use `pnpm link` to link the local version of `foo` to your project, while the `package.json` won't be modified. cd ~/projects/foopnpm install # install dependencies of foopnpm link --global # link foo globallycd ~/projects/my-projectpnpm link --global foo # link foo to my-project You can also link a package from a directory to another directory, without using the global `node_modules` folder: cd ~/projects/foopnpm install # install dependencies of foocd ~/projects/my-projectpnpm link ~/projects/foo # link foo to my-project ### Add a binary globally[​](https://pnpm.io/9.x/cli/link#add-a-binary-globally "Direct link to Add a binary globally") If you are developing a package that has a binary, for example, a CLI tool, you can use `pnpm link --global` to make the binary available system-wide. This is the same as using `pnpm install -g foo`, but it will use the local version of `foo` instead of downloading it from the registry. Remember that the binary will be available only if the package has a `bin` field in its `package.json`. cd ~/projects/foopnpm install # install dependencies of foopnpm link --global # link foo globally What's the difference between `pnpm link` and using the `file:` protocol?[​](https://pnpm.io/9.x/cli/link#whats-the-difference-between-pnpm-link-and-using-the-file-protocol "Direct link to whats-the-difference-between-pnpm-link-and-using-the-file-protocol") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ When you use `pnpm link`, the linked package is symlinked from the source code. You can modify the source code of the linked package, and the changes will be reflected in your project. With this method pnpm will not install the dependencies of the linked package, you will have to install them manually in the source code. This may be useful when you have to use a specific package manager for the linked package, for example, if you want to use `npm` for the linked package, but pnpm for your project. When you use the `file:` protocol in `dependencies`, the linked package is hard-linked to your project `node_modules`, you can modify the source code of the linked package, and the changes will be reflected in your project. With this method pnpm will also install the dependencies of the linked package, overriding the `node_modules` of the linked package. info When dealing with **peer dependencies** it is recommended to use the `file:` protocol. It better resolves the peer dependencies from the project dependencies, ensuring that the linked dependency correctly uses the versions of the dependencies specified in your main project, leading to more consistent and expected behaviors. | Feature | `pnpm link` | `file:` Protocol | | --- | --- | --- | | Symlink/Hard-link | Symlink | Hard-link | | Reflects source code modifications | Yes | Yes | | Installs dependencies of the linked package | No (manual installation required) | Yes (overrides `node_modules` of the linked package) | | Use different package manager for dependency | Possible (e.g., use `npm` for linked pkg) | No, it will use pnpm | * [Options](https://pnpm.io/9.x/cli/link#options) * [\--dir , -C](https://pnpm.io/9.x/cli/link#--dir-dir--c) * [`pnpm link `](https://pnpm.io/9.x/cli/link#pnpm-link-dir) * [`pnpm link --global`](https://pnpm.io/9.x/cli/link#pnpm-link---global) * [`pnpm link --global `](https://pnpm.io/9.x/cli/link#pnpm-link---global-pkg) * [Difference between `pnpm link ` and `pnpm link --dir `](https://pnpm.io/9.x/cli/link#difference-between-pnpm-link-dir-and-pnpm-link---dir-dir) * [Use Cases](https://pnpm.io/9.x/cli/link#use-cases) * [Replace an installed package with a local version of it](https://pnpm.io/9.x/cli/link#replace-an-installed-package-with-a-local-version-of-it) * [Add a binary globally](https://pnpm.io/9.x/cli/link#add-a-binary-globally) * [What's the difference between `pnpm link` and using the `file:` protocol?](https://pnpm.io/9.x/cli/link#whats-the-difference-between-pnpm-link-and-using-the-file-protocol) --- # pnpm list | pnpm [Skip to main content](https://pnpm.io/9.x/cli/list#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/list) ** (10.x). Version: 9.x On this page Aliases: `ls` This command will output all the versions of packages that are installed, as well as their dependencies, in a tree-structure. Positional arguments are `name-pattern@version-range` identifiers, which will limit the results to only the packages named. For example, `pnpm list "babel-*" "eslint-*" semver@5`. Options[​](https://pnpm.io/9.x/cli/list#options "Direct link to Options") -------------------------------------------------------------------------- ### \--recursive, -r[​](https://pnpm.io/9.x/cli/list#--recursive--r "Direct link to --recursive, -r") Perform command on every package in subdirectories or on every workspace package, when executed inside a workspace. ### \--json[​](https://pnpm.io/9.x/cli/list#--json "Direct link to --json") Log output in JSON format. ### \--long[​](https://pnpm.io/9.x/cli/list#--long "Direct link to --long") Show extended information. ### \--parseable[​](https://pnpm.io/9.x/cli/list#--parseable "Direct link to --parseable") Outputs package directories in a parseable format instead of their tree view. ### \--global, -g[​](https://pnpm.io/9.x/cli/list#--global--g "Direct link to --global, -g") List packages in the global install directory instead of in the current project. ### \--depth [​](https://pnpm.io/9.x/cli/list#--depth-number "Direct link to --depth ") Max display depth of the dependency tree. `pnpm ls --depth 0` (default) will list direct dependencies only. `pnpm ls --depth -1` will list projects only. Useful inside a workspace when used with the `-r` option. `pnpm ls --depth Infinity` will list all dependencies regardless of depth. ### \--prod, -P[​](https://pnpm.io/9.x/cli/list#--prod--p "Direct link to --prod, -P") Display only the dependency graph for packages in `dependencies` and `optionalDependencies`. ### \--dev, -D[​](https://pnpm.io/9.x/cli/list#--dev--d "Direct link to --dev, -D") Display only the dependency graph for packages in `devDependencies`. ### \--no-optional[​](https://pnpm.io/9.x/cli/list#--no-optional "Direct link to --no-optional") Don't display packages from `optionalDependencies`. ### \--only-projects[​](https://pnpm.io/9.x/cli/list#--only-projects "Direct link to --only-projects") Display only dependencies that are also projects within the workspace. ### \--exclude-peers[​](https://pnpm.io/9.x/cli/list#--exclude-peers "Direct link to --exclude-peers") Added in: v9.10.0 Exclude peer dependencies from the results (but dependencies of peer dependencies are not ignored). ### \--filter [​](https://pnpm.io/9.x/cli/list#--filter-package_selector "Direct link to --filter ") [Read more about filtering.](https://pnpm.io/9.x/filtering) * [Options](https://pnpm.io/9.x/cli/list#options) * [\--recursive, -r](https://pnpm.io/9.x/cli/list#--recursive--r) * [\--json](https://pnpm.io/9.x/cli/list#--json) * [\--long](https://pnpm.io/9.x/cli/list#--long) * [\--parseable](https://pnpm.io/9.x/cli/list#--parseable) * [\--global, -g](https://pnpm.io/9.x/cli/list#--global--g) * [\--depth ](https://pnpm.io/9.x/cli/list#--depth-number) * [\--prod, -P](https://pnpm.io/9.x/cli/list#--prod--p) * [\--dev, -D](https://pnpm.io/9.x/cli/list#--dev--d) * [\--no-optional](https://pnpm.io/9.x/cli/list#--no-optional) * [\--only-projects](https://pnpm.io/9.x/cli/list#--only-projects) * [\--exclude-peers](https://pnpm.io/9.x/cli/list#--exclude-peers) * [\--filter ](https://pnpm.io/9.x/cli/list#--filter-package_selector) --- # pnpm patch | pnpm [Skip to main content](https://pnpm.io/9.x/cli/patch#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/patch) ** (10.x). Version: 9.x On this page Prepare a package for patching (inspired by a similar command in Yarn). This command will cause a package to be extracted in a temporary directory intended to be editable at will. Once you're done with your changes, run `pnpm patch-commit ` (with `` being the temporary directory you received) to generate a patchfile and register it into your top-level manifest via the [`patchedDependencies`](https://pnpm.io/9.x/package_json#pnpmpatcheddependencies) field. Usage: pnpm patch @ note If you want to change the dependencies of a package, don't use patching to modify the `package.json` file of the package. For overriding dependencies, use [overrides](https://pnpm.io/9.x/package_json#pnpmoverrides) or a [package hook](https://pnpm.io/9.x/pnpmfile#hooksreadpackagepkg-context-pkg--promisepkg) . Options[​](https://pnpm.io/9.x/cli/patch#options "Direct link to Options") --------------------------------------------------------------------------- ### \--edit-dir [​](https://pnpm.io/9.x/cli/patch#--edit-dir-dir "Direct link to --edit-dir ") The package that needs to be patched will be extracted to this directory. ### \--ignore-existing[​](https://pnpm.io/9.x/cli/patch#--ignore-existing "Direct link to --ignore-existing") Ignore existing patch files when patching. * [Options](https://pnpm.io/9.x/cli/patch#options) * [\--edit-dir ](https://pnpm.io/9.x/cli/patch#--edit-dir-dir) * [\--ignore-existing](https://pnpm.io/9.x/cli/patch#--ignore-existing) --- # pnpm outdated | pnpm [Skip to main content](https://pnpm.io/9.x/cli/outdated#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/outdated) ** (10.x). Version: 9.x On this page Checks for outdated packages. The check can be limited to a subset of the installed packages by providing arguments (patterns are supported). Examples: pnpm outdatedpnpm outdated "*gulp-*" @babel/core Options[​](https://pnpm.io/9.x/cli/outdated#options "Direct link to Options") ------------------------------------------------------------------------------ ### \--recursive, -r[​](https://pnpm.io/9.x/cli/outdated#--recursive--r "Direct link to --recursive, -r") Check for outdated dependencies in every package found in subdirectories, or in every workspace package when executed inside a workspace. ### \--filter [​](https://pnpm.io/9.x/cli/outdated#--filter-package_selector "Direct link to --filter ") [Read more about filtering.](https://pnpm.io/9.x/filtering) ### \--global, -g[​](https://pnpm.io/9.x/cli/outdated#--global--g "Direct link to --global, -g") List outdated global packages. ### \--long[​](https://pnpm.io/9.x/cli/outdated#--long "Direct link to --long") Print details. ### \--format [​](https://pnpm.io/9.x/cli/outdated#--format-format "Direct link to --format ") * Default: **table** * Type: **table**, **list**, **json** Prints the outdated dependencies in the given format. ### \--compatible[​](https://pnpm.io/9.x/cli/outdated#--compatible "Direct link to --compatible") Prints only versions that satisfy specifications in `package.json`. ### \--dev, -D[​](https://pnpm.io/9.x/cli/outdated#--dev--d "Direct link to --dev, -D") Checks only `devDependencies`. ### \--prod, -P[​](https://pnpm.io/9.x/cli/outdated#--prod--p "Direct link to --prod, -P") Checks only `dependencies` and `optionalDependencies`. ### \--no-optional[​](https://pnpm.io/9.x/cli/outdated#--no-optional "Direct link to --no-optional") Doesn't check `optionalDependencies`. ### \--sort-by[​](https://pnpm.io/9.x/cli/outdated#--sort-by "Direct link to --sort-by") Added in: v9.12.0 Specifies the order in which the output results are sorted. Currently only the value `name` is accepted. * [Options](https://pnpm.io/9.x/cli/outdated#options) * [\--recursive, -r](https://pnpm.io/9.x/cli/outdated#--recursive--r) * [\--filter ](https://pnpm.io/9.x/cli/outdated#--filter-package_selector) * [\--global, -g](https://pnpm.io/9.x/cli/outdated#--global--g) * [\--long](https://pnpm.io/9.x/cli/outdated#--long) * [\--format ](https://pnpm.io/9.x/cli/outdated#--format-format) * [\--compatible](https://pnpm.io/9.x/cli/outdated#--compatible) * [\--dev, -D](https://pnpm.io/9.x/cli/outdated#--dev--d) * [\--prod, -P](https://pnpm.io/9.x/cli/outdated#--prod--p) * [\--no-optional](https://pnpm.io/9.x/cli/outdated#--no-optional) * [\--sort-by](https://pnpm.io/9.x/cli/outdated#--sort-by) --- # pnpm pack | pnpm [Skip to main content](https://pnpm.io/9.x/cli/pack#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/pack) ** (10.x). Version: 9.x On this page Create a tarball from a package. Options[​](https://pnpm.io/9.x/cli/pack#options "Direct link to Options") -------------------------------------------------------------------------- ### \--out [​](https://pnpm.io/9.x/cli/pack#--out-path "Direct link to --out ") Customizes the output path for the tarball. Use `%s` and `%v` to include the package name and version, e.g., `%s.tgz` or `some-dir/%s-%v.tgz`. By default, the tarball is saved in the current working directory with the name `-.tgz`. ### \--pack-destination [​](https://pnpm.io/9.x/cli/pack#--pack-destination-dir "Direct link to --pack-destination ") Directory in which `pnpm pack` will save tarballs. The default is the current working directory. ### \--pack-gzip-level [​](https://pnpm.io/9.x/cli/pack#--pack-gzip-level-level "Direct link to --pack-gzip-level ") Specifying custom compression level. ### \--json[​](https://pnpm.io/9.x/cli/pack#--json "Direct link to --json") Added in: v9.14.1 Log output in JSON format. Life Cycle Scripts[​](https://pnpm.io/9.x/cli/pack#life-cycle-scripts "Direct link to Life Cycle Scripts") ----------------------------------------------------------------------------------------------------------- * `prepack` * `prepare` * `postpack` * [Options](https://pnpm.io/9.x/cli/pack#options) * [\--out ](https://pnpm.io/9.x/cli/pack#--out-path) * [\--pack-destination ](https://pnpm.io/9.x/cli/pack#--pack-destination-dir) * [\--pack-gzip-level ](https://pnpm.io/9.x/cli/pack#--pack-gzip-level-level) * [\--json](https://pnpm.io/9.x/cli/pack#--json) * [Life Cycle Scripts](https://pnpm.io/9.x/cli/pack#life-cycle-scripts) --- # pnpm patch-commit | pnpm [Skip to main content](https://pnpm.io/9.x/cli/patch-commit#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/patch-commit) ** (10.x). Version: 9.x On this page Generate a patch out of a directory and save it (inspired by a similar command in Yarn). This command will compare the changes from `path` to the package it was supposed to patch, generate a patch file, save the a patch file to `patchesDir` (which can be customized by the `--patches-dir` option), and add an entry to `patchesDependencies` in the top level manifest file. Usage: pnpm patch-commit * `path` is the path to a modified copy of the patch target package, it is usually a temporary directory generated by [`pnpm patch`](https://pnpm.io/9.x/cli/patch) . Options[​](https://pnpm.io/9.x/cli/patch-commit#options "Direct link to Options") ---------------------------------------------------------------------------------- ### \---patches-dir [​](https://pnpm.io/9.x/cli/patch-commit#---patches-dir-patchesdir "Direct link to ---patches-dir ") The generated patch file will be saved to this directory. By default, patches are saved to the `patches` directory in the root of the project. * [Options](https://pnpm.io/9.x/cli/patch-commit#options) * [\---patches-dir ](https://pnpm.io/9.x/cli/patch-commit#---patches-dir-patchesdir) --- # pnpm patch-remove | pnpm [Skip to main content](https://pnpm.io/9.x/cli/patch-remove#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/patch-remove) ** (10.x). Version: 9.x Remove existing patch files and settings in `pnpm.patchedDependencies`. pnpm patch-remove foo@1.0.0 bar@1.0.1 --- # pnpm prune | pnpm [Skip to main content](https://pnpm.io/9.x/cli/prune#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/prune) ** (10.x). Version: 9.x On this page Removes unnecessary packages. Options[​](https://pnpm.io/9.x/cli/prune#options "Direct link to Options") --------------------------------------------------------------------------- ### \--prod[​](https://pnpm.io/9.x/cli/prune#--prod "Direct link to --prod") Remove the packages specified in `devDependencies`. ### \--no-optional[​](https://pnpm.io/9.x/cli/prune#--no-optional "Direct link to --no-optional") Remove the packages specified in `optionalDependencies`. warning The prune command does not support recursive execution on a monorepo currently. To only install production-dependencies in a monorepo `node_modules` folders can be deleted and then re-installed with `pnpm install --prod`. * [Options](https://pnpm.io/9.x/cli/prune#options) * [\--prod](https://pnpm.io/9.x/cli/prune#--prod) * [\--no-optional](https://pnpm.io/9.x/cli/prune#--no-optional) --- # pnpm root | pnpm [Skip to main content](https://pnpm.io/9.x/cli/root#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/root) ** (10.x). Version: 9.x On this page Prints the effective modules directory. Options[​](https://pnpm.io/9.x/cli/root#options "Direct link to Options") -------------------------------------------------------------------------- ### \--global, -g[​](https://pnpm.io/9.x/cli/root#--global--g "Direct link to --global, -g") The global package's modules directory is printed. * [Options](https://pnpm.io/9.x/cli/root#options) * [\--global, -g](https://pnpm.io/9.x/cli/root#--global--g) --- # pnpm run | pnpm [Skip to main content](https://pnpm.io/9.x/cli/run#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/run) ** (10.x). Version: 9.x On this page Aliases: `run-script` Runs a script defined in the package's manifest file. Examples[​](https://pnpm.io/9.x/cli/run#examples "Direct link to Examples") ---------------------------------------------------------------------------- Let's say you have a `watch` script configured in your `package.json`, like so: "scripts": { "watch": "webpack --watch"} You can now run that script by using `pnpm run watch`! Simple, right? Another thing to note for those that like to save keystrokes and time is that all scripts get aliased in as pnpm commands, so ultimately `pnpm watch` is just shorthand for `pnpm run watch` (ONLY for scripts that do not share the same name as already existing pnpm commands). Running multiple scripts[​](https://pnpm.io/9.x/cli/run#running-multiple-scripts "Direct link to Running multiple scripts") ---------------------------------------------------------------------------------------------------------------------------- You may run multiple scripts at the same time by using a regex instead of the script name. pnpm run "//" Run all scripts that start with `watch:`: pnpm run "/^watch:.*/" Details[​](https://pnpm.io/9.x/cli/run#details "Direct link to Details") ------------------------------------------------------------------------- In addition to the shell’s pre-existing `PATH`, `pnpm run` includes `node_modules/.bin` in the `PATH` provided to `scripts`. This means that so long as you have a package installed, you can use it in a script like a regular command. For example, if you have `eslint` installed, you can write up a script like so: "lint": "eslint src --fix" And even though `eslint` is not installed globally in your shell, it will run. For workspaces, `/node_modules/.bin` is also added to the `PATH`, so if a tool is installed in the workspace root, it may be called in any workspace package's `scripts`. Environment[​](https://pnpm.io/9.x/cli/run#environment "Direct link to Environment") ------------------------------------------------------------------------------------- There are some environment variables that pnpm automatically creates for the executed scripts. These environment variables may be used to get contextual information about the running process. These are the environment variables created by pnpm: * **npm\_command** - contains the name of the executed command. If the executed command is `pnpm run`, then the value of this variable will be "run-script". Options[​](https://pnpm.io/9.x/cli/run#options "Direct link to Options") ------------------------------------------------------------------------- Any options for the `run` command should be listed before the script's name. Options listed after the script's name are passed to the executed script. All these will run pnpm CLI with the `--silent` option: pnpm run --silent watchpnpm --silent run watchpnpm --silent watch Any arguments after the command's name are added to the executed script. So if `watch` runs `webpack --watch`, then this command: pnpm run watch --no-color will run: webpack --watch --no-color ### \--recursive, -r[​](https://pnpm.io/9.x/cli/run#--recursive--r "Direct link to --recursive, -r") This runs an arbitrary command from each package's "scripts" object. If a package doesn't have the command, it is skipped. If none of the packages have the command, the command fails. ### \--if-present[​](https://pnpm.io/9.x/cli/run#--if-present "Direct link to --if-present") You can use the `--if-present` flag to avoid exiting with a non-zero exit code when the script is undefined. This lets you run potentially undefined scripts without breaking the execution chain. ### \--parallel[​](https://pnpm.io/9.x/cli/run#--parallel "Direct link to --parallel") Completely disregard concurrency and topological sorting, running a given script immediately in all matching packages with prefixed streaming output. This is the preferred flag for long-running processes over many packages, for instance, a lengthy build process. ### \--stream[​](https://pnpm.io/9.x/cli/run#--stream "Direct link to --stream") Stream output from child processes immediately, prefixed with the originating package directory. This allows output from different packages to be interleaved. ### \--aggregate-output[​](https://pnpm.io/9.x/cli/run#--aggregate-output "Direct link to --aggregate-output") Aggregate output from child processes that are run in parallel, and only print output when the child process is finished. It makes reading large logs after running `pnpm -r ` with `--parallel` or with `--workspace-concurrency=` much easier (especially on CI). Only `--reporter=append-only` is supported. ### \--resume-from [​](https://pnpm.io/9.x/cli/run#--resume-from-package_name "Direct link to --resume-from ") Resume execution from a particular project. This can be useful if you are working with a large workspace and you want to restart a build at a particular project without running through all of the projects that precede it in the build order. ### \--report-summary[​](https://pnpm.io/9.x/cli/run#--report-summary "Direct link to --report-summary") Record the result of the scripts executions into a `pnpm-exec-summary.json` file. An example of a `pnpm-exec-summary.json` file: { "executionStatus": { "/Users/zoltan/src/pnpm/pnpm/cli/command": { "status": "passed", "duration": 1861.143042 }, "/Users/zoltan/src/pnpm/pnpm/cli/common-cli-options-help": { "status": "passed", "duration": 1865.914958 } } Possible values of `status` are: 'passed', 'queued', 'running'. ### \--reporter-hide-prefix[​](https://pnpm.io/9.x/cli/run#--reporter-hide-prefix "Direct link to --reporter-hide-prefix") Hide workspace prefix from output from child processes that are run in parallel, and only print the raw output. This can be useful if you are running on CI and the output must be in a specific format without any prefixes (e.g. [GitHub Actions annotations](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-error-message) ). Only `--reporter=append-only` is supported. ### \--filter [​](https://pnpm.io/9.x/cli/run#--filter-package_selector "Direct link to --filter ") [Read more about filtering.](https://pnpm.io/9.x/filtering) .npmrc settings[​](https://pnpm.io/9.x/cli/run#npmrc-settings "Direct link to .npmrc settings") ------------------------------------------------------------------------------------------------ ### enable-pre-post-scripts[​](https://pnpm.io/9.x/cli/run#enable-pre-post-scripts "Direct link to enable-pre-post-scripts") * Default: **true** * Type: **Boolean** When `true`, pnpm will run any pre/post scripts automatically. So running `pnpm foo` will be like running `pnpm prefoo && pnpm foo && pnpm postfoo`. ### script-shell[​](https://pnpm.io/9.x/cli/run#script-shell "Direct link to script-shell") * Default: **null** * Type: **path** The shell to use for scripts run with the `pnpm run` command. For instance, to force usage of Git Bash on Windows: pnpm config set script-shell "C:\\Program Files\\git\\bin\\bash.exe" ### shell-emulator[​](https://pnpm.io/9.x/cli/run#shell-emulator "Direct link to shell-emulator") * Default: **false** * Type: **Boolean** When `true`, pnpm will use a JavaScript implementation of a [bash-like shell](https://www.npmjs.com/package/@yarnpkg/shell) to execute scripts. This option simplifies cross-platform scripting. For instance, by default, the next script will fail on non-POSIX-compliant systems: "scripts": { "test": "NODE_ENV=test node test.js"} But if the `shell-emulator` setting is set to `true`, it will work on all platforms. * [Examples](https://pnpm.io/9.x/cli/run#examples) * [Running multiple scripts](https://pnpm.io/9.x/cli/run#running-multiple-scripts) * [Details](https://pnpm.io/9.x/cli/run#details) * [Environment](https://pnpm.io/9.x/cli/run#environment) * [Options](https://pnpm.io/9.x/cli/run#options) * [\--recursive, -r](https://pnpm.io/9.x/cli/run#--recursive--r) * [\--if-present](https://pnpm.io/9.x/cli/run#--if-present) * [\--parallel](https://pnpm.io/9.x/cli/run#--parallel) * [\--stream](https://pnpm.io/9.x/cli/run#--stream) * [\--aggregate-output](https://pnpm.io/9.x/cli/run#--aggregate-output) * [\--resume-from ](https://pnpm.io/9.x/cli/run#--resume-from-package_name) * [\--report-summary](https://pnpm.io/9.x/cli/run#--report-summary) * [\--reporter-hide-prefix](https://pnpm.io/9.x/cli/run#--reporter-hide-prefix) * [\--filter ](https://pnpm.io/9.x/cli/run#--filter-package_selector) * [.npmrc settings](https://pnpm.io/9.x/cli/run#npmrc-settings) * [enable-pre-post-scripts](https://pnpm.io/9.x/cli/run#enable-pre-post-scripts) * [script-shell](https://pnpm.io/9.x/cli/run#script-shell) * [shell-emulator](https://pnpm.io/9.x/cli/run#shell-emulator) --- # pnpm self-update | pnpm [Skip to main content](https://pnpm.io/9.x/cli/self-update#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/self-update) ** (10.x). Version: 9.x Updates pnpm to the latest version or the one specified. Usage examples: pnpm self-updatepnpm self-update 9pnpm self-update next-10pnpm self-update 9.10.0 --- # pnpm start | pnpm [Skip to main content](https://pnpm.io/9.x/cli/start#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/start) ** (10.x). Version: 9.x Aliases: `run start` Runs an arbitrary command specified in the package's `start` property of its `scripts` object. If no `start` property is specified on the `scripts` object, it will attempt to run `node server.js` as a default, failing if neither are present. The intended usage of the property is to specify a command that starts your program. --- # pnpm server | pnpm [Skip to main content](https://pnpm.io/9.x/cli/server#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/server) ** (10.x). Version: 9.x On this page danger Deprecated feature Manage a store server. Commands[​](https://pnpm.io/9.x/cli/server#commands "Direct link to Commands") ------------------------------------------------------------------------------- ### pnpm server start[​](https://pnpm.io/9.x/cli/server#pnpm-server-start "Direct link to pnpm server start") Starts a server that performs all interactions with the store. Other commands will delegate any store-related tasks to this server. ### pnpm server stop[​](https://pnpm.io/9.x/cli/server#pnpm-server-stop "Direct link to pnpm server stop") Stops the store server. ### pnpm server status[​](https://pnpm.io/9.x/cli/server#pnpm-server-status "Direct link to pnpm server status") Prints information about the running server. Options[​](https://pnpm.io/9.x/cli/server#options "Direct link to Options") ---------------------------------------------------------------------------- ### \--background[​](https://pnpm.io/9.x/cli/server#--background "Direct link to --background") * Default: **false** * Type: **Boolean** Runs the server in the background, similar to daemonizing on UNIX systems. ### \--network-concurrency[​](https://pnpm.io/9.x/cli/server#--network-concurrency "Direct link to --network-concurrency") * Default: **null** * Type: **Number** The maximum number of network requests to process simultaneously. ### \--protocol[​](https://pnpm.io/9.x/cli/server#--protocol "Direct link to --protocol") * Default: **auto** * Type: **auto**, **tcp**, **ipc** The communication protocol used by the server. When this is set to `auto`, IPC is used on all systems except for Windows, which uses TCP. ### \--port[​](https://pnpm.io/9.x/cli/server#--port "Direct link to --port") * Default: **5813** * Type: **port number** The port number to use when TCP is used for communication. If a port is specified and the protocol is set to `auto`, regardless of system type, the protocol is automatically set to use TCP. ### \--store-dir[​](https://pnpm.io/9.x/cli/server#--store-dir "Direct link to --store-dir") * Default: **/.pnpm-store** * Type: **Path** The directory to use for the content addressable store. ### \--\[no-\]lock[​](https://pnpm.io/9.x/cli/server#--no-lock "Direct link to --[no-]lock") * Default: **false** * Type: **Boolean** Set whether to make the package store immutable to external processes while the server is running or not. ### \--ignore-stop-requests[​](https://pnpm.io/9.x/cli/server#--ignore-stop-requests "Direct link to --ignore-stop-requests") * Default: **false** * Type: **Boolean** Prevents you from stopping the server using `pnpm server stop`. ### \--ignore-upload-requests[​](https://pnpm.io/9.x/cli/server#--ignore-upload-requests "Direct link to --ignore-upload-requests") * Default: **false** * Type: **Boolean** Prevents creating a new side effect cache during install. * [Commands](https://pnpm.io/9.x/cli/server#commands) * [pnpm server start](https://pnpm.io/9.x/cli/server#pnpm-server-start) * [pnpm server stop](https://pnpm.io/9.x/cli/server#pnpm-server-stop) * [pnpm server status](https://pnpm.io/9.x/cli/server#pnpm-server-status) * [Options](https://pnpm.io/9.x/cli/server#options) * [\--background](https://pnpm.io/9.x/cli/server#--background) * [\--network-concurrency](https://pnpm.io/9.x/cli/server#--network-concurrency) * [\--protocol](https://pnpm.io/9.x/cli/server#--protocol) * [\--port](https://pnpm.io/9.x/cli/server#--port) * [\--store-dir](https://pnpm.io/9.x/cli/server#--store-dir) * [\--\[no-\]lock](https://pnpm.io/9.x/cli/server#--no-lock) * [\--ignore-stop-requests](https://pnpm.io/9.x/cli/server#--ignore-stop-requests) * [\--ignore-upload-requests](https://pnpm.io/9.x/cli/server#--ignore-upload-requests) --- # pnpm setup | pnpm [Skip to main content](https://pnpm.io/9.x/cli/setup#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/setup) ** (10.x). Version: 9.x This command is used by the standalone installation scripts of pnpm. For instance, in [https://get.pnpm.io/install.sh](https://get.pnpm.io/install.sh) . Setup does the following actions: * creates a home directory for the pnpm CLI * adds the pnpm home directory to the `PATH` by updating the shell configuration file * copies the pnpm executable to the pnpm home directory --- # pnpm test | pnpm [Skip to main content](https://pnpm.io/9.x/cli/test#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/test) ** (10.x). Version: 9.x Aliases: `run test`, `t`, `tst` Runs an arbitrary command specified in the package's `test` property of its `scripts` object. The intended usage of the property is to specify a command that runs unit or integration testing for your program. --- # pnpm store | pnpm [Skip to main content](https://pnpm.io/9.x/cli/store#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/store) ** (10.x). Version: 9.x On this page Managing the package store. Commands[​](https://pnpm.io/9.x/cli/store#commands "Direct link to Commands") ------------------------------------------------------------------------------ ### status[​](https://pnpm.io/9.x/cli/store#status "Direct link to status") Checks for modified packages in the store. Returns exit code 0 if the content of the package is the same as it was at the time of unpacking. ### add[​](https://pnpm.io/9.x/cli/store#add "Direct link to add") Functionally equivalent to [`pnpm add`](https://pnpm.io/9.x/cli/add) , except this adds new packages to the store directly without modifying any projects or files outside of the store. ### prune[​](https://pnpm.io/9.x/cli/store#prune "Direct link to prune") Removes _unreferenced packages_ from the store. Unreferenced packages are packages that are not used by any projects on the system. Packages can become unreferenced after most installation operations, for instance when dependencies are made redundant. For example, during `pnpm install`, package `foo@1.0.0` is updated to `foo@1.0.1`. pnpm will keep `foo@1.0.0` in the store, as it does not automatically remove packages. If package `foo@1.0.0` is not used by any other project on the system, it becomes unreferenced. Running `pnpm store prune` would remove `foo@1.0.0` from the store. Running `pnpm store prune` is not harmful and has no side effects on your projects. If future installations require removed packages, pnpm will download them again. It is best practice to run `pnpm store prune` occasionally to clean up the store, but not too frequently. Sometimes, unreferenced packages become required again. This could occur when switching branches and installing older dependencies, in which case pnpm would need to re-download all removed packages, briefly slowing down the installation process. Please note that this command is prohibited when a [store server](https://pnpm.io/9.x/cli/server) is running. ### path[​](https://pnpm.io/9.x/cli/store#path "Direct link to path") Returns the path to the active store directory. * [Commands](https://pnpm.io/9.x/cli/store#commands) * [status](https://pnpm.io/9.x/cli/store#status) * [add](https://pnpm.io/9.x/cli/store#add) * [prune](https://pnpm.io/9.x/cli/store#prune) * [path](https://pnpm.io/9.x/cli/store#path) --- # Command line tab-completion | pnpm [Skip to main content](https://pnpm.io/9.x/completion#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/completion) ** (10.x). Version: 9.x On this page info Completion for pnpm v9 is incompatible with completion for older pnpm versions. If you have already installed pnpm completion for a version older than v9, you must uninstall it first to ensure that completion for v9 works properly. You can do this by removing the section of code that contains `__tabtab` in your dot files. Unlike other popular package managers, which usually require plugins, pnpm supports command line tab-completion for Bash, Zsh, Fish, and similar shells. To setup autocompletion for Bash, run: pnpm completion bash > ~/completion-for-pnpm.bashecho 'source ~/completion-for-pnpm.bash' >> ~/.bashrc To setup autocompletion for Fish, run: pnpm completion fish > ~/.config/fish/completions/pnpm.fish g-plane/pnpm-shell-completion[​](https://pnpm.io/9.x/completion#g-planepnpm-shell-completion "Direct link to g-plane/pnpm-shell-completion") --------------------------------------------------------------------------------------------------------------------------------------------- [pnpm-shell-completion](https://github.com/g-plane/pnpm-shell-completion) is a shell plugin maintained by Pig Fang on Github. Features: * Provide completion for `pnpm --filter `. * Provide completion for `pnpm remove` command, even in workspace's packages (by specifying `--filter` option). * Provide completion for scripts in `package.json`. * [g-plane/pnpm-shell-completion](https://pnpm.io/9.x/completion#g-planepnpm-shell-completion) --- # pnpm why | pnpm [Skip to main content](https://pnpm.io/9.x/cli/why#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/why) ** (10.x). Version: 9.x On this page Shows all packages that depend on the specified package. caution If the Dependencies Tree has more than 10 results (end leaves), the output will be truncated to 10 end leaves. This makes the output more readable and avoids memory issues. Options[​](https://pnpm.io/9.x/cli/why#options "Direct link to Options") ------------------------------------------------------------------------- ### \--recursive, -r[​](https://pnpm.io/9.x/cli/why#--recursive--r "Direct link to --recursive, -r") Show the dependency tree for the specified package on every package in subdirectories or on every workspace package when executed inside a workspace. ### \--json[​](https://pnpm.io/9.x/cli/why#--json "Direct link to --json") Show information in JSON format. ### \--long[​](https://pnpm.io/9.x/cli/why#--long "Direct link to --long") Show verbose output. ### \--parseable[​](https://pnpm.io/9.x/cli/why#--parseable "Direct link to --parseable") Show parseable output instead of tree view. ### \--global, -g[​](https://pnpm.io/9.x/cli/why#--global--g "Direct link to --global, -g") List packages in the global install directory instead of in the current project. ### \--prod, -P[​](https://pnpm.io/9.x/cli/why#--prod--p "Direct link to --prod, -P") Only display the dependency tree for packages in `dependencies`. ### \--dev, -D[​](https://pnpm.io/9.x/cli/why#--dev--d "Direct link to --dev, -D") Only display the dependency tree for packages in `devDependencies`. ### \--depth [​](https://pnpm.io/9.x/cli/why#--depth-number "Direct link to --depth ") Display only dependencies within a specific depth. ### \--only-projects[​](https://pnpm.io/9.x/cli/why#--only-projects "Direct link to --only-projects") Display only dependencies that are also projects within the workspace. ### \--exclude-peers[​](https://pnpm.io/9.x/cli/why#--exclude-peers "Direct link to --exclude-peers") Added in: v9.10.0 Exclude peer dependencies from the results (but dependencies of peer dependencies are not ignored). ### \--filter [​](https://pnpm.io/9.x/cli/why#--filter-package_selector "Direct link to --filter ") [Read more about filtering.](https://pnpm.io/9.x/filtering) * [Options](https://pnpm.io/9.x/cli/why#options) * [\--recursive, -r](https://pnpm.io/9.x/cli/why#--recursive--r) * [\--json](https://pnpm.io/9.x/cli/why#--json) * [\--long](https://pnpm.io/9.x/cli/why#--long) * [\--parseable](https://pnpm.io/9.x/cli/why#--parseable) * [\--global, -g](https://pnpm.io/9.x/cli/why#--global--g) * [\--prod, -P](https://pnpm.io/9.x/cli/why#--prod--p) * [\--dev, -D](https://pnpm.io/9.x/cli/why#--dev--d) * [\--depth ](https://pnpm.io/9.x/cli/why#--depth-number) * [\--only-projects](https://pnpm.io/9.x/cli/why#--only-projects) * [\--exclude-peers](https://pnpm.io/9.x/cli/why#--exclude-peers) * [\--filter ](https://pnpm.io/9.x/cli/why#--filter-package_selector) --- # pnpm unlink | pnpm [Skip to main content](https://pnpm.io/9.x/cli/unlink#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/unlink) ** (10.x). Version: 9.x On this page Unlinks a system-wide package (inverse of [`pnpm link`](https://pnpm.io/9.x/cli/link) ). If called without arguments, all linked dependencies will be unlinked inside the current project. This is similar to `yarn unlink`, except pnpm re-installs the dependency after removing the external link. info If you want to remove a link made with `pnpm link --global `, you should use `pnpm uninstall --global `. `pnpm unlink` only removes the links in your current directory. Options[​](https://pnpm.io/9.x/cli/unlink#options "Direct link to Options") ---------------------------------------------------------------------------- ### \--recursive, -r[​](https://pnpm.io/9.x/cli/unlink#--recursive--r "Direct link to --recursive, -r") Unlink in every package found in subdirectories or in every workspace package, when executed inside a [workspace](https://pnpm.io/9.x/workspaces) . ### \--filter [​](https://pnpm.io/9.x/cli/unlink#--filter-package_selector "Direct link to --filter ") [Read more about filtering.](https://pnpm.io/9.x/filtering) * [Options](https://pnpm.io/9.x/cli/unlink#options) * [\--recursive, -r](https://pnpm.io/9.x/cli/unlink#--recursive--r) * [\--filter ](https://pnpm.io/9.x/cli/unlink#--filter-package_selector) --- # pnpm update | pnpm [Skip to main content](https://pnpm.io/9.x/cli/update#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/update) ** (10.x). Version: 9.x On this page Aliases: `up`, `upgrade` `pnpm update` updates packages to their latest version based on the specified range. When used without arguments, updates all dependencies. TL;DR[​](https://pnpm.io/9.x/cli/update#tldr "Direct link to TL;DR") --------------------------------------------------------------------- | Command | Meaning | | --- | --- | | `pnpm up` | Updates all dependencies, adhering to ranges specified in `package.json` | | `pnpm up --latest` | Updates all dependencies to their latest versions | | `pnpm up foo@2` | Updates `foo` to the latest version on v2 | | `pnpm up "@babel/*"` | Updates all dependencies under the `@babel` scope | Selecting dependencies with patterns[​](https://pnpm.io/9.x/cli/update#selecting-dependencies-with-patterns "Direct link to Selecting dependencies with patterns") ------------------------------------------------------------------------------------------------------------------------------------------------------------------- You can use patterns to update specific dependencies. Update all `babel` packages: pnpm update "@babel/*" Update all dependencies, except `webpack`: pnpm update "\!webpack" Patterns may also be combined, so the next command will update all `babel` packages, except `core`: pnpm update "@babel/*" "\!@babel/core" Options[​](https://pnpm.io/9.x/cli/update#options "Direct link to Options") ---------------------------------------------------------------------------- ### \--recursive, -r[​](https://pnpm.io/9.x/cli/update#--recursive--r "Direct link to --recursive, -r") Concurrently runs update in all subdirectories with a `package.json` (excluding node\_modules). Usage examples: pnpm --recursive update# updates all packages up to 100 subdirectories in depthpnpm --recursive update --depth 100# update typescript to the latest version in every packagepnpm --recursive update typescript@latest ### \--latest, -L[​](https://pnpm.io/9.x/cli/update#--latest--l "Direct link to --latest, -L") Update the dependencies to their latest stable version as determined by their `latest` tags (potentially upgrading the packages across major versions) as long as the version range specified in `package.json` is lower than the `latest` tag (i.e. it will not downgrade prereleases). ### \--global, -g[​](https://pnpm.io/9.x/cli/update#--global--g "Direct link to --global, -g") Update global packages. ### \--workspace[​](https://pnpm.io/9.x/cli/update#--workspace "Direct link to --workspace") Tries to link all packages from the workspace. Versions are updated to match the versions of packages inside the workspace. If specific packages are updated, the command will fail if any of the updated dependencies are not found inside the workspace. For instance, the following command fails if `express` is not a workspace package: pnpm up -r --workspace express ### \--prod, -P[​](https://pnpm.io/9.x/cli/update#--prod--p "Direct link to --prod, -P") Only update packages in `dependencies` and `optionalDependencies`. ### \--dev, -D[​](https://pnpm.io/9.x/cli/update#--dev--d "Direct link to --dev, -D") Only update packages in `devDependencies`. ### \--no-optional[​](https://pnpm.io/9.x/cli/update#--no-optional "Direct link to --no-optional") Don't update packages in `optionalDependencies`. ### \--interactive, -i[​](https://pnpm.io/9.x/cli/update#--interactive--i "Direct link to --interactive, -i") Show outdated dependencies and select which ones to update. ### \--no-save[​](https://pnpm.io/9.x/cli/update#--no-save "Direct link to --no-save") Don't update the ranges in `package.json`. ### \--filter [​](https://pnpm.io/9.x/cli/update#--filter-package_selector "Direct link to --filter ") [Read more about filtering.](https://pnpm.io/9.x/filtering) * [TL;DR](https://pnpm.io/9.x/cli/update#tldr) * [Selecting dependencies with patterns](https://pnpm.io/9.x/cli/update#selecting-dependencies-with-patterns) * [Options](https://pnpm.io/9.x/cli/update#options) * [\--recursive, -r](https://pnpm.io/9.x/cli/update#--recursive--r) * [\--latest, -L](https://pnpm.io/9.x/cli/update#--latest--l) * [\--global, -g](https://pnpm.io/9.x/cli/update#--global--g) * [\--workspace](https://pnpm.io/9.x/cli/update#--workspace) * [\--prod, -P](https://pnpm.io/9.x/cli/update#--prod--p) * [\--dev, -D](https://pnpm.io/9.x/cli/update#--dev--d) * [\--no-optional](https://pnpm.io/9.x/cli/update#--no-optional) * [\--interactive, -i](https://pnpm.io/9.x/cli/update#--interactive--i) * [\--no-save](https://pnpm.io/9.x/cli/update#--no-save) * [\--filter ](https://pnpm.io/9.x/cli/update#--filter-package_selector) --- # Configuring | pnpm [Skip to main content](https://pnpm.io/9.x/configuring#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/configuring) ** (10.x). Version: 9.x pnpm uses [npm's configuration](https://docs.npmjs.com/misc/config) formats. Hence, you should set configuration the same way you would for npm. For example, pnpm config set store-dir /path/to/.pnpm-store If no store is configured, then pnpm will automatically create a store on the same drive. If you need pnpm to work across multiple hard drives or filesystems, please read [the FAQ](https://pnpm.io/9.x/faq#does-pnpm-work-across-multiple-hard-drives-or-filesystems) . Furthermore, pnpm uses the same configuration that npm uses for doing installations. If you have a private registry and npm is configured to work with it, pnpm should be able to authorize requests as well, with no additional configuration. In addition to those options, pnpm also allows you to use all parameters that are flags (for example `--filter` or `--workspace-concurrency`) as options: workspace-concurrency = 1filter = @my-scope/* See the [`config` command](https://pnpm.io/9.x/cli/config) for more information. --- # Frequently Asked Questions | pnpm [Skip to main content](https://pnpm.io/9.x/faq#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/faq) ** (10.x). Version: 9.x On this page Why does my `node_modules` folder use disk space if packages are stored in a global store?[​](https://pnpm.io/9.x/faq#why-does-my-node_modules-folder-use-disk-space-if-packages-are-stored-in-a-global-store "Direct link to why-does-my-node_modules-folder-use-disk-space-if-packages-are-stored-in-a-global-store") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ pnpm creates [hard links](https://en.wikipedia.org/wiki/Hard_link) from the global store to the project's `node_modules` folders. Hard links point to the same place on the disk where the original files are. So, for example, if you have `foo` in your project as a dependency and it occupies 1MB of space, then it will look like it occupies 1MB of space in the project's `node_modules` folder and the same amount of space in the global store. However, that 1MB is _the same space_ on the disk addressed from two different locations. So in total `foo` occupies 1MB, not 2MB. For more on this subject: * [Why do hard links seem to take the same space as the originals?](https://unix.stackexchange.com/questions/88423/why-do-hard-links-seem-to-take-the-same-space-as-the-originals) * [A thread from the pnpm chat room](https://gist.github.com/zkochan/106cfef49f8476b753a9cbbf9c65aff1) * [An issue in the pnpm repo](https://github.com/pnpm/pnpm/issues/794) Does it work on Windows?[​](https://pnpm.io/9.x/faq#does-it-work-on-windows "Direct link to Does it work on Windows?") ----------------------------------------------------------------------------------------------------------------------- Short answer: Yes. Long answer: Using symbolic linking on Windows is problematic to say the least, however, pnpm has a workaround. For Windows, we use [junctions](https://docs.microsoft.com/en-us/windows/win32/fileio/hard-links-and-junctions) instead. But the nested `node_modules` approach is incompatible with Windows?[​](https://pnpm.io/9.x/faq#but-the-nested-node_modules-approach-is-incompatible-with-windows "Direct link to but-the-nested-node_modules-approach-is-incompatible-with-windows") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Early versions of npm had issues because of nesting all `node_modules` (see [this issue](https://github.com/nodejs/node-v0.x-archive/issues/6960) ). However, pnpm does not create deep folders, it stores all packages flatly and uses symbolic links to create the dependency tree structure. What about circular symlinks?[​](https://pnpm.io/9.x/faq#what-about-circular-symlinks "Direct link to What about circular symlinks?") -------------------------------------------------------------------------------------------------------------------------------------- Although pnpm uses linking to put dependencies into `node_modules` folders, circular symlinks are avoided because parent packages are placed into the same `node_modules` folder in which their dependencies are. So `foo`'s dependencies are not in `foo/node_modules`, but `foo` is in `node_modules` together with its own dependencies. Why have hard links at all? Why not symlink directly to the global store?[​](https://pnpm.io/9.x/faq#why-have-hard-links-at-all-why-not-symlink-directly-to-the-global-store "Direct link to Why have hard links at all? Why not symlink directly to the global store?") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- One package can have different sets of dependencies on one machine. In project **A** `foo@1.0.0` can have a dependency resolved to `bar@1.0.0`, but in project **B** the same dependency of `foo` might resolve to `bar@1.1.0`; so, pnpm hard links `foo@1.0.0` to every project where it is used, in order to create different sets of dependencies for it. Direct symlinking to the global store would work with Node's `--preserve-symlinks` flag, however, that approach comes with a plethora of its own issues, so we decided to stick with hard links. For more details about why this decision was made, see [this issue](https://github.com/nodejs/node-eps/issues/46) . Does pnpm work across different subvolumes in one Btrfs partition?[​](https://pnpm.io/9.x/faq#does-pnpm-work-across-different-subvolumes-in-one-btrfs-partition "Direct link to Does pnpm work across different subvolumes in one Btrfs partition?") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- While Btrfs does not allow cross-device hardlinks between different subvolumes in a single partition, it does permit reflinks. As a result, pnpm utilizes reflinks to share data between these subvolumes. Does pnpm work across multiple drives or filesystems?[​](https://pnpm.io/9.x/faq#does-pnpm-work-across-multiple-drives-or-filesystems "Direct link to Does pnpm work across multiple drives or filesystems?") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The package store should be on the same drive and filesystem as installations, otherwise packages will be copied, not linked. This is due to a limitation in how hard linking works, in that a file on one filesystem cannot address a location in another. See [Issue #712](https://github.com/pnpm/pnpm/issues/712) for more details. pnpm functions differently in the 2 cases below: ### Store path is specified[​](https://pnpm.io/9.x/faq#store-path-is-specified "Direct link to Store path is specified") If the store path is specified via [the store config](https://pnpm.io/9.x/configuring) , then copying occurs between the store and any projects that are on a different disk. If you run `pnpm install` on disk `A`, then the pnpm store must be on disk `A`. If the pnpm store is located on disk `B`, then all required packages will be directly copied to the project location instead of being linked. This severely inhibits the storage and performance benefits of pnpm. ### Store path is NOT specified[​](https://pnpm.io/9.x/faq#store-path-is-not-specified "Direct link to Store path is NOT specified") If the store path is not set, then multiple stores are created (one per drive or filesystem). If installation is run on disk `A`, the store will be created on `A` `.pnpm-store` under the filesystem root. If later the installation is run on disk `B`, an independent store will be created on `B` at `.pnpm-store`. The projects would still maintain the benefits of pnpm, but each drive may have redundant packages. What does `pnpm` stand for?[​](https://pnpm.io/9.x/faq#what-does-pnpm-stand-for "Direct link to what-does-pnpm-stand-for") --------------------------------------------------------------------------------------------------------------------------- `pnpm` stands for `performant npm`. [@rstacruz](https://github.com/rstacruz/) came up with the name. `pnpm` does not work with ?[​](https://pnpm.io/9.x/faq#pnpm-does-not-work-with-your-project-here "Direct link to pnpm-does-not-work-with-your-project-here") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- In most cases it means that one of the dependencies require packages not declared in `package.json`. It is a common mistake caused by flat `node_modules`. If this happens, this is an error in the dependency and the dependency should be fixed. That might take time though, so pnpm supports workarounds to make the buggy packages work. ### Solution 1[​](https://pnpm.io/9.x/faq#solution-1 "Direct link to Solution 1") In case there are issues, you can use the [`node-linker=hoisted`](https://pnpm.io/9.x/npmrc#node-linker) setting. This creates a flat `node_modules` structure similar to the one created by `npm`. ### Solution 2[​](https://pnpm.io/9.x/faq#solution-2 "Direct link to Solution 2") In the following example, a dependency does **not** have the `iterall` module in its own list of deps. The easiest solution to resolve missing dependencies of the buggy packages is to **add `iterall` as a dependency to our project's `package.json`**. You can do so, by installing it via `pnpm add iterall`, and will be automatically added to your project's `package.json`. "dependencies": { ... "iterall": "^1.2.2", ... } ### Solution 3[​](https://pnpm.io/9.x/faq#solution-3 "Direct link to Solution 3") One of the solutions is to use [hooks](https://pnpm.io/9.x/pnpmfile#hooks) for adding the missing dependencies to the package's `package.json`. An example was [Webpack Dashboard](https://github.com/pnpm/pnpm/issues/1043) which wasn't working with `pnpm`. It has since been resolved such that it works with `pnpm` now. It used to throw an error: Error: Cannot find module 'babel-traverse' at /node_modules/inspectpack@2.2.3/node_modules/inspectpack/lib/actions/parse The problem was that `babel-traverse` was used in `inspectpack` which was used by `webpack-dashboard`, but `babel-traverse` wasn't specified in `inspectpack`'s `package.json`. It still worked with `npm` and `yarn` because they create flat `node_modules`. The solution was to create a `.pnpmfile.cjs` with the following contents: module.exports = { hooks: { readPackage: (pkg) => { if (pkg.name === "inspectpack") { pkg.dependencies['babel-traverse'] = '^6.26.0'; } return pkg; } }}; After creating a `.pnpmfile.cjs`, delete `pnpm-lock.yaml` only - there is no need to delete `node_modules`, as pnpm hooks only affect module resolution. Then, rebuild the dependencies & it should be working. * [Why does my `node_modules` folder use disk space if packages are stored in a global store?](https://pnpm.io/9.x/faq#why-does-my-node_modules-folder-use-disk-space-if-packages-are-stored-in-a-global-store) * [Does it work on Windows?](https://pnpm.io/9.x/faq#does-it-work-on-windows) * [But the nested `node_modules` approach is incompatible with Windows?](https://pnpm.io/9.x/faq#but-the-nested-node_modules-approach-is-incompatible-with-windows) * [What about circular symlinks?](https://pnpm.io/9.x/faq#what-about-circular-symlinks) * [Why have hard links at all? Why not symlink directly to the global store?](https://pnpm.io/9.x/faq#why-have-hard-links-at-all-why-not-symlink-directly-to-the-global-store) * [Does pnpm work across different subvolumes in one Btrfs partition?](https://pnpm.io/9.x/faq#does-pnpm-work-across-different-subvolumes-in-one-btrfs-partition) * [Does pnpm work across multiple drives or filesystems?](https://pnpm.io/9.x/faq#does-pnpm-work-across-multiple-drives-or-filesystems) * [Store path is specified](https://pnpm.io/9.x/faq#store-path-is-specified) * [Store path is NOT specified](https://pnpm.io/9.x/faq#store-path-is-not-specified) * [What does `pnpm` stand for?](https://pnpm.io/9.x/faq#what-does-pnpm-stand-for) * [`pnpm` does not work with ?](https://pnpm.io/9.x/faq#pnpm-does-not-work-with-your-project-here) * [Solution 1](https://pnpm.io/9.x/faq#solution-1) * [Solution 2](https://pnpm.io/9.x/faq#solution-2) * [Solution 3](https://pnpm.io/9.x/faq#solution-3) --- # Continuous Integration | pnpm [Skip to main content](https://pnpm.io/9.x/continuous-integration#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/continuous-integration) ** (10.x). Version: 9.x On this page pnpm can easily be used in various continuous integration systems. note In all the provided configuration files the store is cached. However, this is not required, and it is not guaranteed that caching the store will make installation faster. So feel free to not cache the pnpm store in your job. Travis[​](https://pnpm.io/9.x/continuous-integration#travis "Direct link to Travis") ------------------------------------------------------------------------------------- On [Travis CI](https://travis-ci.org/) , you can use pnpm for installing your dependencies by adding this to your `.travis.yml` file: .travis.yml cache: npm: false directories: - "~/.pnpm-store"before_install: - corepack enable - corepack prepare pnpm@latest-9 --activate - pnpm config set store-dir ~/.pnpm-storeinstall: - pnpm install Semaphore[​](https://pnpm.io/9.x/continuous-integration#semaphore "Direct link to Semaphore") ---------------------------------------------------------------------------------------------- On [Semaphore](https://semaphoreci.com/) , you can use pnpm for installing and caching your dependencies by adding this to your `.semaphore/semaphore.yml` file: .semaphore/semaphore.yml version: v1.0name: Semaphore CI pnpm exampleagent: machine: type: e1-standard-2 os_image: ubuntu1804blocks: - name: Install dependencies task: jobs: - name: pnpm install commands: - corepack enable - corepack prepare pnpm@latest-9 --activate - checkout - cache restore node-$(checksum pnpm-lock.yaml) - pnpm install - cache store node-$(checksum pnpm-lock.yaml) $(pnpm store path) AppVeyor[​](https://pnpm.io/9.x/continuous-integration#appveyor "Direct link to AppVeyor") ------------------------------------------------------------------------------------------- On [AppVeyor](https://www.appveyor.com/) , you can use pnpm for installing your dependencies by adding this to your `appveyor.yml`: appveyor.yml install: - ps: Install-Product node $env:nodejs_version - corepack enable - corepack prepare pnpm@latest-9 --activate - pnpm install GitHub Actions[​](https://pnpm.io/9.x/continuous-integration#github-actions "Direct link to GitHub Actions") ------------------------------------------------------------------------------------------------------------- On GitHub Actions, you can use pnpm for installing and caching your dependencies like so (belongs in `.github/workflows/NAME.yml`): .github/workflows/NAME.yml name: pnpm Example Workflowon: push:jobs: build: runs-on: ubuntu-22.04 strategy: matrix: node-version: [20] steps: - uses: actions/checkout@v4 - name: Install pnpm uses: pnpm/action-setup@v4 with: version: 9 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} cache: 'pnpm' - name: Install dependencies run: pnpm install GitLab CI[​](https://pnpm.io/9.x/continuous-integration#gitlab-ci "Direct link to GitLab CI") ---------------------------------------------------------------------------------------------- On GitLab, you can use pnpm for installing and caching your dependencies like so (belongs in `.gitlab-ci.yml`): .gitlab-ci.yml stages: - buildbuild: stage: build image: node:18.17.1 before_script: - corepack enable - corepack prepare pnpm@latest-9 --activate - pnpm config set store-dir .pnpm-store script: - pnpm install # install dependencies cache: key: files: - pnpm-lock.yaml paths: - .pnpm-store Bitbucket Pipelines[​](https://pnpm.io/9.x/continuous-integration#bitbucket-pipelines "Direct link to Bitbucket Pipelines") ---------------------------------------------------------------------------------------------------------------------------- You can use pnpm for installing and caching your dependencies: .bitbucket-pipelines.yml definitions: caches: pnpm: $BITBUCKET_CLONE_DIR/.pnpm-storepipelines: pull-requests: "**": - step: name: Build and test image: node:18.17.1 script: - corepack enable - corepack prepare pnpm@latest-9 --activate - pnpm install - pnpm run build # Replace with your build/test…etc. commands caches: - pnpm Azure Pipelines[​](https://pnpm.io/9.x/continuous-integration#azure-pipelines "Direct link to Azure Pipelines") ---------------------------------------------------------------------------------------------------------------- On Azure Pipelines, you can use pnpm for installing and caching your dependencies by adding this to your `azure-pipelines.yml`: azure-pipelines.yml variables: pnpm_config_cache: $(Pipeline.Workspace)/.pnpm-storesteps: - task: Cache@2 inputs: key: 'pnpm | "$(Agent.OS)" | pnpm-lock.yaml' path: $(pnpm_config_cache) displayName: Cache pnpm - script: | corepack enable corepack prepare pnpm@latest-9 --activate pnpm config set store-dir $(pnpm_config_cache) displayName: "Setup pnpm" - script: | pnpm install pnpm run build displayName: "pnpm install and build" CircleCI[​](https://pnpm.io/9.x/continuous-integration#circleci "Direct link to CircleCI") ------------------------------------------------------------------------------------------- On CircleCI, you can use pnpm for installing and caching your dependencies by adding this to your `.circleci/config.yml`: .circleci/config.yml version: 2.1jobs: build: # this can be any name you choose docker: - image: node:18 resource_class: large parallelism: 10 steps: - checkout - restore_cache: name: Restore pnpm Package Cache keys: - pnpm-packages-{{ checksum "pnpm-lock.yaml" }} - run: name: Install pnpm package manager command: | corepack enable corepack prepare pnpm@latest-9 --activate pnpm config set store-dir .pnpm-store - run: name: Install Dependencies command: | pnpm install - save_cache: name: Save pnpm Package Cache key: pnpm-packages-{{ checksum "pnpm-lock.yaml" }} paths: - .pnpm-store Jenkins[​](https://pnpm.io/9.x/continuous-integration#jenkins "Direct link to Jenkins") ---------------------------------------------------------------------------------------- You can use pnpm for installing and caching your dependencies: pipeline { agent { docker { image 'node:lts-bullseye-slim' args '-p 3000:3000' } } stages { stage('Build') { steps { sh 'corepack enable' sh 'corepack prepare pnpm@latest-9 --activate' sh 'pnpm install' } } }} * [Travis](https://pnpm.io/9.x/continuous-integration#travis) * [Semaphore](https://pnpm.io/9.x/continuous-integration#semaphore) * [AppVeyor](https://pnpm.io/9.x/continuous-integration#appveyor) * [GitHub Actions](https://pnpm.io/9.x/continuous-integration#github-actions) * [GitLab CI](https://pnpm.io/9.x/continuous-integration#gitlab-ci) * [Bitbucket Pipelines](https://pnpm.io/9.x/continuous-integration#bitbucket-pipelines) * [Azure Pipelines](https://pnpm.io/9.x/continuous-integration#azure-pipelines) * [CircleCI](https://pnpm.io/9.x/continuous-integration#circleci) * [Jenkins](https://pnpm.io/9.x/continuous-integration#jenkins) --- # Working with Docker | pnpm [Skip to main content](https://pnpm.io/9.x/docker#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/docker) ** (10.x). Version: 9.x On this page note It is impossible to create reflinks or hardlinks between a Docker container and the host filesystem during build time. The next best thing you can do is using BuildKit cache mount to share cache between builds. Alternatively, you may use [podman](https://pnpm.io/9.x/podman) because it can mount Btrfs volumes during build time. Minimizing Docker image size and build time[​](https://pnpm.io/9.x/docker#minimizing-docker-image-size-and-build-time "Direct link to Minimizing Docker image size and build time") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ * Use a small image, e.g. `node:XX-slim`. * Leverage multi-stage if possible and makes sense. * Leverage BuildKit cache mounts. ### Example 1: Build a bundle in a Docker container[​](https://pnpm.io/9.x/docker#example-1-build-a-bundle-in-a-docker-container "Direct link to Example 1: Build a bundle in a Docker container") Since `devDependencies` is only necessary for building the bundle, `pnpm install --prod` will be a separate stage from `pnpm install` and `pnpm run build`, allowing the final stage to copy only necessary files from the earlier stages, minimizing the size of the final image. .dockerignore node_modules.git.gitignore*.mddist Dockerfile FROM node:20-slim AS baseENV PNPM_HOME="/pnpm"ENV PATH="$PNPM_HOME:$PATH"RUN corepack enableCOPY . /appWORKDIR /appFROM base AS prod-depsRUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --prod --frozen-lockfileFROM base AS buildRUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfileRUN pnpm run buildFROM baseCOPY --from=prod-deps /app/node_modules /app/node_modulesCOPY --from=build /app/dist /app/distEXPOSE 8000CMD [ "pnpm", "start" ] ### Example 2: Build multiple Docker images in a monorepo[​](https://pnpm.io/9.x/docker#example-2-build-multiple-docker-images-in-a-monorepo "Direct link to Example 2: Build multiple Docker images in a monorepo") Assuming you have a monorepo with 3 packages: app1, app2, and common; app1 and app2 depend on common but not each other. You want to save only necessary dependencies for each package, `pnpm deploy` should help you with copying only necessary files and packages. Structure of the monorepo ./├── Dockerfile├── .dockerignore├── .gitignore├── packages/│   ├── app1/│   │   ├── dist/│   │   ├── package.json│   │   ├── src/│   │   └── tsconfig.json│   ├── app2/│   │   ├── dist/│   │   ├── package.json│   │   ├── src/│   │   └── tsconfig.json│   └── common/│   ├── dist/│   ├── package.json│   ├── src/│   └── tsconfig.json├── pnpm-lock.yaml├── pnpm-workspace.yaml└── tsconfig.json pnpm-workspace.yaml packages: - 'packages/*' .dockerignore node_modules.git.gitignore*.mddist Dockerfile FROM node:20-slim AS baseENV PNPM_HOME="/pnpm"ENV PATH="$PNPM_HOME:$PATH"RUN corepack enableFROM base AS buildCOPY . /usr/src/appWORKDIR /usr/src/appRUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfileRUN pnpm run -r buildRUN pnpm deploy --filter=app1 --prod /prod/app1RUN pnpm deploy --filter=app2 --prod /prod/app2FROM base AS app1COPY --from=build /prod/app1 /prod/app1WORKDIR /prod/app1EXPOSE 8000CMD [ "pnpm", "start" ]FROM base AS app2COPY --from=build /prod/app2 /prod/app2WORKDIR /prod/app2EXPOSE 8001CMD [ "pnpm", "start" ] Run the following commands to build images for app1 and app2: docker build . --target app1 --tag app1:latestdocker build . --target app2 --tag app2:latest ### Example 3: Build on CI/CD[​](https://pnpm.io/9.x/docker#example-3-build-on-cicd "Direct link to Example 3: Build on CI/CD") On CI or CD environments, the BuildKit cache mounts might not be available, because the VM or container is ephemeral and only normal docker cache will work. So an alternative is to use a typical Dockerfile with layers that are built incrementally, for this scenario, `pnpm fetch` is the best option, as it only needs the `pnpm-lock.yaml` file and the layer cache will only be lost when you change the dependencies. Dockerfile FROM node:20-slim AS baseWORKDIR /appENV PNPM_HOME="/pnpm"ENV PATH="$PNPM_HOME:$PATH"RUN corepack enableFROM base AS prodCOPY pnpm-lock.yaml /appRUN pnpm fetch --prodCOPY . /appRUN pnpm run buildFROM baseCOPY --from=prod /app/node_modules /app/node_modulesCOPY --from=prod /app/dist /app/distEXPOSE 8000CMD [ "pnpm", "start" ] * [Minimizing Docker image size and build time](https://pnpm.io/9.x/docker#minimizing-docker-image-size-and-build-time) * [Example 1: Build a bundle in a Docker container](https://pnpm.io/9.x/docker#example-1-build-a-bundle-in-a-docker-container) * [Example 2: Build multiple Docker images in a monorepo](https://pnpm.io/9.x/docker#example-2-build-multiple-docker-images-in-a-monorepo) * [Example 3: Build on CI/CD](https://pnpm.io/9.x/docker#example-3-build-on-cicd) --- # Feature Comparison | pnpm [Skip to main content](https://pnpm.io/9.x/feature-comparison#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/feature-comparison) ** (10.x). Version: 9.x | Feature | pnpm | Yarn | npm | | --- | --- | --- | --- | | Workspace support | ✔️ | ✔️ | ✔️ | | Isolated `node_modules` | ✔️ - The default | ✔️ | ✔️ | | Hoisted `node_modules` | ✔️ | ✔️ | ✔️ - The default | | Autoinstalling peers | ✔️ | ❌ | ✔️ | | Plug'n'Play | ✔️ | ✔️ - The default | ❌ | | Zero-Installs | ❌ | ✔️ | ❌ | | Patching dependencies | ✔️ | ✔️ | ❌ | | Managing Node.js versions | ✔️ | ❌ | ❌ | | Has a lockfile | ✔️ - `pnpm-lock.yaml` | ✔️ - `yarn.lock` | ✔️ - `package-lock.json` | | Overrides support | ✔️ | ✔️ - Via resolutions | ✔️ | | Content-addressable storage | ✔️ | ❌ | ❌ | | Dynamic package execution | ✔️ - Via `pnpm dlx` | ✔️ - Via `yarn dlx` | ✔️ - Via `npx` | | Side-effects cache | ✔️ | ❌ | ❌ | | Listing licenses | ✔️ - Via `pnpm licenses list` | ✔️ - Via a plugin | ❌ | --- # Error Codes | pnpm [Skip to main content](https://pnpm.io/9.x/errors#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/errors) ** (10.x). Version: 9.x On this page ERR\_PNPM\_UNEXPECTED\_STORE[​](https://pnpm.io/9.x/errors#err_pnpm_unexpected_store "Direct link to ERR_PNPM_UNEXPECTED_STORE") --------------------------------------------------------------------------------------------------------------------------------- A modules directory is present and is linked to a different store directory. If you changed the store directory intentionally, run `pnpm install` and pnpm will reinstall the dependencies using the new store. ERR\_PNPM\_NO\_MATCHING\_VERSION\_INSIDE\_WORKSPACE[​](https://pnpm.io/9.x/errors#err_pnpm_no_matching_version_inside_workspace "Direct link to ERR_PNPM_NO_MATCHING_VERSION_INSIDE_WORKSPACE") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ A project has a workspace dependency that does not exist in the workspace. For instance, package `foo` has `bar@1.0.0` in the `dependencies`: { "name": "foo", "version": "1.0.0", "dependencies": { "bar": "workspace:1.0.0" }} However, there is only `bar@2.0.0` in the workspace, so `pnpm install` will fail. To fix this error, all dependencies that use the [workspace protocol](https://pnpm.io/9.x/workspaces#workspace-protocol-workspace) should be updated to use versions of packages that are present in the workspace. This can be done either manually or using the `pnpm -r update` command. ERR\_PNPM\_PEER\_DEP\_ISSUES[​](https://pnpm.io/9.x/errors#err_pnpm_peer_dep_issues "Direct link to ERR_PNPM_PEER_DEP_ISSUES") ------------------------------------------------------------------------------------------------------------------------------- `pnpm install` will fail if the project has unresolved peer dependencies or the peer dependencies are not matching the wanted ranges. To fix this, install the missing peer dependencies. You may also selectively ignore these errors using the [pnpm.peerDependencyRules.ignoreMissing](https://pnpm.io/9.x/package_json#pnpmpeerdependencyrulesignoremissing) and [pnpm.peerDependencyRules.allowedVersions](https://pnpm.io/9.x/package_json#pnpmpeerdependencyrulesallowedversions) fields in `package.json`. ERR\_PNPM\_OUTDATED\_LOCKFILE[​](https://pnpm.io/9.x/errors#err_pnpm_outdated_lockfile "Direct link to ERR_PNPM_OUTDATED_LOCKFILE") ------------------------------------------------------------------------------------------------------------------------------------ This error happens when installation cannot be performed without changes to the lockfile. This might happen in a CI environment if someone has changed a `package.json` file in the repository without running `pnpm install` afterwards. Or someone forgot to commit the changes to the lockfile. To fix this error, just run `pnpm install` and commit the changes to the lockfile. ERR\_PNPM\_TARBALL\_INTEGRITY[​](https://pnpm.io/9.x/errors#err_pnpm_tarball_integrity "Direct link to ERR_PNPM_TARBALL_INTEGRITY") ------------------------------------------------------------------------------------------------------------------------------------ This error indicates that the downloaded package's tarball did not match the expected integrity checksum. If you use the npm registry (`registry.npmjs.org`), then this probably means that the integrity in your lockfile is incorrect. This might happen if a lockfile had badly resolved merge conflicts. If you use a registry that allows to override existing versions of a package, then it might mean that in your local metadata cache you have the integrity checksum of an older version of the package. In this case, you should run `pnpm store prune`. This command will remove your local metadata cache. Then you can retry the command that failed. But also be careful and verify that the package is downloaded from the right URL. The URL should be printed in the error message. ERR\_PNPM\_MISMATCHED\_RELEASE\_CHANNEL[​](https://pnpm.io/9.x/errors#err_pnpm_mismatched_release_channel "Direct link to ERR_PNPM_MISMATCHED_RELEASE_CHANNEL") ---------------------------------------------------------------------------------------------------------------------------------------------------------------- The config field `use-node-version` defines a release channel different from version suffix. For example: * `rc/20.0.0` defines an `rc` channel but the version is that of a stable release. * `release/20.0.0-rc.0` defines a `release` channel but the version is that of an RC release. To fix this error, either remove the release channel prefix or correct the version suffix. Note that it is not allowed to specify node versions like `lts/Jod`. The correct syntax for stable release is strictly X.Y.Z or release/X.Y.Z. ERR\_PNPM\_INVALID\_NODE\_VERSION[​](https://pnpm.io/9.x/errors#err_pnpm_invalid_node_version "Direct link to ERR_PNPM_INVALID_NODE_VERSION") ---------------------------------------------------------------------------------------------------------------------------------------------- The value of config field `use-node-version` has an invalid syntax. Below are the valid forms of `use-node-version`: * Stable release: * `X.Y.Z` (`X`, `Y`, `Z` are integers) * `release/X.Y.Z` (`X`, `Y`, `Z` are integers) * RC release: * `X.Y.Z-rc.W` (`X`, `Y`, `Z`, `W` are integers) * `rc/X.Y.Z-rc.W` (`X`, `Y`, `Z`, `W` are integers) * [ERR\_PNPM\_UNEXPECTED\_STORE](https://pnpm.io/9.x/errors#err_pnpm_unexpected_store) * [ERR\_PNPM\_NO\_MATCHING\_VERSION\_INSIDE\_WORKSPACE](https://pnpm.io/9.x/errors#err_pnpm_no_matching_version_inside_workspace) * [ERR\_PNPM\_PEER\_DEP\_ISSUES](https://pnpm.io/9.x/errors#err_pnpm_peer_dep_issues) * [ERR\_PNPM\_OUTDATED\_LOCKFILE](https://pnpm.io/9.x/errors#err_pnpm_outdated_lockfile) * [ERR\_PNPM\_TARBALL\_INTEGRITY](https://pnpm.io/9.x/errors#err_pnpm_tarball_integrity) * [ERR\_PNPM\_MISMATCHED\_RELEASE\_CHANNEL](https://pnpm.io/9.x/errors#err_pnpm_mismatched_release_channel) * [ERR\_PNPM\_INVALID\_NODE\_VERSION](https://pnpm.io/9.x/errors#err_pnpm_invalid_node_version) --- # Working with Git | pnpm [Skip to main content](https://pnpm.io/9.x/git#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/git) ** (10.x). Version: 9.x On this page Lockfiles[​](https://pnpm.io/9.x/git#lockfiles "Direct link to Lockfiles") --------------------------------------------------------------------------- You should always commit the lockfile (`pnpm-lock.yaml`). This is for a multitude of reasons, the primary of which being: * it enables faster installation for CI and production environments, due to being able to skip package resolution * it enforces consistent installations and resolution between development, testing, and production environments, meaning the packages used in testing and production will be exactly the same as when you developed your project ### Merge conflicts[​](https://pnpm.io/9.x/git#merge-conflicts "Direct link to Merge conflicts") pnpm can automatically resolve merge conflicts in `pnpm-lock.yaml`. If you have conflicts, just run `pnpm install` and commit the changes. Be warned, however. It is advised that you review the changes prior to staging a commit, because we cannot guarantee that pnpm will choose the correct head - it instead builds with the most updated of lockfiles, which is ideal in most cases. * [Lockfiles](https://pnpm.io/9.x/git#lockfiles) * [Merge conflicts](https://pnpm.io/9.x/git#merge-conflicts) --- # Git Branch Lockfiles | pnpm [Skip to main content](https://pnpm.io/9.x/git_branch_lockfiles#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/git_branch_lockfiles) ** (10.x). Version: 9.x On this page Git branch lockfiles allows you to totally avoid lockfile merge conflicts and solve it later. Use git branch lockfiles[​](https://pnpm.io/9.x/git_branch_lockfiles#use-git-branch-lockfiles "Direct link to Use git branch lockfiles") ----------------------------------------------------------------------------------------------------------------------------------------- You can turn on this feature by configuring the `.npmrc` file. git-branch-lockfile=true By doing this, lockfile name will be generated based on the current branch name. For instance, the current branch name is `feature-1`. Then, the generated lockfile name will be `pnpm-lock.feature-1.yaml`. You can commit it to the Git, and merge all git branch lockfiles later. - |- pnpm-lock.yaml|- pnpm-lock.feature-1.yaml|- pnpm-lock..yaml note `feature/1` is special in that the `/` is automatically converted to `!`, so the corresponding lockfile name would be `pnpm-lock.feature!1.yaml`. Merge git branch lockfiles[​](https://pnpm.io/9.x/git_branch_lockfiles#merge-git-branch-lockfiles "Direct link to Merge git branch lockfiles") ----------------------------------------------------------------------------------------------------------------------------------------------- ### `pnpm install --merge-git-branch-lockfiles`[​](https://pnpm.io/9.x/git_branch_lockfiles#pnpm-install---merge-git-branch-lockfiles "Direct link to pnpm-install---merge-git-branch-lockfiles") To merge all git branch lockfiles, just specify `--merge-git-branch-lockfiles` to `pnpm install` command. After that, all git branch lockfiles will be merged into one `pnpm-lock.yaml` ### Branch Matching[​](https://pnpm.io/9.x/git_branch_lockfiles#branch-matching "Direct link to Branch Matching") pnpm allows you to specify `--merge-git-branch-lockfiles` by matching the current branch name. For instance, by the following setting in `.npmrc` file, `pnpm install` will merge all git branch lockfiles when running in the `main` branch and the branch name starts with `release`. merge-git-branch-lockfiles-branch-pattern[]=mainmerge-git-branch-lockfiles-branch-pattern[]=release* * [Use git branch lockfiles](https://pnpm.io/9.x/git_branch_lockfiles#use-git-branch-lockfiles) * [Merge git branch lockfiles](https://pnpm.io/9.x/git_branch_lockfiles#merge-git-branch-lockfiles) * [`pnpm install --merge-git-branch-lockfiles`](https://pnpm.io/9.x/git_branch_lockfiles#pnpm-install---merge-git-branch-lockfiles) * [Branch Matching](https://pnpm.io/9.x/git_branch_lockfiles#branch-matching) --- # Filtering | pnpm [Skip to main content](https://pnpm.io/9.x/filtering#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/filtering) ** (10.x). Version: 9.x On this page Filtering allows you to restrict commands to specific subsets of packages. pnpm supports a rich selector syntax for picking packages by name or by relation. Selectors may be specified via the `--filter` (or `-F`) flag: pnpm --filter Matching[​](https://pnpm.io/9.x/filtering#matching "Direct link to Matching") ------------------------------------------------------------------------------ ### \--filter [​](https://pnpm.io/9.x/filtering#--filter-package_name "Direct link to --filter ") To select an exact package, just specify its name (`@scope/pkg`) or use a pattern to select a set of packages (`@scope/*`). Examples: pnpm --filter "@babel/core" testpnpm --filter "@babel/*" testpnpm --filter "*core" test Specifying the scope of the package is optional, so `--filter=core` will pick `@babel/core` if `core` is not found. However, if the workspace has multiple packages with the same name (for instance, `@babel/core` and `@types/core`), then filtering without scope will pick nothing. ### \--filter ...[​](https://pnpm.io/9.x/filtering#--filter-package_name-1 "Direct link to --filter ...") To select a package and its dependencies (direct and non-direct), suffix the package name with an ellipsis: `...`. For instance, the next command will run tests of `foo` and all of its dependencies: pnpm --filter foo... test You may use a pattern to select a set of root packages: pnpm --filter "@babel/preset-*..." test ### \--filter ^...[​](https://pnpm.io/9.x/filtering#--filter-package_name-2 "Direct link to --filter ^...") To ONLY select the dependencies of a package (both direct and non-direct), suffix the name with the aforementioned ellipsis preceded by a chevron. For instance, the next command will run tests for all of `foo`'s dependencies: pnpm --filter "foo^..." test ### \--filter ...[​](https://pnpm.io/9.x/filtering#--filter-package_name-3 "Direct link to --filter ...") To select a package and its dependent packages (direct and non-direct), prefix the package name with an ellipsis: `...`. For instance, this will run the tests of `foo` and all packages dependent on it: pnpm --filter ...foo test ### \--filter "...^"[​](https://pnpm.io/9.x/filtering#--filter-package_name-4 "Direct link to --filter "...^"") To ONLY select a package's dependents (both direct and non-direct), prefix the package name with an ellipsis followed by a chevron. For instance, this will run tests for all packages dependent on `foo`: pnpm --filter "...^foo" test ### \--filter `./`, --filter `{}`[​](https://pnpm.io/9.x/filtering#--filter-glob---filter-glob "Direct link to --filter-glob---filter-glob") A glob pattern relative to the current working directory matching projects. pnpm --filter "./packages/**" Includes all projects that are under the specified directory. It may be used with the ellipsis and chevron operators to select dependents/dependencies as well: pnpm --filter ...{} pnpm --filter {}... pnpm --filter ...{}... It may also be combined with `[]`. For instance, to select all changed projects inside a directory: pnpm --filter "{packages/**}[origin/master]" pnpm --filter "...{packages/**}[origin/master]" pnpm --filter "{packages/**}[origin/master]..." pnpm --filter "...{packages/**}[origin/master]..." Or you may select all packages from a directory with names matching the given pattern: pnpm --filter "@babel/*{components/**}" pnpm --filter "@babel/*{components/**}[origin/master]" pnpm --filter "...@babel/*{components/**}[origin/master]" ### \--filter "\[\]"[​](https://pnpm.io/9.x/filtering#--filter-since "Direct link to --filter "[]"") Selects all the packages changed since the specified commit/branch. May be suffixed or prefixed with `...` to include dependencies/dependents. For example, the next command will run tests in all changed packages since `master` and on any dependent packages: pnpm --filter "...[origin/master]" test ### \--fail-if-no-match[​](https://pnpm.io/9.x/filtering#--fail-if-no-match "Direct link to --fail-if-no-match") Use this flag if you want the CLI to fail if no packages have matched the filters. Excluding[​](https://pnpm.io/9.x/filtering#excluding "Direct link to Excluding") --------------------------------------------------------------------------------- Any of the filter selectors may work as exclusion operators when they have a leading "!". In zsh (and possibly other shells), "!" should be escaped: `\!`. For instance, this will run a command in all projects except for `foo`: pnpm --filter=!foo And this will run a command in all projects that are not under the `lib` directory: pnpm --filter=!./lib Multiplicity[​](https://pnpm.io/9.x/filtering#multiplicity "Direct link to Multiplicity") ------------------------------------------------------------------------------------------ When packages are filtered, every package is taken that matches at least one of the selectors. You can use as many filters as you want: pnpm --filter ...foo --filter bar --filter baz... test \--filter-prod [​](https://pnpm.io/9.x/filtering#--filter-prod-filtering_pattern "Direct link to --filter-prod ") --------------------------------------------------------------------------------------------------------------------------------------------------------- Acts the same a `--filter` but omits `devDependencies` when selecting dependency projects from the workspace. \--test-pattern [​](https://pnpm.io/9.x/filtering#--test-pattern-glob "Direct link to --test-pattern ") -------------------------------------------------------------------------------------------------------------------- `test-pattern` allows detecting whether the modified files are related to tests. If they are, the dependent packages of such modified packages are not included. This option is useful with the "changed since" filter. For instance, the next command will run tests in all changed packages, and if the changes are in the source code of the package, tests will run in the dependent packages as well: pnpm --filter="...[origin/master]" --test-pattern="test/*" test \--changed-files-ignore-pattern [​](https://pnpm.io/9.x/filtering#--changed-files-ignore-pattern-glob "Direct link to --changed-files-ignore-pattern ") -------------------------------------------------------------------------------------------------------------------------------------------------------------------- Allows to ignore changed files by glob patterns when filtering for changed projects since the specified commit/branch. Usage example: pnpm --filter="...[origin/master]" --changed-files-ignore-pattern="**/README.md" run build * [Matching](https://pnpm.io/9.x/filtering#matching) * [\--filter ](https://pnpm.io/9.x/filtering#--filter-package_name) * [\--filter ...](https://pnpm.io/9.x/filtering#--filter-package_name-1) * [\--filter ^...](https://pnpm.io/9.x/filtering#--filter-package_name-2) * [\--filter ...](https://pnpm.io/9.x/filtering#--filter-package_name-3) * [\--filter "...^"](https://pnpm.io/9.x/filtering#--filter-package_name-4) * [\--filter `./`, --filter `{}`](https://pnpm.io/9.x/filtering#--filter-glob---filter-glob) * [\--filter "\[\]"](https://pnpm.io/9.x/filtering#--filter-since) * [\--fail-if-no-match](https://pnpm.io/9.x/filtering#--fail-if-no-match) * [Excluding](https://pnpm.io/9.x/filtering#excluding) * [Multiplicity](https://pnpm.io/9.x/filtering#multiplicity) * [\--filter-prod ](https://pnpm.io/9.x/filtering#--filter-prod-filtering_pattern) * [\--test-pattern ](https://pnpm.io/9.x/filtering#--test-pattern-glob) * [\--changed-files-ignore-pattern ](https://pnpm.io/9.x/filtering#--changed-files-ignore-pattern-glob) --- # Only allow pnpm | pnpm [Skip to main content](https://pnpm.io/9.x/only-allow-pnpm#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/only-allow-pnpm) ** (10.x). Version: 9.x When you use pnpm on a project, you don't want others to accidentally run `npm install` or `yarn`. To prevent devs from using other package managers, you can add the following `preinstall` script to your `package.json`: { "scripts": { "preinstall": "npx only-allow pnpm" }} Now, whenever someone runs `npm install` or `yarn`, they'll get an error instead and installation will not proceed. If you use npm v7, use `npx -y` instead. --- # How peers are resolved | pnpm [Skip to main content](https://pnpm.io/9.x/how-peers-are-resolved#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/how-peers-are-resolved) ** (10.x). Version: 9.x One of the best features of pnpm is that in one project, a specific version of a package will always have one set of dependencies. There is one exception from this rule, though - packages with [peer dependencies](https://docs.npmjs.com/cli/v10/configuring-npm/package-json#peerdependencies) . Peer dependencies are resolved from dependencies installed higher in the dependency graph, since they share the same version as their parent. That means that if `foo@1.0.0` has two peers (`bar@^1` and `baz@^1`) then it might have multiple different sets of dependencies in the same project. - foo-parent-1 - bar@1.0.0 - baz@1.0.0 - foo@1.0.0- foo-parent-2 - bar@1.0.0 - baz@1.1.0 - foo@1.0.0 In the example above, `foo@1.0.0` is installed for `foo-parent-1` and `foo-parent-2`. Both packages have `bar` and `baz` as well, but they depend on different versions of `baz`. As a result, `foo@1.0.0` has two different sets of dependencies: one with `baz@1.0.0` and the other one with `baz@1.1.0`. To support these use cases, pnpm has to hard link `foo@1.0.0` as many times as there are different dependency sets. Normally, if a package does not have peer dependencies, it is hard linked to a `node_modules` folder next to symlinks of its dependencies, like so: node_modules└── .pnpm ├── foo@1.0.0 │ └── node_modules │ ├── foo │ ├── qux -> ../../qux@1.0.0/node_modules/qux │ └── plugh -> ../../plugh@1.0.0/node_modules/plugh ├── qux@1.0.0 ├── plugh@1.0.0 However, if `foo` has peer dependencies, there may be multiple sets of dependencies for it, so we create different sets for different peer dependency resolutions: node_modules└── .pnpm ├── foo@1.0.0_bar@1.0.0+baz@1.0.0 │ └── node_modules │ ├── foo │ ├── bar -> ../../bar@1.0.0/node_modules/bar │ ├── baz -> ../../baz@1.0.0/node_modules/baz │ ├── qux -> ../../qux@1.0.0/node_modules/qux │ └── plugh -> ../../plugh@1.0.0/node_modules/plugh ├── foo@1.0.0_bar@1.0.0+baz@1.1.0 │ └── node_modules │ ├── foo │ ├── bar -> ../../bar@1.0.0/node_modules/bar │ ├── baz -> ../../baz@1.1.0/node_modules/baz │ ├── qux -> ../../qux@1.0.0/node_modules/qux │ └── plugh -> ../../plugh@1.0.0/node_modules/plugh ├── bar@1.0.0 ├── baz@1.0.0 ├── baz@1.1.0 ├── qux@1.0.0 ├── plugh@1.0.0 We create symlinks either to the `foo` that is inside `foo@1.0.0_bar@1.0.0+baz@1.0.0` or to the one in `foo@1.0.0_bar@1.0.0+baz@1.1.0`. As a consequence, the Node.js module resolver will find the correct peers. _If a package has no peer dependencies but has dependencies with peers that are resolved higher in the graph_, then that transitive package can appear in the project with different sets of dependencies. For instance, there's package `a@1.0.0` with a single dependency `b@1.0.0`. `b@1.0.0` has a peer dependency `c@^1`. `a@1.0.0` will never resolve the peers of `b@1.0.0`, so it becomes dependent from the peers of `b@1.0.0` as well. Here's how that structure will look in `node_modules`. In this example, `a@1.0.0` will need to appear twice in the project's `node_modules` - resolved once with `c@1.0.0` and again with `c@1.1.0`. node_modules└── .pnpm ├── a@1.0.0_c@1.0.0 │ └── node_modules │ ├── a │ └── b -> ../../b@1.0.0_c@1.0.0/node_modules/b ├── a@1.0.0_c@1.1.0 │ └── node_modules │ ├── a │ └── b -> ../../b@1.0.0_c@1.1.0/node_modules/b ├── b@1.0.0_c@1.0.0 │ └── node_modules │ ├── b │ └── c -> ../../c@1.0.0/node_modules/c ├── b@1.0.0_c@1.1.0 │ └── node_modules │ ├── b │ └── c -> ../../c@1.1.0/node_modules/c ├── c@1.0.0 ├── c@1.1.0 --- # Limitations | pnpm [Skip to main content](https://pnpm.io/9.x/limitations#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/limitations) ** (10.x). Version: 9.x 1. `npm-shrinkwrap.json` and `package-lock.json` are ignored. Unlike pnpm, npm can install the same `name@version` multiple times and with different sets of dependencies. npm's lockfile is designed to reflect the flat `node_modules` layout, however, as pnpm creates an isolated layout by default, it cannot respect npm's lockfile format. See [pnpm import](https://pnpm.io/9.x/cli/import) if you wish to convert a lockfile to pnpm's format, though. 2. Binstubs (files in `node_modules/.bin`) are always shell files, not symlinks to JS files. The shell files are created to help pluggable CLI apps in finding their plugins in the unusual `node_modules` structure. This is very rarely an issue and if you expect the file to be a JS file, reference the original file directly instead, as described in [#736](https://github.com/pnpm/pnpm/issues/736) . Got an idea for workarounds for these issues? [Share them.](https://github.com/pnpm/pnpm/issues/new) --- # Installation | pnpm [Skip to main content](https://pnpm.io/9.x/installation#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/installation) ** (10.x). Version: 9.x On this page Prerequisites[​](https://pnpm.io/9.x/installation#prerequisites "Direct link to Prerequisites") ------------------------------------------------------------------------------------------------ If you don't use the standalone script or `@pnpm/exe` to install pnpm, then you need to have Node.js (at least v18.12) to be installed on your system. Using a standalone script[​](https://pnpm.io/9.x/installation#using-a-standalone-script "Direct link to Using a standalone script") ------------------------------------------------------------------------------------------------------------------------------------ You may install pnpm even if you don't have Node.js installed, using the following scripts. ### On Windows[​](https://pnpm.io/9.x/installation#on-windows "Direct link to On Windows") warning Sometimes, Windows Defender may block our executable if you install pnpm this way. Due to this issue, we currently recommend installing pnpm using [npm](https://pnpm.io/9.x/installation#using-npm) or [Corepack](https://pnpm.io/9.x/installation#using-corepack) on Windows. Using PowerShell: $env:PNPM_VERSION = "9.15.5"; Invoke-WebRequest https://get.pnpm.io/install.ps1 -UseBasicParsing | Invoke-Expression ### On POSIX systems[​](https://pnpm.io/9.x/installation#on-posix-systems "Direct link to On POSIX systems") curl -fsSL https://get.pnpm.io/install.sh | env PNPM_VERSION=9.15.5 sh - If you don't have curl installed, you would like to use wget: wget -qO- https://get.pnpm.io/install.sh | env PNPM_VERSION=9.15.5 sh - tip You may use the [pnpm env](https://pnpm.io/9.x/cli/env) command then to install Node.js. ### In a Docker container[​](https://pnpm.io/9.x/installation#in-a-docker-container "Direct link to In a Docker container") # bashwget -qO- https://get.pnpm.io/install.sh | ENV="$HOME/.bashrc" SHELL="$(which bash)" bash -# shwget -qO- https://get.pnpm.io/install.sh | ENV="$HOME/.shrc" SHELL="$(which sh)" sh -# dashwget -qO- https://get.pnpm.io/install.sh | ENV="$HOME/.dashrc" SHELL="$(which dash)" dash - ### Installing a specific version[​](https://pnpm.io/9.x/installation#installing-a-specific-version "Direct link to Installing a specific version") Prior to running the install script, you may optionally set an env variable `PNPM_VERSION` to install a specific version of pnpm: curl -fsSL https://get.pnpm.io/install.sh | env PNPM_VERSION= sh - Using Corepack[​](https://pnpm.io/9.x/installation#using-corepack "Direct link to Using Corepack") --------------------------------------------------------------------------------------------------- Since v16.13, Node.js is shipping [Corepack](https://nodejs.org/api/corepack.html) for managing package managers. This is an experimental feature, so you need to enable it by running: info If you have installed Node.js with `pnpm env` Corepack won't be installed on your system, you will need to install it separately. See [#4029](https://github.com/pnpm/pnpm/issues/4029) . corepack enable pnpm If you installed Node.js using Homebrew, you'll need to install corepack separately: brew install corepack This will automatically install pnpm on your system. You can pin the version of pnpm used on your project using the following command: corepack use pnpm@latest This will add a `"packageManager"` field in your local `package.json` which will instruct Corepack to always use a specific version on that project. This can be useful if you want reproducability, as all developers who are using Corepack will use the same version as you. When a new version of pnpm is released, you can re-run the above command. Using other package managers[​](https://pnpm.io/9.x/installation#using-other-package-managers "Direct link to Using other package managers") --------------------------------------------------------------------------------------------------------------------------------------------- ### Using npm[​](https://pnpm.io/9.x/installation#using-npm "Direct link to Using npm") We provide two packages of pnpm CLI, `pnpm` and `@pnpm/exe`. * [`pnpm`](https://www.npmjs.com/package/pnpm) is an ordinary version of pnpm, which needs Node.js to run. * [`@pnpm/exe`](https://www.npmjs.com/package/@pnpm/exe) is packaged with Node.js into an executable, so it may be used on a system with no Node.js installed. npm install -g pnpm or npm install -g @pnpm/exe ### Using Homebrew[​](https://pnpm.io/9.x/installation#using-homebrew "Direct link to Using Homebrew") If you have the package manager installed, you can install pnpm using the following command: brew install pnpm ### Using winget[​](https://pnpm.io/9.x/installation#using-winget "Direct link to Using winget") If you have winget installed, you can install pnpm using the following command: winget install -e --id pnpm.pnpm ### Using Scoop[​](https://pnpm.io/9.x/installation#using-scoop "Direct link to Using Scoop") If you have Scoop installed, you can install pnpm using the following command: scoop install nodejs-lts pnpm ### Using Choco[​](https://pnpm.io/9.x/installation#using-choco "Direct link to Using Choco") If you have Chocolatey installed, you can install pnpm using the following command: choco install pnpm ### Using Volta[​](https://pnpm.io/9.x/installation#using-volta "Direct link to Using Volta") If you have Volta installed, you can install pnpm using the following command: volta install pnpm tip Do you wanna use pnpm on CI servers? See: [Continuous Integration](https://pnpm.io/9.x/continuous-integration) . Compatibility[​](https://pnpm.io/9.x/installation#compatibility "Direct link to Compatibility") ------------------------------------------------------------------------------------------------ Here is a list of past pnpm versions with respective Node.js version support. | Node.js | pnpm 7 | pnpm 8 | pnpm 9 | | --- | --- | --- | --- | | Node.js 12 | ❌ | ❌ | ❌ | | Node.js 14 | ✔️ | ❌ | ❌ | | Node.js 16 | ✔️ | ✔️ | ❌ | | Node.js 18 | ✔️ | ✔️ | ✔️ | | Node.js 20 | ✔️ | ✔️ | ✔️ | Troubleshooting[​](https://pnpm.io/9.x/installation#troubleshooting "Direct link to Troubleshooting") ------------------------------------------------------------------------------------------------------ If pnpm is broken and you cannot fix it by reinstalling, you might need to remove it manually from the PATH. Let's assume you have the following error when running `pnpm install`: C:\src>pnpm installinternal/modules/cjs/loader.js:883 throw err; ^Error: Cannot find module 'C:\Users\Bence\AppData\Roaming\npm\pnpm-global\4\node_modules\pnpm\bin\pnpm.js'←[90m at Function.Module._resolveFilename (internal/modules/cjs/loader.js:880:15)←[39m←[90m at Function.Module._load (internal/modules/cjs/loader.js:725:27)←[39m←[90m at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12)←[39m←[90m at internal/main/run_main_module.js:17:47←[39m { code: ←[32m'MODULE_NOT_FOUND'←[39m, requireStack: []}\ \ First, try to find the location of pnpm by running: `which pnpm`. If you're on Windows, run `where.exe pnpm.*` You'll get the location of the pnpm command, for instance:\ \ $ which pnpm/c/Program Files/nodejs/pnpm\ \ Now that you know where the pnpm CLI is, open that directory and remove any pnpm-related files (`pnpm.cmd`, `pnpx.cmd`, `pnpm`, etc). Once done, install pnpm again and it should work as expected.\ \ Using a shorter alias[​](https://pnpm.io/9.x/installation#using-a-shorter-alias "Direct link to Using a shorter alias")\ \ ------------------------------------------------------------------------------------------------------------------------\ \ `pnpm` might be hard to type, so you may use a shorter alias like `pn` instead.\ \ #### Adding a permanent alias on POSIX systems[​](https://pnpm.io/9.x/installation#adding-a-permanent-alias-on-posix-systems "Direct link to Adding a permanent alias on POSIX systems")\ \ Just put the following line to your `.bashrc`, `.zshrc`, or `config.fish`:\ \ alias pn=pnpm\ \ #### Adding a permanent alias in Powershell (Windows):[​](https://pnpm.io/9.x/installation#adding-a-permanent-alias-in-powershell-windows "Direct link to Adding a permanent alias in Powershell (Windows):")\ \ In a Powershell window with admin rights, execute:\ \ notepad $profile.AllUsersAllHosts\ \ In the `profile.ps1` file that opens, put:\ \ set-alias -name pn -value pnpm\ \ Save the file and close the window. You may need to close any open Powershell window in order for the alias to take effect.\ \ Updating pnpm[​](https://pnpm.io/9.x/installation#updating-pnpm "Direct link to Updating pnpm")\ \ ------------------------------------------------------------------------------------------------\ \ To update pnpm, run the [`self-update`](https://pnpm.io/9.x/cli/self-update)\ command:\ \ pnpm self-update\ \ Uninstalling pnpm[​](https://pnpm.io/9.x/installation#uninstalling-pnpm "Direct link to Uninstalling pnpm")\ \ ------------------------------------------------------------------------------------------------------------\ \ If you need to remove the pnpm CLI from your system and any files it has written to your disk, see [Uninstalling pnpm](https://pnpm.io/9.x/uninstall)\ .\ \ * [Prerequisites](https://pnpm.io/9.x/installation#prerequisites)\ \ * [Using a standalone script](https://pnpm.io/9.x/installation#using-a-standalone-script)\ * [On Windows](https://pnpm.io/9.x/installation#on-windows)\ \ * [On POSIX systems](https://pnpm.io/9.x/installation#on-posix-systems)\ \ * [In a Docker container](https://pnpm.io/9.x/installation#in-a-docker-container)\ \ * [Installing a specific version](https://pnpm.io/9.x/installation#installing-a-specific-version)\ \ * [Using Corepack](https://pnpm.io/9.x/installation#using-corepack)\ \ * [Using other package managers](https://pnpm.io/9.x/installation#using-other-package-managers)\ * [Using npm](https://pnpm.io/9.x/installation#using-npm)\ \ * [Using Homebrew](https://pnpm.io/9.x/installation#using-homebrew)\ \ * [Using winget](https://pnpm.io/9.x/installation#using-winget)\ \ * [Using Scoop](https://pnpm.io/9.x/installation#using-scoop)\ \ * [Using Choco](https://pnpm.io/9.x/installation#using-choco)\ \ * [Using Volta](https://pnpm.io/9.x/installation#using-volta)\ \ * [Compatibility](https://pnpm.io/9.x/installation#compatibility)\ \ * [Troubleshooting](https://pnpm.io/9.x/installation#troubleshooting)\ \ * [Using a shorter alias](https://pnpm.io/9.x/installation#using-a-shorter-alias)\ \ * [Updating pnpm](https://pnpm.io/9.x/installation#updating-pnpm)\ \ * [Uninstalling pnpm](https://pnpm.io/9.x/installation#uninstalling-pnpm) --- # Production | pnpm [Skip to main content](https://pnpm.io/9.x/production#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/production) ** (10.x). Version: 9.x There are two ways to bootstrap your package in a production environment with pnpm. One of these is to commit the lockfile. Then, in your production environment, run `pnpm install` - this will build the dependency tree using the lockfile, meaning the dependency versions will be consistent with how they were when the lockfile was committed. This is the most effective way (and the one we recommend) to ensure your dependency tree persists across environments. The other method is to commit the lockfile AND copy the package store to your production environment (you can change where with the [store location option](https://pnpm.io/9.x/npmrc#store-dir) ). Then, you can run `pnpm install --offline` and pnpm will use the packages from the global store, so it will not make any requests to the registry. This is recommended **ONLY** for environments where external access to the registry is unavailable for whatever reason. --- # Logos | pnpm [Skip to main content](https://pnpm.io/9.x/logos#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/logos) ** (10.x). Version: 9.x On this page Standard logo[​](https://pnpm.io/9.x/logos#standard-logo "Direct link to Standard logo") ----------------------------------------------------------------------------------------- **SVG:** ![](data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMjYiIGhlaWdodD0iMTYwIiBmaWxsPSJub25lIj48cGF0aCBmaWxsPSIjRjlBRDAwIiBkPSJNMjIxLjQ3OCA0OS43NTZoLTQ4Ljc4Vi45NzZoNDguNzh2NDguNzhaTTE2Ny44MSA0OS43NTZoLTQ4Ljc4MVYuOTc2aDQ4Ljc4MXY0OC43OFpNMTE0LjE1MSA0OS43NTZoLTQ4Ljc4Vi45NzZoNDguNzh2NDguNzhaTTIyMS40NzggMTAzLjQxNWgtNDguNzhWNTQuNjM0aDQ4Ljc4djQ4Ljc4MVoiLz48cGF0aCBmaWxsPSIjNEU0RTRFIiBkPSJNMTY3LjgxIDEwMy40MTVoLTQ4Ljc4MVY1NC42MzRoNDguNzgxdjQ4Ljc4MVpNMTY3LjgxIDE1Ny4wNzNoLTQ4Ljc4MXYtNDguNzhoNDguNzgxdjQ4Ljc4Wk0yMjEuNDc4IDE1Ny4wNzNoLTQ4Ljc4di00OC43OGg0OC43OHY0OC43OFpNMTE0LjE1MSAxNTcuMDczaC00OC43OHYtNDguNzhoNDguNzh2NDguNzhaTTEzLjA0MSA2OC4zNWMxLjY0IDAgMy4xNTUuMjE4IDQuNTQ5LjY1NSAxLjQyLjQxIDIuNjM2IDEuMDUyIDMuNjQ2IDEuOTI2IDEuMDExLjg3NCAxLjgwMyAxLjk4IDIuMzc3IDMuMzE5LjU3NCAxLjMxLjg2IDIuODgyLjg2IDQuNzEyIDAgMS43NDgtLjI0NSAzLjI3OC0uNzM3IDQuNTktLjQ5MiAxLjMxLTEuMTg4IDIuNDE3LTIuMDkgMy4zMTgtLjkwMS44NzQtMS45OTQgMS41My0zLjI3OCAxLjk2Ny0xLjI1Ni40MzctMi42NjMuNjU2LTQuMjIuNjU2LTEuMTc1IDAtMi4yNjgtLjE3OC0zLjI3OC0uNTMzdjYuODAyYy0uMjc0LjA4Mi0uNzEuMTY0LTEuMzEyLjI0Ni0uNi4xMDktMS4yMTUuMTY0LTEuODQ0LjE2NC0uNiAwLTEuMTQ3LS4wNDEtMS42MzktLjEyM2EyLjc0MiAyLjc0MiAwIDAgMS0xLjE4OC0uNDkyYy0uMzI4LS4yNDYtLjU3NC0uNTg3LS43MzctMS4wMjQtLjE2NC0uNDEtLjI0Ni0uOTU3LS4yNDYtMS42NFY3My4yMjZjMC0uNzM3LjE1LTEuMzM4LjQ1LTEuODAzLjMyOC0uNDY0Ljc2NS0uODg4IDEuMzEyLTEuMjcuODQ2LS41NDYgMS44OTgtLjk4MyAzLjE1NS0xLjMxMSAxLjI1Ni0uMzI4IDIuNjYzLS40OTIgNC4yMi0uNDkyWm0uMDgyIDE1LjY1MmMyLjgxNCAwIDQuMjItMS42OCA0LjIyLTUuMDQgMC0xLjc0OS0uMzU0LTMuMDQ2LTEuMDY1LTMuODkzLS42ODMtLjg0Ny0xLjY4LTEuMjctMi45OS0xLjI3LS41MiAwLS45ODQuMDY4LTEuMzk0LjIwNS0uNDEuMTEtLjc2NS4yNDYtMS4wNjUuNDF2OS4wMTRjLjMyNy4xNjQuNjgyLjMgMS4wNjUuNDEuMzgyLjExLjc5Mi4xNjQgMS4yMy4xNjRabTI3LjM3LTcuNzQ1YzAtLjg0Ni0uMjQ2LTEuNDYxLS43MzctMS44NDQtLjQ2NS0uNDEtMS4xMDctLjYxNC0xLjkyNi0uNjE0LS41NDcgMC0xLjA5My4wNjgtMS42NC4yMDUtLjUxOC4xMzYtLjk2OS4zNDEtMS4zNTEuNjE0djE0LjIxOWMtLjI3My4wODItLjcxLjE2NC0xLjMxMi4yNDYtLjU3My4wODItMS4xNzQuMTIzLTEuODAzLjEyMy0uNiAwLTEuMTQ3LS4wNDEtMS42MzktLjEyM2EyLjc0IDIuNzQgMCAwIDEtMS4xODgtLjQ5MiAyLjU1IDIuNTUgMCAwIDEtLjc3OC0uOTgzYy0uMTY0LS40MzctLjI0Ni0uOTk3LS4yNDYtMS42OFY3My42MzVjMC0uNzM4LjE1LTEuMzM5LjQ1LTEuODAzLjMyOC0uNDY0Ljc2NS0uODg4IDEuMzEyLTEuMjcuOTI4LS42NTYgMi4wOS0xLjE4OCAzLjQ4My0xLjU5OCAxLjQyLS40MSAyLjk5LS42MTUgNC43MTItLjYxNSAzLjA4NyAwIDUuNDYzLjY4MyA3LjEzIDIuMDQ5IDEuNjY2IDEuMzM5IDIuNSAzLjIxIDIuNSA1LjYxNHYxMi44MjVjLS4yNzQuMDgyLS43MTEuMTY0LTEuMzEyLjI0Ni0uNTc0LjA4Mi0xLjE3NS4xMjMtMS44MDMuMTIzLS42MDEgMC0xLjE0Ny0uMDQxLTEuNjM5LS4xMjNhMi43NCAyLjc0IDAgMCAxLTEuMTg4LS40OTIgMi41NSAyLjU1IDAgMCAxLS43NzktLjk4M2MtLjE2NC0uNDM3LS4yNDYtLjk5Ny0uMjQ2LTEuNjh2LTkuNjdaTTYwLjkgNjguMzVjMS42MzkgMCAzLjE1NS4yMTkgNC41NDguNjU2IDEuNDIuNDEgMi42MzYgMS4wNTIgMy42NDcgMS45MjYgMS4wMS44NzQgMS44MDIgMS45OCAyLjM3NiAzLjMxOS41NzQgMS4zMS44NiAyLjg4Mi44NiA0LjcxMiAwIDEuNzQ4LS4yNDUgMy4yNzgtLjczNyA0LjU5LS40OTIgMS4zMS0xLjE4OCAyLjQxNy0yLjA5IDMuMzE4LS45MDEuODc0LTEuOTk0IDEuNTMtMy4yNzggMS45NjctMS4yNTYuNDM3LTIuNjYzLjY1Ni00LjIyLjY1Ni0xLjE3NSAwLTIuMjY3LS4xNzgtMy4yNzgtLjUzM3Y2LjgwMmMtLjI3My4wODItLjcxLjE2NC0xLjMxMi4yNDYtLjYuMTA5LTEuMjE1LjE2NC0xLjg0My4xNjQtLjYwMSAwLTEuMTQ4LS4wNDEtMS42NC0uMTIzYTIuNzQyIDIuNzQyIDAgMCAxLTEuMTg4LS40OTJjLS4zMjgtLjI0Ni0uNTczLS41ODctLjczNy0xLjAyNC0uMTY0LS40MS0uMjQ2LS45NTctLjI0Ni0xLjY0VjczLjIyNmMwLS43MzcuMTUtMS4zMzguNDUtMS44MDMuMzI4LS40NjQuNzY1LS44ODggMS4zMTItMS4yNy44NDctLjU0NiAxLjg5OC0uOTgzIDMuMTU1LTEuMzExIDEuMjU3LS4zMjggMi42NjMtLjQ5MiA0LjIyLS40OTJabS4wODEgMTUuNjUzYzIuODE0IDAgNC4yMi0xLjY4IDQuMjItNS4wNCAwLTEuNzQ5LS4zNTQtMy4wNDYtMS4wNjQtMy44OTMtLjY4My0uODQ3LTEuNjgtMS4yNy0yLjk5Mi0xLjI3LS41MTkgMC0uOTgzLjA2OC0xLjM5My4yMDUtLjQxLjExLS43NjUuMjQ2LTEuMDY1LjQxdjkuMDE0Yy4zMjguMTY0LjY4My4zIDEuMDY1LjQxLjM4My4xMS43OTIuMTY0IDEuMjMuMTY0Wm0yNC4yOTctMTUuNjUzYzEuMTIgMCAyLjIxMy4xNjQgMy4yNzguNDkyIDEuMDkzLjMgMi4wMzUuNzY1IDIuODI4IDEuMzkzLjgyLS41NDYgMS43MzQtLjk5NyAyLjc0NS0xLjM1MiAxLjAzOC0uMzU1IDIuMjgxLS41MzMgMy43MjktLjUzMyAxLjAzOCAwIDIuMDQ5LjEzNyAzLjAzMi40MSAxLjAxMS4yNzMgMS44OTkuNzEgMi42NjMgMS4zMTEuNzkzLjU3NCAxLjQyMSAxLjM1MiAxLjg4NSAyLjMzNi40NjUuOTU2LjY5NyAyLjEzLjY5NyAzLjUyNHYxMi45MDdjLS4yNzMuMDgyLS43MS4xNjQtMS4zMTEuMjQ2LS41NzQuMDgyLTEuMTc1LjEyMy0xLjgwMy4xMjNhMTAgMTAgMCAwIDEtMS42MzktLjEyMyAyLjc0IDIuNzQgMCAwIDEtMS4xODktLjQ5MiAyLjU1NCAyLjU1NCAwIDAgMS0uNzc4LS45ODNjLS4xNjQtLjQzNy0uMjQ2LS45OTctLjI0Ni0xLjY4di05Ljc5M2MwLS44Mi0uMjMyLTEuNDA3LS42OTctMS43NjItLjQ2NC0uMzgzLTEuMDkyLS41NzQtMS44ODQtLjU3NC0uMzgzIDAtLjc5My4wOTUtMS4yMy4yODctLjQzNy4xNjQtLjc2NC4zNDEtLjk4My41MzIuMDI3LjExLjA0LjIxOS4wNC4zMjh2MTMuODkxYy0uMy4wODItLjc1LjE2NC0xLjM1MS4yNDYtLjU3NC4wODItMS4xNjEuMTIzLTEuNzYyLjEyM3MtMS4xNDgtLjA0MS0xLjY0LS4xMjNhMi43NCAyLjc0IDAgMCAxLTEuMTg4LS40OTIgMi41NSAyLjU1IDAgMCAxLS43NzgtLjk4M2MtLjE2NC0uNDM3LS4yNDYtLjk5Ny0uMjQ2LTEuNjh2LTkuNzkzYzAtLjgyLS4yNi0xLjQwNy0uNzc5LTEuNzYyLS40OTEtLjM4My0xLjA5Mi0uNTc0LTEuODAyLS41NzQtLjQ5MiAwLS45MTUuMDgyLTEuMjcuMjQ2YTcuMTggNy4xOCAwIDAgMC0uOTAyLjQxdjE0LjM4MmMtLjI3My4wODItLjcxLjE2NC0xLjMxMS4yNDZhMTIuNzQgMTIuNzQgMCAwIDEtMS44MDMuMTIzYy0uNjAxIDAtMS4xNDgtLjA0MS0xLjY0LS4xMjNhMi43NCAyLjc0IDAgMCAxLTEuMTg4LS40OTIgMi41NSAyLjU1IDAgMCAxLS43NzgtLjk4M2MtLjE2NC0uNDM3LS4yNDYtLjk5Ny0uMjQ2LTEuNjhWNzMuNTUzYzAtLjczNy4xNS0xLjMyNS40NS0xLjc2Mi4zMjktLjQzNy43NjYtLjg0NyAxLjMxMi0xLjIzLjkyOS0uNjU1IDIuMDc2LTEuMTg4IDMuNDQyLTEuNTk3YTE1LjMxMiAxNS4zMTIgMCAwIDEgNC4zNDMtLjYxNVoiLz48L3N2Zz4K) **PNG:** ![](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOEAAACgCAYAAAD6twuzAAAIMUlEQVR4nO2d76tkdR3Hz0KLtHG1rEBKrVyxIjJ1xJQCr7Tsema+78/cRW8P+oFo1KIbi/gjUCF3C38gi4Ig+xf0g+teZQ0plkAoIh8UaQ8kRHb1gZWUIFurd++K44M7wnWcOffMnTNzPsfP6wWvBwszXz5zzvfFmTvDmc0yAIC6WVnOjp5aznpNtnckm1v/mnpL2dl1zzSxh7OnB8/V6nK2p/a5JnT1iezG2e3uhkCETiXCOBChU4kwDkToVCKMAxE6lQjjQIROJcI4EKFTiTAOROhUIowDETqVCONAhE4lwjgQoVOJMA5E6FQijAMROpUI40CETiXCOBChU4kwDkToVCKMAxE6lQjjQIROJcI4EKFTiTAOROhUIowDETqVCONAhE4lwjgQoVOJMA5E6FQijAMROpUI40CETiXCOBChU4kwDkToVCKMAxE6lQjjQIROJcI4EKFTiTAOROhUIowDETqVCONAhE4lwjgQoVOJMA5E6FQijAMROpUI40CETiXCOBChU4kwDkToVCKMAxE6lQjjQIROJcI4EKFTiTAOROhUIowDETqVCONAhE4lwjgQoVOJMA5E6FQijMPqcnZw5XD2TJPt/Sbbtv419Y5kc3XPNKmnlrMHB8/VyuFMdc81qaefyK6d3e4GAAAAAAAAgFpIKc032W63+9XB19Q7kn3m9OPZfJPtLWXn1LEfYMbs2rXrbDPrNVlJfEUBzYUI/UqEQSBCvxJhEIjQr0QYBCL0KxEGgQj9SoRBIEK/EmEQiNCvRBgEIvQrEQaBCP1KhEEgQr8SYRCI0K9EGAQi9CsRBoEI/bqpCNvt9jmdTmeXpD0ppTsl3S3pFknfNrMvZlm2ZdJN0+12z5PUNbMfmdlPzOyulNJeSdd1Op0LJll7FvPneb7dzBb7694t6db+v88f8ZQtZnaxmd1gZre9N5OZXWNmcyOeUxoi9GvpCCV9ysz2S3qhxMF63cwOmdnF42wUSZdJetTM/lnipBw3s3vzPD/Ty/xmdrmkx8zstQ3W/6uZ3ZBl2ZZOp/MJSQck/avg8W9J+kWe59vHmWc9ROjXUhGa2Q/N7H+bOGjvSHpM0rai9VNKnzWzpU2enFclXe1g/sc3MfuzZvbfMeZZMbPFDU/YEIjQrxtGKOm6Cg7gX2zEW6qFhYXPW7krX9HJOZlSuqqO+fM83150FZuCb5vZN0p09z6I0K8bRmhmf6joAP4+G/K3lqRfVrT+C61Wa+us57fNXQEnneX5sQrMiNCzZa6Exyo8kN8bson/UeFJymc9v6QX69iQKaWvEWGcCF8uODD3d7vdr/f/JrpU0gOSThccxGPjrC/paUldSV/qdDoXSPqBmZ0oePwjzuZ/OKV0Rbvd/lz/k9eRb7slnTSzu9rt9kVmdqGkfUWzmNnNREiEvYWFhY8Pefx3ig5ku92+pOz67Xb7A79CJemOgvWXPM+/wd+nfxucxdY+oR21IQ8UnrgBiNCvlUfYf87zo56TUrqz7PrDIux2uzsKTtRvPc/fv8qN2mDPDZljX8HjDw4/Y8MhQr9OK8JHCg7ko2XXHxZhSmm+4ET9zvP8ZnbhOBGa2Y+JkAg3u4mL3jL+quz6NUY4lfmJkAhnFqGZ3V5wMJfKrl9XhNOanwiJcJZXwocLDuahsuvXeCWcyvxESISzvBL+veBA/rTs+jVeCacyPxES4UwiTCnduMHBvKbs+nVEOM35iZAIK4/QzH4u6UpJX5D0Ta3dAfF2weNP5Hl+xmY3cZZVG+Gs5ydCIpxGhON6/zjrzyDCmc5PhERYd4Sv7t69+5NDNtrxcSKUdHVNEU48f/9G39IRppT2EiERVrWJ30wpXTFi/efGidDMLq0hwkrmz/P80+NEKOn7REiEE29iScckXVaw/oFxImy1Wls1+s6IyiOsen5Jfy4bYZ7n59qIm5GJcI3wEUp6p+CgvSTp1p07d36saP35+fmPmNlDkl6RtNL332b2px07dpw1YqavSHpK0utau9PgRD+W+7zPL+l8Sb+W9B9JpyX9vz/joWHrp5S+JemPZvaGrX1o9Iat3f51U9FcgxChXyeKsNPpfFlrtxrtk3RPSmlvSul6jf4xo5nT9Pmrggj9OlGEw95ueaPp81cFEfqVCINAhH4t8xszx5u8iZs+f1UQoV/LXAnH+grBG02fvyqI0K9lIvxZkzdx0+evCiL064YRtlqtrWb2kJkd19ovQZ/sfxx/tOyvX9dJ0+evCiL0K/8hTBCI0K9EGAQi9CsRBoEI/UqEQSBCvxJhEIjQr0QYBCL0KxEGYXFx8aNmtr/hfnfwda0+mbVOLWf7m+zqk9klw84ZAAAAAAAAQEgkHZT0TMPdtv41mdmcg5km9cHBc5VSkoO5JtLMrp3d7m4Iko7W/XF8Bc6tf00f1q8oJO2pe65JTSnxFcUgROhTIgwEEfqUCANBhD4lwkAQoU+JMBBE6FMiDAQR+pQIA0GEPiXCQBChT4kwEEToUyIMBBH6lAgDQYQ+JcJAEKFPiTAQROhTIgwEEfqUCANBhD4lwkAQoU+JMBBE6FMiDAQR+pQIA0GEPiXCQBChT4kwEEToUyIMBBH6lAgDQYQ+JcJAEKFPiTAQROhTIgwEEfqUCANBhD4lwkAQoU+JMBBE6FMiDAQR+pQIA0GEPiXCQBChT4kwEEToUyIMBBH6lAgDQYQ+JcJAEKFPiTAQROhTIgwEEfqUCANBhD4lwkAQoU+JMBBE6FMiDAQR+pQIA0GEPiXCQBChT4kwEEToUyIMBBH6lAgDQYQ+JUIAAAAAgKnzLpMda6atX1zLAAAAAElFTkSuQmCC) Standard logo with no text[​](https://pnpm.io/9.x/logos#standard-logo-with-no-text "Direct link to Standard logo with no text") -------------------------------------------------------------------------------------------------------------------------------- **SVG:** ![](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWlkWU1pZCBtZWV0IiB2aWV3Qm94PSI3Ni41ODk4NzI0NDg5Nzk1OCA0NCAxNjQuMDA3NzU1MTAyMDQwNjggMTY0IiB3aWR0aD0iMTYwLjAxIiBoZWlnaHQ9IjE2MCI+PGRlZnM+PHBhdGggZD0iTTIzNy42IDk1TDE4Ny42IDk1TDE4Ny42IDQ1TDIzNy42IDQ1TDIzNy42IDk1WiIgaWQ9ImFyTlJvSzQzNSI+PC9wYXRoPjxwYXRoIGQ9Ik0xODIuNTkgOTVMMTMyLjU5IDk1TDEzMi41OSA0NUwxODIuNTkgNDVMMTgyLjU5IDk1WiIgaWQ9ImEzSDJXVTdQeCI+PC9wYXRoPjxwYXRoIGQ9Ik0xMjcuNTkgOTVMNzcuNTkgOTVMNzcuNTkgNDVMMTI3LjU5IDQ1TDEyNy41OSA5NVoiIGlkPSJiMURJbk01NnZsIj48L3BhdGg+PHBhdGggZD0iTTIzNy42IDE1MEwxODcuNiAxNTBMMTg3LjYgMTAwTDIzNy42IDEwMEwyMzcuNiAxNTBaIiBpZD0iYTdMRmxnUUl3dSI+PC9wYXRoPjxwYXRoIGQ9Ik0xODIuNTkgMTUwTDEzMi41OSAxNTBMMTMyLjU5IDEwMEwxODIuNTkgMTAwTDE4Mi41OSAxNTBaIiBpZD0iYW13TGlaY3VvIj48L3BhdGg+PHBhdGggZD0iTTE4Mi41OSAyMDVMMTMyLjU5IDIwNUwxMzIuNTkgMTU1TDE4Mi41OSAxNTVMMTgyLjU5IDIwNVoiIGlkPSJmM1BldTVSV2FuIj48L3BhdGg+PHBhdGggZD0iTTIzNy42IDIwNUwxODcuNiAyMDVMMTg3LjYgMTU1TDIzNy42IDE1NUwyMzcuNiAyMDVaIiBpZD0iYTZEWEJmcVBhIj48L3BhdGg+PHBhdGggZD0iTTEyNy41OSAyMDVMNzcuNTkgMjA1TDc3LjU5IDE1NUwxMjcuNTkgMTU1TDEyNy41OSAyMDVaIiBpZD0iYzFHV1NUSDF6NyI+PC9wYXRoPjwvZGVmcz48Zz48Zz48dXNlIHhsaW5rOmhyZWY9IiNhck5Sb0s0MzUiIG9wYWNpdHk9IjEiIGZpbGw9IiNmOWFkMDAiIGZpbGwtb3BhY2l0eT0iMSI+PC91c2U+PC9nPjxnPjx1c2UgeGxpbms6aHJlZj0iI2EzSDJXVTdQeCIgb3BhY2l0eT0iMSIgZmlsbD0iI2Y5YWQwMCIgZmlsbC1vcGFjaXR5PSIxIj48L3VzZT48L2c+PGc+PHVzZSB4bGluazpocmVmPSIjYjFESW5NNTZ2bCIgb3BhY2l0eT0iMSIgZmlsbD0iI2Y5YWQwMCIgZmlsbC1vcGFjaXR5PSIxIj48L3VzZT48L2c+PGc+PHVzZSB4bGluazpocmVmPSIjYTdMRmxnUUl3dSIgb3BhY2l0eT0iMSIgZmlsbD0iI2Y5YWQwMCIgZmlsbC1vcGFjaXR5PSIxIj48L3VzZT48L2c+PGc+PHVzZSB4bGluazpocmVmPSIjYW13TGlaY3VvIiBvcGFjaXR5PSIxIiBmaWxsPSIjNGU0ZTRlIiBmaWxsLW9wYWNpdHk9IjEiPjwvdXNlPjwvZz48Zz48dXNlIHhsaW5rOmhyZWY9IiNmM1BldTVSV2FuIiBvcGFjaXR5PSIxIiBmaWxsPSIjNGU0ZTRlIiBmaWxsLW9wYWNpdHk9IjEiPjwvdXNlPjwvZz48Zz48dXNlIHhsaW5rOmhyZWY9IiNhNkRYQmZxUGEiIG9wYWNpdHk9IjEiIGZpbGw9IiM0ZTRlNGUiIGZpbGwtb3BhY2l0eT0iMSI+PC91c2U+PC9nPjxnPjx1c2UgeGxpbms6aHJlZj0iI2MxR1dTVEgxejciIG9wYWNpdHk9IjEiIGZpbGw9IiM0ZTRlNGUiIGZpbGwtb3BhY2l0eT0iMSI+PC91c2U+PC9nPjwvZz48L3N2Zz4=) **PNG:** ![](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKAAAACgCAYAAACLz2ctAAADNElEQVR4nO3YMYpcRxhG0YoETpQ4MHgPxokXoEgw0K9ggkkcKPcuFCnWOqRpYRA4lZalHgWtTIa2szZ+dWfOBzevn3eiN4bZnju/G89Ox3Eu9+U4Pl/e9fBhvNr7Xdf2cD/+uLzrdD8+7v2uazt/GD8CGAjASAC2AjASgJEAbAVgJAAjAdgKwEgARgKwFYCRAIwEYCsAIwEYCcBWAEYCMBKArQCMBGAkAFsBGAnASAC2AjASgJEAbAVgJAAjAdgKwEgARgKwFYCRAIwEYCsAIwEYCcBWAEYCMBKArQCMBGAkAFsBGAnASAC2AjASgJEAbAVgJAAjAdgKwEgARgKwFYCRAIwEYCsAIwEYCcBWAEYCMBKArQCM9CQAjjHGl/vxqdzD/Xh7+aG+vh8v937X1R3H/AfA43iz+7uu7PzXeH55l5mZmZlZfnPOnw6Hw4tyc86fL+86/Tl++fp+vCi3A4f/f4fD4dWc8xzvafyGeYwDcN0A7ARgdQCuG4CdAKwOwHUDsBOA1QG4bgB2ArA6ANcNwE4AVgfgugHYCcDqAFw3ADsBWB2A6wZgJwCrA3DdAOwEYHUArhuAnQCsDsB1A7ATgNUBuG4AdgKwOgDXDcBOAFYH4LoB2AnA6gBcNwA7AVgdgOsGYCcAqwNw3QDsBGB1AK4bgJ0ArA7AdQOwE4DVAbhuAHYCsDoA1w3ATgBWB+C6AdgJwOoAXDcAOwFYHYDr9lQA/jrnfB3vt8u7Tsfx++k4Xpc7vxs/7GHCzMzMzBbatm2fys053/7LTS/3ftd/cNe8vGvO+Wbvd13bzc3N8+8H3d3dPVvgd8NVbdv2+fJDPdbfMNu2fVzgXVd1e3v7928YAJcOwEIAtgKwE4CFAGwFYCcACwHYCsBOABYCsBWAnQAsBGArADsBWAjAVgB2ArAQgK0A7ARgIQBbAdgJwEIAtgKwE4CFAGwFYCcACwHYCsBOABYCsBWAnQAsBGArADsBWAjAVgB2ArAQgK0A7ARgIQBbAdgJwEIAtgKwE4CFAGwFYCcACwHYCsBOABYCsBWAnQAsBGArADsBWAjAVgB2ArAQgK0A7PT4AZqZmdke+wbo36TP2WmnigAAAABJRU5ErkJggg==) Standard light logo[​](https://pnpm.io/9.x/logos#standard-light-logo "Direct link to Standard light logo") ----------------------------------------------------------------------------------------------------------- **SVG:** > ![](https://pnpm.io/assets/images/pnpm-light-477811893d2e1c4ad4b10345c442282e.svg) **PNG:** > ![](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOEAAACgCAYAAAD6twuzAAAHrklEQVR4nO3d3Ytcdx3H8RMwKJFEiwrFh6qN+IBQbSlVUWiKQvCmXmi98IGiRSVWgqgVrKCNYqVWWihI/gIfSDdCfahWhIIieqHY9qKISKIXtS1VKNXoJim+vTh7ETZnzszsObPzOf2+3/C9CJz55bsz82J3Z5ndpjEzW3ebG80DZ082THm4vzlw4cfET5pL1r3T0NncaO7f/lid22iOrHuvoXNuo7lx957dE0mEmSPCQokwc0RYKBFmjggLJcLMEWGhRJg5IiyUCDNHhIUSYeaIsFAizBwRFkqEmSPCQokwc0RYKBFmjggLJcLMEWGhRJg5IiyUCDNHhIUSYeaIsFAizBwRFkqEmSPCQokwc0RYKBFmjggLJcLMEWGhRJg5IiyUCDNHhIUSYeaIsFAizBwRFkqEmSPCQokwc0RYKBFmjggLJcLMEWGhRJg5IiyUCDNHhIUSYeaIsFAizBwRFkqEmSPCQokwc0RYKBFmjggLJcLMEWGhRJg5IiyUCDNHhIUSYeaIsFAizBwRFkqEmSPCQokwc0RYKBFmjggLJcLMEWGhRJg5IiyUCDNHhIUSYeaIsFBnN5o7NzeaB6c8/LjZd+HHxH3N/nXvNHTOnmzu2P5YbZ5srl/3XkPn/EZzePee3WZmZmZmZma2loBDE58rLvqY7mtefv7e5tCUhxPNpet4PtguB1zC9PNHFDbdEGHsiLBIiDB2RFgkRBg7IiwSIowdERYJEcaOCIuECGNHhEVChLEjwiIhwtgRYZEQYeyIsEiIMHZEWCREGDsiLBIijB0RFgkRxs6OEAKXAoeBTwG3ALcCnwY+CLwB2DPCk+ZVwPuATwJfBL4E3Ay8H7h84Nm7sf9B4Iatc28FPrv178tmXL8HuAK4EfjcBTtdB+wfYR8Rhs7CCIGXArcBjy5wZ/0TOE7H+7/m/B9XAfcAf1/g/zgNfBU4MP/kXdv/auA7wJNzzv8DLbY9tDiOAY/3XP9f4LvAwWX22babCENnIYTAJ4B/7eBO+x/tk3LfnPNfAZzY4QPzGHBtwP737uD83wH/WOL6TeCGuQ9Y944iDJ25CGm//Bva75nxJRXwGhb7zNfXGeAda9r/IP2fxcbuWeCdC7jbvqcIQ2cRhL8a6Q78JR3fawHfG+n8R4G9a9h/J58Bh/bwkgZFGDyLIDw14p34kY7z/zTi+e9dw/5/HvH8ZXqLCOsg/GvPnXI78Dba74muBL4JnO+5/tSS5/+U9hXSNwKXAzcBz/Rcf3fY/ncB1wCvpn3lte/L7jO0rwC/HngdcHTOLkdEKEKAF3dc/6E5d+Rblzj/ot9CBXyh5/oTyfvT//3pHzt2Od5z/bHeB+7is0QYOqMj3LrNwz23uWWJ87sQvqfn+p8l70/7WW5WD3XscbTn+m93P2LdIcLYWRXCu3tuc88S53chPNRz/c+T96f9MnNWXQg/03O9CBsRwuwncd+XjN9f4vx1IVzJ/ohwaCLsaNaT+PM9tzmxxPnrQriS/RHh0ETY0awn8V09tzm+xPnrQriS/RHh0ETY0awn8SM9t/nKEuevC+FK9keEQxNhR10v8X9szh153RLn7zrCVe6PCIcmwo6+DrwdeC3wLtp3QDzbc/0zwPN3+iTeun5MhLu6PyIcmghH6PYlz181wl3dHxEOTYQDewx4Scf5p3tu04Xw2p7rV4lw8P6077iYVRfCm3uuF2EjwmX6D3DNjPMf6rldF8Ire65fFcJR9gde1nNtF8KP9lwvwkaEi3YKuKrn/GM9t+1CuJfZ74xYBcKx9//tjGu7EL6S2W9GFmEjQmjfeT6rv9D+XpUXzjn/ecC3gL/RvnN8E3gC+A3wohm3eTPwI9pfQ3Ge9gWTU8A30vcHLgN+ADy1tfu/t3Y8PuP8dwO/Bp6mfdHoadq3f328b6+Oc0QYOkMRvon2rUZHgS/Tfg/zAWb8MqN1NPX9xwoRxs5QhPF/8H7q+48VIowdERYJEcbOIghP99wp8U/iqe8/VogwdhZBuNSPENKa+v5jhQhjZxGEX+u5U+KfxFPff6wQYewsgnAv7Uvwp2l/E/QZ2pfjf8GCv/16nU19/7FChLHjH4QpEiKMHREWCRHGjgiLhAhjR4RFQoSxI8IiIcLYEWGREGHsiLBIwAto/0jqlOfD2z+ucxvN1WdPNrdNec79sFnqj/uYmZmZmZmZPacD7gQenPjs2/Yx7Q/Yaejc0fFYXR+w19A5vHvP7okEPMD0O7DtY3pO/ogCOLLupUbIH1FsDxGmJsIqIcLURFglRJiaCKuECFMTYZUQYWoirBIiTE2EVUKEqYmwSogwNRFWCRGmJsIqIcLURFglRJiaCKuECFMTYZUQYWoirBIiTE2EVUKEqYmwSogwNRFWCRGmJsIqIcLURFglRJiaCKuECFMTYZUQYWoirBIiTE2EVUKEqYmwSogwNRFWCRGmJsIqIcLURFglRJiaCKuECFMTYZUQYWoirBIiTE2EVUKEqYmwSogwNRFWCRGmJsIqIcLURFglRJiaCKuECFMTYZUQYWoirBIiTE2EVUKEqYmwSogwNRFWCRGmJsIqIcLURFglRJiaCKuECFMTYZUQYWoirBIiTE2EVUKEqYnQzMzMzGy1/R/J5EIfR2HYOQAAAABJRU5ErkJggg==) Standard light logo with no text[​](https://pnpm.io/9.x/logos#standard-light-logo-with-no-text "Direct link to Standard light logo with no text") -------------------------------------------------------------------------------------------------------------------------------------------------- **SVG:** > ![](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWlkWU1pZCBtZWV0IiB2aWV3Qm94PSI3Ni41ODk4NzI0NDg5Nzk1OCA0NCAxNjQuMDA3NzU1MTAyMDQwNjggMTY0IiB3aWR0aD0iMTYwLjAxIiBoZWlnaHQ9IjE2MCI+PGRlZnM+PHBhdGggZD0iTTIzNy42IDk1TDE4Ny42IDk1TDE4Ny42IDQ1TDIzNy42IDQ1TDIzNy42IDk1WiIgaWQ9ImI0NXZkVEQ4aHMiPjwvcGF0aD48cGF0aCBkPSJNMTgyLjU5IDk1TDEzMi41OSA5NUwxMzIuNTkgNDVMMTgyLjU5IDQ1TDE4Mi41OSA5NVoiIGlkPSJhNDBXdHhJbDhkIj48L3BhdGg+PHBhdGggZD0iTTEyNy41OSA5NUw3Ny41OSA5NUw3Ny41OSA0NUwxMjcuNTkgNDVMMTI3LjU5IDk1WiIgaWQ9ImgyQ045QUVFcGUiPjwvcGF0aD48cGF0aCBkPSJNMjM3LjYgMTUwTDE4Ny42IDE1MEwxODcuNiAxMDBMMjM3LjYgMTAwTDIzNy42IDE1MFoiIGlkPSJkcXY1MTMzRzgiPjwvcGF0aD48cGF0aCBkPSJNMTgyLjU5IDE1MEwxMzIuNTkgMTUwTDEzMi41OSAxMDBMMTgyLjU5IDEwMEwxODIuNTkgMTUwWiIgaWQ9ImIxTHY3OXlwdm0iPjwvcGF0aD48cGF0aCBkPSJNMTgyLjU5IDIwNUwxMzIuNTkgMjA1TDEzMi41OSAxNTVMMTgyLjU5IDE1NUwxODIuNTkgMjA1WiIgaWQ9Imh5MUlaV3dMWCI+PC9wYXRoPjxwYXRoIGQ9Ik0yMzcuNiAyMDVMMTg3LjYgMjA1TDE4Ny42IDE1NUwyMzcuNiAxNTVMMjM3LjYgMjA1WiIgaWQ9ImFrUWZqeFFlcyI+PC9wYXRoPjxwYXRoIGQ9Ik0xMjcuNTkgMjA1TDc3LjU5IDIwNUw3Ny41OSAxNTVMMTI3LjU5IDE1NUwxMjcuNTkgMjA1WiIgaWQ9ImJkU3J3RTVwayI+PC9wYXRoPjwvZGVmcz48Zz48Zz48dXNlIHhsaW5rOmhyZWY9IiNiNDV2ZFREOGhzIiBvcGFjaXR5PSIxIiBmaWxsPSIjZjlhZDAwIiBmaWxsLW9wYWNpdHk9IjEiPjwvdXNlPjwvZz48Zz48dXNlIHhsaW5rOmhyZWY9IiNhNDBXdHhJbDhkIiBvcGFjaXR5PSIxIiBmaWxsPSIjZjlhZDAwIiBmaWxsLW9wYWNpdHk9IjEiPjwvdXNlPjwvZz48Zz48dXNlIHhsaW5rOmhyZWY9IiNoMkNOOUFFRXBlIiBvcGFjaXR5PSIxIiBmaWxsPSIjZjlhZDAwIiBmaWxsLW9wYWNpdHk9IjEiPjwvdXNlPjwvZz48Zz48dXNlIHhsaW5rOmhyZWY9IiNkcXY1MTMzRzgiIG9wYWNpdHk9IjEiIGZpbGw9IiNmOWFkMDAiIGZpbGwtb3BhY2l0eT0iMSI+PC91c2U+PC9nPjxnPjx1c2UgeGxpbms6aHJlZj0iI2IxTHY3OXlwdm0iIG9wYWNpdHk9IjEiIGZpbGw9IiNmZmZmZmYiIGZpbGwtb3BhY2l0eT0iMSI+PC91c2U+PC9nPjxnPjx1c2UgeGxpbms6aHJlZj0iI2h5MUlaV3dMWCIgb3BhY2l0eT0iMSIgZmlsbD0iI2ZmZmZmZiIgZmlsbC1vcGFjaXR5PSIxIj48L3VzZT48L2c+PGc+PHVzZSB4bGluazpocmVmPSIjYWtRZmp4UWVzIiBvcGFjaXR5PSIxIiBmaWxsPSIjZmZmZmZmIiBmaWxsLW9wYWNpdHk9IjEiPjwvdXNlPjwvZz48Zz48dXNlIHhsaW5rOmhyZWY9IiNiZFNyd0U1cGsiIG9wYWNpdHk9IjEiIGZpbGw9IiNmZmZmZmYiIGZpbGwtb3BhY2l0eT0iMSI+PC91c2U+PC9nPjwvZz48L3N2Zz4=) **PNG:** > ![](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKAAAACgCAYAAACLz2ctAAADI0lEQVR4nO3YIY5VWRSG0aNIMBhEJ8yBYBgACskAWuB7Fig044B6pBOStjAsXiF2W/Io9wj3fFXrS35/du5Sdy3pyObjenQ+rSnv+2l9u7zr9vN6e/S7rt3tzfrn8q7zzfpy9Luu3XxeTwEMDMDIAGwNwMgAjAzA1gCMDMDIAGwNwMgAjAzA1gCMDMDIAGwNwMgAjAzA1gCMDMDIAGwNwMgAjAzA1gCMDMDIAGwNwMgAjAzA1gCMDMDIAGwNwMgAjAzA1gCMDMDIAGwNwMgAjAzA1gCMDMDIAGwNwMgAjAzA1gCMDMDIAGwNwMgAjAzA1gCMDMDIAGwNwMgAjAzA1gCMDMDIAGwNwMgAjAzA1gCMDMDIAGwNwMgeBMC11vp+s76Wd3uzPlx+qB+f1uuj33X1TuvNLwBP6/3h77py8996cnmXJEmSlG9m/pqZV/E9u7zr/O96/uPTelXeARz+fDPzdvo9jN8w97EBcNsB2AnAagPgtgOwE4DVBsBtB2AnAKsNgNsOwE4AVhsAtx2AnQCsNgBuOwA7AVhtANx2AHYCsNoAuO0A7ARgtQFw2wHYCcBqA+C2A7ATgNUGwG0HYCcAqw2A2w7ATgBWGwC3HYCdAKw2AG47ADsBWG0A3HYAdgKw2gC47QDsBGC1AXDbAdgJwGoD4LYDsBOA1QbAbQdgJwCrDYDbDsBOAFYbALcdgJ0ArDYAbjsAOwFYbQDcdgB2ArDaALjtHgrAFzPzLr6Xl3edT+vv82m9K28+rsdHmJAkSdJGzczX+D7ccdPrDd517d7ccdf7Dd517Z78fNCj6fftjg91L3/DzMyXox/1G3r680EA7huAkQBsBWAkACMB2ArASABGArAVgJEAjARgKwAjARgJwFYARgIwEoCtAIwEYCQAWwEYCcBIALYCMBKAkQBsBWAkACMB2ArASABGArAVgJEAjARgKwAjARgJwFYARgIwEoCtAIwEYCQAWwEYCcBIALYCMBKAkQBsBWAkACMB2ArASABGArAVgJEAjARgKwAjARgJwFYARgIwEoCtAIwEYCQAWwEY6f4DlCRJR/Q/zoV3IvK4wkkAAAAASUVORK5CYII=) * [Standard logo](https://pnpm.io/9.x/logos#standard-logo) * [Standard logo with no text](https://pnpm.io/9.x/logos#standard-logo-with-no-text) * [Standard light logo](https://pnpm.io/9.x/logos#standard-light-logo) * [Standard light logo with no text](https://pnpm.io/9.x/logos#standard-light-logo-with-no-text) --- # Motivation | pnpm [Skip to main content](https://pnpm.io/9.x/motivation#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/motivation) ** (10.x). Version: 9.x On this page Saving disk space[​](https://pnpm.io/9.x/motivation#saving-disk-space "Direct link to Saving disk space") ---------------------------------------------------------------------------------------------------------- ![An illustration of the pnpm content-addressable store. On the illustration there are two projects with node_modules. The files in the node_modules directories are hard links to the same files in the content-addressable store.](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgeG1sbnM6eGw9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjExMC41IDEyMSA2NTkuMjk0NCAyNzIuODM1OTQiIHdpZHRoPSI2NTkuMjk0NCIgaGVpZ2h0PSIyNzIuODM1OTQiPgogIDxkZWZzPgogICAgPG1hcmtlciBvcmllbnQ9ImF1dG8iIG92ZXJmbG93PSJ2aXNpYmxlIiBtYXJrZXJVbml0cz0ic3Ryb2tlV2lkdGgiIGlkPSJGaWxsZWRBcnJvd19NYXJrZXIiIHN0cm9rZS1saW5lam9pbj0ibWl0ZXIiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgdmlld0JveD0iLTEgLTQgMTAgOCIgbWFya2VyV2lkdGg9IjEwIiBtYXJrZXJIZWlnaHQ9IjgiIGNvbG9yPSIjN2Y4MDgwIj4KICAgICAgPGc+CiAgICAgICAgPHBhdGggZD0iTSA4IDAgTCAwIC0zIEwgMCAzIFoiIGZpbGw9ImN1cnJlbnRDb2xvciIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMSIvPgogICAgICA8L2c+CiAgICA8L21hcmtlcj4KICA8L2RlZnM+CiAgPGcgaWQ9IkNhbnZhc18xIiBzdHJva2UtZGFzaGFycmF5PSJub25lIiBmaWxsPSJub25lIiBzdHJva2Utb3BhY2l0eT0iMSIgZmlsbC1vcGFjaXR5PSIxIiBzdHJva2U9Im5vbmUiPgogICAgPHRpdGxlPkNhbnZhcyAxPC90aXRsZT4KICAgIDxyZWN0IGZpbGw9IndoaXRlIiB4PSIxMTAuNSIgeT0iMTIxIiB3aWR0aD0iNjU5LjI5NDQiIGhlaWdodD0iMjcyLjgzNTk0Ii8+CiAgICA8ZyBpZD0iQ2FudmFzXzFfTGF5ZXJfMSI+CiAgICAgIDx0aXRsZT5MYXllciAxPC90aXRsZT4KICAgICAgPGcgaWQ9IkdyYXBoaWNfNjMiPgogICAgICAgIDxyZWN0IHg9IjM4Ny4zOTcyIiB5PSIxNTcuMzM1OTQiIHdpZHRoPSIxMDUuNSIgaGVpZ2h0PSIzOC41IiBmaWxsPSJ3aGl0ZSIvPgogICAgICAgIDxyZWN0IHg9IjM4Ny4zOTcyIiB5PSIxNTcuMzM1OTQiIHdpZHRoPSIxMDUuNSIgaGVpZ2h0PSIzOC41IiBzdHJva2U9ImJsYWNrIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMSIvPgogICAgICAgIDx0ZXh0IHRyYW5zZm9ybT0idHJhbnNsYXRlKDM5Mi4zOTcyIDE2NS45MTc5NykiIGZpbGw9ImJsYWNrIj4KICAgICAgICAgIDx0c3BhbiBmb250LWZhbWlseT0iTW9uYWNvIiBmb250LXNpemU9IjE2IiBmaWxsPSJibGFjayIgeD0iNC41NDI5NjkiIHk9IjE2Ij4wMDAwMDAwMDE8L3RzcGFuPgogICAgICAgIDwvdGV4dD4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY182MiI+CiAgICAgICAgPHJlY3QgeD0iMzg3LjM5NzIiIHk9IjE5NS44MzU5NCIgd2lkdGg9IjEwNS41IiBoZWlnaHQ9IjM4LjUiIGZpbGw9IiNjMGZmZmYiLz4KICAgICAgICA8cmVjdCB4PSIzODcuMzk3MiIgeT0iMTk1LjgzNTk0IiB3aWR0aD0iMTA1LjUiIGhlaWdodD0iMzguNSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjEiLz4KICAgICAgICA8dGV4dCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgzOTIuMzk3MiAyMDQuNDE3OTcpIiBmaWxsPSJibGFjayI+CiAgICAgICAgICA8dHNwYW4gZm9udC1mYW1pbHk9Ik1vbmFjbyIgZm9udC1zaXplPSIxNiIgZmlsbD0iYmxhY2siIHg9IjQuNTQyOTY5IiB5PSIxNiI+MDAwMDAwMDAyPC90c3Bhbj4KICAgICAgICA8L3RleHQ+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfNjEiPgogICAgICAgIDxyZWN0IHg9IjM4Ny4zOTcyIiB5PSIyMzQuMzM1OTQiIHdpZHRoPSIxMDUuNSIgaGVpZ2h0PSIzOC41IiBmaWxsPSJ3aGl0ZSIvPgogICAgICAgIDxyZWN0IHg9IjM4Ny4zOTcyIiB5PSIyMzQuMzM1OTQiIHdpZHRoPSIxMDUuNSIgaGVpZ2h0PSIzOC41IiBzdHJva2U9ImJsYWNrIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMSIvPgogICAgICAgIDx0ZXh0IHRyYW5zZm9ybT0idHJhbnNsYXRlKDM5Mi4zOTcyIDI0Mi45MTc5NykiIGZpbGw9ImJsYWNrIj4KICAgICAgICAgIDx0c3BhbiBmb250LWZhbWlseT0iTW9uYWNvIiBmb250LXNpemU9IjE2IiBmaWxsPSJibGFjayIgeD0iNC41NDI5NjkiIHk9IjE2Ij4wMDAwMDAwMDQ8L3RzcGFuPgogICAgICAgIDwvdGV4dD4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY182MCI+CiAgICAgICAgPHJlY3QgeD0iMzg3LjM5NzIiIHk9IjI3Mi44MzU5NCIgd2lkdGg9IjEwNS41IiBoZWlnaHQ9IjM4LjUiIGZpbGw9IndoaXRlIi8+CiAgICAgICAgPHJlY3QgeD0iMzg3LjM5NzIiIHk9IjI3Mi44MzU5NCIgd2lkdGg9IjEwNS41IiBoZWlnaHQ9IjM4LjUiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIxIi8+CiAgICAgICAgPHRleHQgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMzkyLjM5NzIgMjgxLjQxNzk3KSIgZmlsbD0iYmxhY2siPgogICAgICAgICAgPHRzcGFuIGZvbnQtZmFtaWx5PSJNb25hY28iIGZvbnQtc2l6ZT0iMTYiIGZpbGw9ImJsYWNrIiB4PSI0LjU0Mjk2OSIgeT0iMTYiPjAwMDAwMDAwNTwvdHNwYW4+CiAgICAgICAgPC90ZXh0PgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzU5Ij4KICAgICAgICA8cmVjdCB4PSIzODcuMzk3MiIgeT0iMzExLjMzNTk0IiB3aWR0aD0iMTA1LjUiIGhlaWdodD0iMzguNSIgZmlsbD0iI2ZmZmZjMCIvPgogICAgICAgIDxyZWN0IHg9IjM4Ny4zOTcyIiB5PSIzMTEuMzM1OTQiIHdpZHRoPSIxMDUuNSIgaGVpZ2h0PSIzOC41IiBzdHJva2U9ImJsYWNrIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMSIvPgogICAgICAgIDx0ZXh0IHRyYW5zZm9ybT0idHJhbnNsYXRlKDM5Mi4zOTcyIDMxOS45MTc5NykiIGZpbGw9ImJsYWNrIj4KICAgICAgICAgIDx0c3BhbiBmb250LWZhbWlseT0iTW9uYWNvIiBmb250LXNpemU9IjE2IiBmaWxsPSJibGFjayIgeD0iNC41NDI5NjkiIHk9IjE2Ij4wMDAwMDAwMDY8L3RzcGFuPgogICAgICAgIDwvdGV4dD4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY181OCI+CiAgICAgICAgPHJlY3QgeD0iMzg3LjM5NzIiIHk9IjM0OS44MzU5NCIgd2lkdGg9IjEwNS41IiBoZWlnaHQ9IjM4LjUiIGZpbGw9IiNjMGZmYzAiLz4KICAgICAgICA8cmVjdCB4PSIzODcuMzk3MiIgeT0iMzQ5LjgzNTk0IiB3aWR0aD0iMTA1LjUiIGhlaWdodD0iMzguNSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjEiLz4KICAgICAgICA8dGV4dCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgzOTIuMzk3MiAzNTguNDE3OTcpIiBmaWxsPSJibGFjayI+CiAgICAgICAgICA8dHNwYW4gZm9udC1mYW1pbHk9Ik1vbmFjbyIgZm9udC1zaXplPSIxNiIgZmlsbD0iYmxhY2siIHg9IjQuNTQyOTY5IiB5PSIxNiI+MDAwMDAwMDA3PC90c3Bhbj4KICAgICAgICA8L3RleHQ+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfNTciPgogICAgICAgIDxyZWN0IHg9IjEzMy44MzcxOSIgeT0iMTk1LjgzNTk0IiB3aWR0aD0iMTg0LjU2IiBoZWlnaHQ9IjM4LjUiIGZpbGw9IiNjMGZmZmYiLz4KICAgICAgICA8cmVjdCB4PSIxMzMuODM3MTkiIHk9IjE5NS44MzU5NCIgd2lkdGg9IjE4NC41NiIgaGVpZ2h0PSIzOC41IiBzdHJva2U9ImJsYWNrIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMSIvPgogICAgICAgIDx0ZXh0IHRyYW5zZm9ybT0idHJhbnNsYXRlKDEzOC44MzcxOSAyMDQuNDE3OTcpIiBmaWxsPSJibGFjayI+CiAgICAgICAgICA8dHNwYW4gZm9udC1mYW1pbHk9Ik1vbmFjbyIgZm9udC1zaXplPSIxNiIgZmlsbD0iYmxhY2siIHg9IjAiIHk9IjE2Ij5pcy1vZGQvaW5kZXguanM8L3RzcGFuPgogICAgICAgIDwvdGV4dD4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY181NiI+CiAgICAgICAgPHJlY3QgeD0iMTMzLjgzNzE5IiB5PSIyMzQuMzM1OTQiIHdpZHRoPSIxODQuNTYiIGhlaWdodD0iMzguNSIgZmlsbD0iI2MwZmZjMCIvPgogICAgICAgIDxyZWN0IHg9IjEzMy44MzcxOSIgeT0iMjM0LjMzNTk0IiB3aWR0aD0iMTg0LjU2IiBoZWlnaHQ9IjM4LjUiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIxIi8+CiAgICAgICAgPHRleHQgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTM4LjgzNzE5IDI0Mi45MTc5NykiIGZpbGw9ImJsYWNrIj4KICAgICAgICAgIDx0c3BhbiBmb250LWZhbWlseT0iTW9uYWNvIiBmb250LXNpemU9IjE2IiBmaWxsPSJibGFjayIgeD0iMCIgeT0iMTYiPmlzLW9kZC9MSUNFTlNFLm1kPC90c3Bhbj4KICAgICAgICA8L3RleHQ+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfNTUiPgogICAgICAgIDxyZWN0IHg9IjU2MS44OTcyIiB5PSIxOTUuODM1OTQiIHdpZHRoPSIxODQuNTYiIGhlaWdodD0iMzguNSIgZmlsbD0iI2ZmZmZjMCIvPgogICAgICAgIDxyZWN0IHg9IjU2MS44OTcyIiB5PSIxOTUuODM1OTQiIHdpZHRoPSIxODQuNTYiIGhlaWdodD0iMzguNSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjEiLz4KICAgICAgICA8dGV4dCB0cmFuc2Zvcm09InRyYW5zbGF0ZSg1NjYuODk3MiAyMDQuNDE3OTcpIiBmaWxsPSJibGFjayI+CiAgICAgICAgICA8dHNwYW4gZm9udC1mYW1pbHk9Ik1vbmFjbyIgZm9udC1zaXplPSIxNiIgZmlsbD0iYmxhY2siIHg9IjAiIHk9IjE2Ij5pcy1ldmVuL2luZGV4LmpzPC90c3Bhbj4KICAgICAgICA8L3RleHQ+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfNTQiPgogICAgICAgIDxyZWN0IHg9IjU2MS44OTcyIiB5PSIyMzQuMzM1OTQiIHdpZHRoPSIxODQuNTYiIGhlaWdodD0iMzguNSIgZmlsbD0iI2MwZmZjMCIvPgogICAgICAgIDxyZWN0IHg9IjU2MS44OTcyIiB5PSIyMzQuMzM1OTQiIHdpZHRoPSIxODQuNTYiIGhlaWdodD0iMzguNSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjEiLz4KICAgICAgICA8dGV4dCB0cmFuc2Zvcm09InRyYW5zbGF0ZSg1NjYuODk3MiAyNDIuOTE3OTcpIiBmaWxsPSJibGFjayI+CiAgICAgICAgICA8dHNwYW4gZm9udC1mYW1pbHk9Ik1vbmFjbyIgZm9udC1zaXplPSIxNiIgZmlsbD0iYmxhY2siIHg9IjAiIHk9IjE2Ij5pcy1ldmVuL0xJQ0VOU0UubWQ8L3RzcGFuPgogICAgICAgIDwvdGV4dD4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY181MyI+CiAgICAgICAgPHRleHQgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMzIwLjEyNzY2IDEzMSkiIGZpbGw9ImJsYWNrIj4KICAgICAgICAgIDx0c3BhbiBmb250LWZhbWlseT0iTW9uYWNvIiBmb250LXNpemU9IjE2IiBmaWxsPSJibGFjayIgeD0iMCIgeT0iMTYiPkNvbnRlbnQtYWRkcmVzc2FibGUgc3RvcmU8L3RzcGFuPgogICAgICAgIDwvdGV4dD4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY181MiI+CiAgICAgICAgPHRleHQgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTIwLjUgMTY5LjUpIiBmaWxsPSJibGFjayI+CiAgICAgICAgICA8dHNwYW4gZm9udC1mYW1pbHk9Ik1vbmFjbyIgZm9udC1zaXplPSIxNiIgZmlsbD0iYmxhY2siIHg9IjAiIHk9IjE2Ij5wcm9qZWN0XzEvbm9kZV9tb2R1bGVzPC90c3Bhbj4KICAgICAgICA8L3RleHQ+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfNDciPgogICAgICAgIDx0ZXh0IHRyYW5zZm9ybT0idHJhbnNsYXRlKDU0OC41NiAxNzIuMzg3OTQpIiBmaWxsPSJibGFjayI+CiAgICAgICAgICA8dHNwYW4gZm9udC1mYW1pbHk9Ik1vbmFjbyIgZm9udC1zaXplPSIxNiIgZmlsbD0iYmxhY2siIHg9IjAiIHk9IjE2Ij5wcm9qZWN0XzIvbm9kZV9tb2R1bGVzPC90c3Bhbj4KICAgICAgICA8L3RleHQ+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkxpbmVfNjQiPgogICAgICAgIDxsaW5lIHgxPSIzMTguMzk3MiIgeTE9IjIxNS4wODU5NCIgeDI9IjM3Ny40OTcyIiB5Mj0iMjE1LjA4NTk0IiBtYXJrZXItZW5kPSJ1cmwoI0ZpbGxlZEFycm93X01hcmtlcikiIHN0cm9rZT0iIzdmODA4MCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjEiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iTGluZV83MSI+CiAgICAgICAgPHBhdGggZD0iTSA1NjEuODk3MiAyMTUuMDg1OTQgTCA1NTEuODk3MiAyMTUuMDg1OTQgTCA1MzEuNTE3NzUgMjE1LjI0MzQgTCA1MTguMDA5OTQgMjE1LjI0MzQgTCA1MTguMDA5OTQgMzMwLjU4NTk0IEwgNTAyLjc5NzIgMzMwLjU4NTk0IiBtYXJrZXItZW5kPSJ1cmwoI0ZpbGxlZEFycm93X01hcmtlcikiIHN0cm9rZT0iIzdmODA4MCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjEiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iTGluZV83MiI+CiAgICAgICAgPHBhdGggZD0iTSAzMTguMzk3MiAyNTMuNTg1OTQgTCAzMjguMzk3MiAyNTMuNTg1OTQgTCAzNTQuNDUxMzQgMjUzLjEwNjcgTCAzNTQuNTQxMiAzNDkuODM1OTQgTCAzNTQuNTQxMiAzNjkuMDg1OTQgTCAzNzcuNDk3MiAzNjkuMDg1OTQiIG1hcmtlci1lbmQ9InVybCgjRmlsbGVkQXJyb3dfTWFya2VyKSIgc3Ryb2tlPSIjN2Y4MDgwIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMSIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJMaW5lXzc0Ij4KICAgICAgICA8cGF0aCBkPSJNIDU2MS44OTcyIDI1My41ODU5NCBMIDU1MS44OTcyIDI1My41ODU5NCBMIDU0MC43MjMyIDI1My44ODc5NCBMIDU0MC43MjMyIDM2OS4wODU5NCBMIDUwMi43OTcyIDM2OS4wODU5NCIgbWFya2VyLWVuZD0idXJsKCNGaWxsZWRBcnJvd19NYXJrZXIpIiBzdHJva2U9IiM3ZjgwODAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIxIi8+CiAgICAgIDwvZz4KICAgIDwvZz4KICA8L2c+Cjwvc3ZnPgo=) When using npm, if you have 100 projects using a dependency, you will have 100 copies of that dependency saved on disk. With pnpm, the dependency will be stored in a content-addressable store, so: 1. If you depend on different versions of the dependency, only the files that differ are added to the store. For instance, if it has 100 files, and a new version has a change in only one of those files, `pnpm update` will only add 1 new file to the store, instead of cloning the entire dependency just for the singular change. 2. All the files are saved in a single place on the disk. When packages are installed, their files are hard-linked from that single place, consuming no additional disk space. This allows you to share dependencies of the same version across projects. As a result, you save a lot of space on your disk proportional to the number of projects and dependencies, and you have a lot faster installations! Boosting installation speed[​](https://pnpm.io/9.x/motivation#boosting-installation-speed "Direct link to Boosting installation speed") ---------------------------------------------------------------------------------------------------------------------------------------- pnpm perfoms installation in three stages: 1. Dependency resolution. All required dependencies are identified and fetched to the store. 2. Directory structure calculation. The `node_modules` directory structure is calculated based on the dependencies. 3. Linking dependencies. All remaining dependencies are fetched and hard linked from the store to `node_modules`. ![An illustration of the pnpm install process. Packages are resolved, fetched, and hard linked as soon as possible.](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bD0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHZpZXdCb3g9IjEzNS4wOTUwNSAxNDA3IDU3NC4zNDg3IDMxNC4zOTYiIHdpZHRoPSI1NzQuMzQ4NyIgaGVpZ2h0PSIzMTQuMzk2Ij4KICA8ZGVmcz4KICAgIDxtYXJrZXIgb3JpZW50PSJhdXRvIiBvdmVyZmxvdz0idmlzaWJsZSIgbWFya2VyVW5pdHM9InN0cm9rZVdpZHRoIiBpZD0iRmlsbGVkQXJyb3dfTWFya2VyIiBzdHJva2UtbGluZWpvaW49Im1pdGVyIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHZpZXdCb3g9Ii0xIC00IDEwIDgiIG1hcmtlcldpZHRoPSIxMCIgbWFya2VySGVpZ2h0PSI4IiBjb2xvcj0iYmxhY2siPgogICAgICA8Zz4KICAgICAgICA8cGF0aCBkPSJNIDggMCBMIDAgLTMgTCAwIDMgWiIgZmlsbD0iY3VycmVudENvbG9yIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIxIi8+CiAgICAgIDwvZz4KICAgIDwvbWFya2VyPgogIDwvZGVmcz4KICA8ZyBpZD0iQ2FudmFzXzEiIHN0cm9rZS1vcGFjaXR5PSIxIiBmaWxsPSJub25lIiBmaWxsLW9wYWNpdHk9IjEiIHN0cm9rZS1kYXNoYXJyYXk9Im5vbmUiIHN0cm9rZT0ibm9uZSI+CiAgICA8dGl0bGU+Q2FudmFzIDE8L3RpdGxlPgogICAgPHJlY3QgZmlsbD0id2hpdGUiIHg9IjEzNS4wOTUwNSIgeT0iMTQwNyIgd2lkdGg9IjU3NC4zNDg3IiBoZWlnaHQ9IjMxNC4zOTYiLz4KICAgIDxnIGlkPSJDYW52YXNfMV9MYXllcl8xIj4KICAgICAgPHRpdGxlPkxheWVyIDE8L3RpdGxlPgogICAgICA8ZyBpZD0iR3JhcGhpY18xNDgiPgogICAgICAgIDxyZWN0IHg9IjE0MS41OTUwNSIgeT0iMTQ0NS40NDgiIHdpZHRoPSI4Mi4xMjU5MiIgaGVpZ2h0PSIyMiIgZmlsbD0iIzYwZDkzNiIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzE0NyI+CiAgICAgICAgPHJlY3QgeD0iMjIzLjcyMDk3IiB5PSIxNDQ1LjQ0OCIgd2lkdGg9IjEwMC41NjIzNSIgaGVpZ2h0PSIyMiIgZmlsbD0iIzAwYTJmZiIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzE0NiI+CiAgICAgICAgPHJlY3QgeD0iNTA3LjM5MDYiIHk9IjE0NDUuNDQ4IiB3aWR0aD0iNDguNjA1MTM0IiBoZWlnaHQ9IjIyIiBmaWxsPSIjZmVhZTAwIi8+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfMTQ1Ij4KICAgICAgICA8cmVjdCB4PSIxNDEuNTk1MDUiIHk9IjE0NzIuNDQ4IiB3aWR0aD0iNDEuMDYyOTYiIGhlaWdodD0iMjIiIGZpbGw9IiM2MGQ5MzYiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xNDQiPgogICAgICAgIDxyZWN0IHg9IjE4Mi42NTgiIHk9IjE0NzIuNDQ4IiB3aWR0aD0iNjguMjU1MDIiIGhlaWdodD0iMjIiIGZpbGw9IiMwMGEyZmYiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xNDMiPgogICAgICAgIDxyZWN0IHg9IjIyMy43MjA5NyIgeT0iMTQ5OS40NDgiIHdpZHRoPSI0OC42MDUxMzQiIGhlaWdodD0iMjIiIGZpbGw9IiM2MGQ5MzYiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xNDIiPgogICAgICAgIDxyZWN0IHg9IjIyMy43MjA5NyIgeT0iMTUyNi40NDgiIHdpZHRoPSI4Mi4xMjU5MiIgaGVpZ2h0PSIyMiIgZmlsbD0iIzYwZDkzNiIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzE0MSI+CiAgICAgICAgPHJlY3QgeD0iMjcyLjMyNjEiIHk9IjE1NTMuNDQ4IiB3aWR0aD0iNTguNjYxMzciIGhlaWdodD0iMjIiIGZpbGw9IiM2MGQ5MzYiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xNDAiPgogICAgICAgIDxyZWN0IHg9IjMwNy41MjI5MiIgeT0iMTU4MC40NDgiIHdpZHRoPSI4Mi4xMjU5MiIgaGVpZ2h0PSIyMiIgZmlsbD0iIzYwZDkzNiIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzEzOSI+CiAgICAgICAgPHJlY3QgeD0iMzMwLjk4NzQ3IiB5PSIxNjA3LjQ0OCIgd2lkdGg9IjQxLjA2Mjk2IiBoZWlnaHQ9IjIyIiBmaWxsPSIjNjBkOTM2Ii8+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfMTM4Ij4KICAgICAgICA8cmVjdCB4PSIzMzAuOTg3NDciIHk9IjE2MzQuNDQ4IiB3aWR0aD0iODkuNSIgaGVpZ2h0PSIyMiIgZmlsbD0iIzYwZDkzNiIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzEzNyI+CiAgICAgICAgPHJlY3QgeD0iMjcyLjMyNjEiIHk9IjE0OTkuNDQ4IiB3aWR0aD0iMTkwLjIzMDQ0IiBoZWlnaHQ9IjIyIiBmaWxsPSIjMDBhMmZmIi8+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfMTM2Ij4KICAgICAgICA8cmVjdCB4PSIzMDUuODQ2OSIgeT0iMTUyNi40NDgiIHdpZHRoPSIyOTYuNjU4OTIiIGhlaWdodD0iMjIiIGZpbGw9IiMwMGEyZmYiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xMzUiPgogICAgICAgIDxyZWN0IHg9IjMzMC45ODc0NyIgeT0iMTU1My40NDgiIHdpZHRoPSIxNTguMzg1NyIgaGVpZ2h0PSIyMiIgZmlsbD0iIzAwYTJmZiIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzEzNCI+CiAgICAgICAgPHJlY3QgeD0iMzg5LjY0ODg0IiB5PSIxNTgwLjQ0OCIgd2lkdGg9IjE1MC4wMDU1IiBoZWlnaHQ9IjIyIiBmaWxsPSIjMDBhMmZmIi8+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfMTMzIj4KICAgICAgICA8cmVjdCB4PSIzNzIuMDUwNDMiIHk9IjE2MDcuNDQ4IiB3aWR0aD0iMjQ5LjcyOTgzIiBoZWlnaHQ9IjIyIiBmaWxsPSIjMDBhMmZmIi8+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfMTMyIj4KICAgICAgICA8cmVjdCB4PSI0MjAuNDkzNiIgeT0iMTYzNC40NDgiIHdpZHRoPSIxNTEuMDA1NSIgaGVpZ2h0PSIyMiIgZmlsbD0iIzAwYTJmZiIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzEzMCI+CiAgICAgICAgPHJlY3QgeD0iNTA3LjM5MDYiIHk9IjE0NzIuNDQ4IiB3aWR0aD0iMzIuMjYzNzUzIiBoZWlnaHQ9IjIyIiBmaWxsPSIjZmVhZTAwIi8+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfMTI5Ij4KICAgICAgICA8cmVjdCB4PSI1MDcuMzkwNiIgeT0iMTQ5OS40NDgiIHdpZHRoPSI2OC4yNTUwMiIgaGVpZ2h0PSIyMiIgZmlsbD0iI2ZlYWUwMCIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzEyOCI+CiAgICAgICAgPHJlY3QgeD0iNjAyLjUwNTgiIHk9IjE1MjYuNDQ4IiB3aWR0aD0iMTAwLjU2MjM1IiBoZWlnaHQ9IjIyIiBmaWxsPSIjZmVhZTAwIi8+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfMTI3Ij4KICAgICAgICA8cmVjdCB4PSI1MDcuMzkwNiIgeT0iMTU1My40NDgiIHdpZHRoPSI0Ny43NjcxMTUiIGhlaWdodD0iMjIiIGZpbGw9IiNmZWFlMDAiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xMjYiPgogICAgICAgIDxyZWN0IHg9IjUzOS42NTQzNCIgeT0iMTU4MC40NDgiIHdpZHRoPSIxMDAuNTYyMzUiIGhlaWdodD0iMjIiIGZpbGw9IiNmZWFlMDAiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xMjUiPgogICAgICAgIDxyZWN0IHg9IjYyMS43ODAyNiIgeT0iMTYwNy40NDgiIHdpZHRoPSI1OC42NjEzNyIgaGVpZ2h0PSIyMiIgZmlsbD0iI2ZlYWUwMCIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzEyNCI+CiAgICAgICAgPHJlY3QgeD0iNTcxLjQ5OTEiIHk9IjE2MzQuNDQ4IiB3aWR0aD0iNTguNjYxMzciIGhlaWdodD0iMjIiIGZpbGw9IiNmZWFlMDAiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iTGluZV8xMjMiPgogICAgICAgIDxwYXRoIGQ9Ik0gNTA3LjM5MDYgMTQzMS40NDggTCA1MDcuNTE1IDE0NzEuNDkxNSBMIDUwNy4zOTA2IDE1NDEuMjM3MyBMIDUwNi41MTUgMTY2Ni43NSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2UtZGFzaGFycmF5PSI0LjAsNC4wIiBzdHJva2Utd2lkdGg9IjEiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iTGluZV8xMjIiPgogICAgICAgIDxwYXRoIGQ9Ik0gMTQxLjQ3MDY2IDE0MzEuNDQ4IEwgMTQxLjU5NTA1IDE0NzEuOTIxIEwgMTQxLjQ3MDY2IDE1NDIuNDE0NiBMIDE0MC41OTUwNSAxNjY2Ljc1IiBzdHJva2U9ImJsYWNrIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS1kYXNoYXJyYXk9IjQuMCw0LjAiIHN0cm9rZS13aWR0aD0iMSIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJMaW5lXzEyMSI+CiAgICAgICAgPHBhdGggZD0iTSA3MDIuOTQzOCAxNDMxLjQ0OCBMIDcwMy4wNjgxNSAxNDcxLjA3IEwgNzAyLjk0MzggMTU0MC4wODE3IEwgNzAzLjA2ODE1IDE2NjcuMjUiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLWRhc2hhcnJheT0iNC4wLDQuMCIgc3Ryb2tlLXdpZHRoPSIxIi8+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfMTE2Ij4KICAgICAgICA8dGV4dCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyNzcuMDk2MyAxNDE3KSIgZmlsbD0iYmxhY2siPgogICAgICAgICAgPHRzcGFuIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2EgTmV1ZSIgZm9udC1zaXplPSIxNiIgZmlsbD0iYmxhY2siIHg9IjMxOTc0NDIzZS0yMCIgeT0iMTUiPjE8L3RzcGFuPgogICAgICAgIDwvdGV4dD4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iTGluZV8xMTUiPgogICAgICAgIDxsaW5lIHgxPSIxNDEuNDk0NTMiIHkxPSIxNDM5LjIxNDUiIHgyPSI0MTEuNDk0OTgiIHkyPSIxNDM5LjcyNDYiIG1hcmtlci1lbmQ9InVybCgjRmlsbGVkQXJyb3dfTWFya2VyKSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjEiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iTGluZV8xMTQiPgogICAgICAgIDxsaW5lIHgxPSI0MjMuNTg4NjMiIHkxPSIxNDM5LjQ0OCIgeDI9IjQ5Ny41MTYyNiIgeTI9IjE0MzkuNjY4MiIgbWFya2VyLWVuZD0idXJsKCNGaWxsZWRBcnJvd19NYXJrZXIpIiBzdHJva2U9ImJsYWNrIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMSIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJMaW5lXzExMyI+CiAgICAgICAgPGxpbmUgeDE9IjUwNy40MTQ3IiB5MT0iMTQzOS4yMTc2IiB4Mj0iNjkzLjA2ODIiIHkyPSIxNDM5LjIyNjgiIG1hcmtlci1lbmQ9InVybCgjRmlsbGVkQXJyb3dfTWFya2VyKSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjEiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xMTIiPgogICAgICAgIDx0ZXh0IHRyYW5zZm9ybT0idHJhbnNsYXRlKDQ2MC4yMDM2IDE0MTcpIiBmaWxsPSJibGFjayI+CiAgICAgICAgICA8dHNwYW4gZm9udC1mYW1pbHk9IkhlbHZldGljYSBOZXVlIiBmb250LXNpemU9IjE2IiBmaWxsPSJibGFjayIgeD0iMzE5NzQ0MjNlLTIwIiB5PSIxNSI+MjwvdHNwYW4+CiAgICAgICAgPC90ZXh0PgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzExMSI+CiAgICAgICAgPHRleHQgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNTk5LjgyMzk2IDE0MTcpIiBmaWxsPSJibGFjayI+CiAgICAgICAgICA8dHNwYW4gZm9udC1mYW1pbHk9IkhlbHZldGljYSBOZXVlIiBmb250LXNpemU9IjE2IiBmaWxsPSJibGFjayIgeD0iNi42ODM4NzciIHk9IjE1Ij4zPC90c3Bhbj4KICAgICAgICA8L3RleHQ+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfMTg2Ij4KICAgICAgICA8dGV4dCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNDYuNTk1MDUgMTY3MC45NDgpIiBmaWxsPSJibGFjayI+CiAgICAgICAgICA8dHNwYW4gZm9udC1mYW1pbHk9IkhlbHZldGljYSBOZXVlIiBmb250LXNpemU9IjE2IiBmaWxsPSJibGFjayIgeD0iODUyNjUxM2UtMTkiIHk9IjE1Ij5QYWNrYWdlIGluc3RhbGxhdGlvbiBwcm9ncmVzczo8L3RzcGFuPgogICAgICAgIDwvdGV4dD4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xODUiPgogICAgICAgIDxyZWN0IHg9IjE0MS41OTUwNSIgeT0iMTY5NC4zOTYiIHdpZHRoPSI4OS41IiBoZWlnaHQ9IjIyIiBmaWxsPSIjNjBkOTM2Ii8+CiAgICAgICAgPHRleHQgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTQ2LjU5NTA1IDE2OTYuMTcyKSIgZmlsbD0id2hpdGUiPgogICAgICAgICAgPHRzcGFuIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2EgTmV1ZSIgZm9udC1zaXplPSIxNiIgZmlsbD0id2hpdGUiIHg9IjQuNzkiIHk9IjE1Ij5SZXNvbHZpbmc8L3RzcGFuPgogICAgICAgIDwvdGV4dD4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xODQiPgogICAgICAgIDxyZWN0IHg9IjIzMS4wOTUwNSIgeT0iMTY5NC4zOTYiIHdpZHRoPSI4OS41IiBoZWlnaHQ9IjIyIiBmaWxsPSIjMDBhMmZmIi8+CiAgICAgICAgPHRleHQgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMjM2LjA5NTA1IDE2OTYuMTcyKSIgZmlsbD0id2hpdGUiPgogICAgICAgICAgPHRzcGFuIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2EgTmV1ZSIgZm9udC1zaXplPSIxNiIgZmlsbD0id2hpdGUiIHg9IjguNzgyIiB5PSIxNSI+RmV0Y2hpbmc8L3RzcGFuPgogICAgICAgIDwvdGV4dD4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xODMiPgogICAgICAgIDxyZWN0IHg9IjMyMC41OTUwNSIgeT0iMTY5NC4zOTYiIHdpZHRoPSI4OS41IiBoZWlnaHQ9IjIyIiBmaWxsPSIjZmVhZTAwIi8+CiAgICAgICAgPHRleHQgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMzI1LjU5NTA1IDE2OTYuMTcyKSIgZmlsbD0id2hpdGUiPgogICAgICAgICAgPHRzcGFuIGZvbnQtZmFtaWx5PSJIZWx2ZXRpY2EgTmV1ZSIgZm9udC1zaXplPSIxNiIgZmlsbD0id2hpdGUiIHg9IjE0LjExIiB5PSIxNSI+TGlua2luZzwvdHNwYW4+CiAgICAgICAgPC90ZXh0PgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJMaW5lXzE4OCI+CiAgICAgICAgPHBhdGggZD0iTSA0MjEuMzY5MiAxNDMxLjQ0OCBMIDQyMS40OTM2IDE0NzEuNDkxNSBMIDQyMS4zNjkyIDE1NDEuMjM3MyBMIDQyMC40OTM2IDE2NjYuNzUiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLWRhc2hhcnJheT0iNC4wLDQuMCIgc3Ryb2tlLXdpZHRoPSIxIi8+CiAgICAgIDwvZz4KICAgIDwvZz4KICA8L2c+Cjwvc3ZnPgo=) This approach is significantly faster than the traditional three-stage installation process of resolving, fetching, and writing all dependencies to `node_modules`. ![An illustration of how package managers like Yarn Classic or npm install dependencies.](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgeG1sbnM6eGw9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjE2Ny41OTUwNSAxNzc3IDY5MC4xMTk4IDMxNC4zOTYiIHdpZHRoPSI2OTAuMTE5OCIgaGVpZ2h0PSIzMTQuMzk2Ij4KICA8ZGVmcz4KICAgIDxtYXJrZXIgb3JpZW50PSJhdXRvIiBvdmVyZmxvdz0idmlzaWJsZSIgbWFya2VyVW5pdHM9InN0cm9rZVdpZHRoIiBpZD0iRmlsbGVkQXJyb3dfTWFya2VyIiBzdHJva2UtbGluZWpvaW49Im1pdGVyIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHZpZXdCb3g9Ii0xIC00IDEwIDgiIG1hcmtlcldpZHRoPSIxMCIgbWFya2VySGVpZ2h0PSI4IiBjb2xvcj0iYmxhY2siPgogICAgICA8Zz4KICAgICAgICA8cGF0aCBkPSJNIDggMCBMIDAgLTMgTCAwIDMgWiIgZmlsbD0iY3VycmVudENvbG9yIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIxIi8+CiAgICAgIDwvZz4KICAgIDwvbWFya2VyPgogIDwvZGVmcz4KICA8ZyBpZD0iQ2FudmFzXzEiIHN0cm9rZS1kYXNoYXJyYXk9Im5vbmUiIGZpbGw9Im5vbmUiIHN0cm9rZS1vcGFjaXR5PSIxIiBmaWxsLW9wYWNpdHk9IjEiIHN0cm9rZT0ibm9uZSI+CiAgICA8dGl0bGU+Q2FudmFzIDE8L3RpdGxlPgogICAgPHJlY3QgZmlsbD0id2hpdGUiIHg9IjE2Ny41OTUwNSIgeT0iMTc3NyIgd2lkdGg9IjY5MC4xMTk4IiBoZWlnaHQ9IjMxNC4zOTYiLz4KICAgIDxnIGlkPSJDYW52YXNfMV9MYXllcl8xIj4KICAgICAgPHRpdGxlPkxheWVyIDE8L3RpdGxlPgogICAgICA8ZyBpZD0iR3JhcGhpY18xMjAiPgogICAgICAgIDx0ZXh0IHRyYW5zZm9ybT0idHJhbnNsYXRlKDE3OS4wOTUwNSAyMDQwLjk0OCkiIGZpbGw9ImJsYWNrIj4KICAgICAgICAgIDx0c3BhbiBmb250LWZhbWlseT0iSGVsdmV0aWNhIE5ldWUiIGZvbnQtc2l6ZT0iMTYiIGZpbGw9ImJsYWNrIiB4PSI4NTI2NTEzZS0xOSIgeT0iMTUiPlBhY2thZ2UgaW5zdGFsbGF0aW9uIHByb2dyZXNzOjwvdHNwYW4+CiAgICAgICAgPC90ZXh0PgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzExOSI+CiAgICAgICAgPHJlY3QgeD0iMTc0LjA5NTA1IiB5PSIyMDY0LjM5NiIgd2lkdGg9Ijg5LjUiIGhlaWdodD0iMjIiIGZpbGw9IiM2MGQ5MzYiLz4KICAgICAgICA8dGV4dCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNzkuMDk1MDUgMjA2Ni4xNzIpIiBmaWxsPSJ3aGl0ZSI+CiAgICAgICAgICA8dHNwYW4gZm9udC1mYW1pbHk9IkhlbHZldGljYSBOZXVlIiBmb250LXNpemU9IjE2IiBmaWxsPSJ3aGl0ZSIgeD0iNC43OSIgeT0iMTUiPlJlc29sdmluZzwvdHNwYW4+CiAgICAgICAgPC90ZXh0PgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzExOCI+CiAgICAgICAgPHJlY3QgeD0iMjYzLjU5NTA1IiB5PSIyMDY0LjM5NiIgd2lkdGg9Ijg5LjUiIGhlaWdodD0iMjIiIGZpbGw9IiMwMGEyZmYiLz4KICAgICAgICA8dGV4dCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyNjguNTk1MDUgMjA2Ni4xNzIpIiBmaWxsPSJ3aGl0ZSI+CiAgICAgICAgICA8dHNwYW4gZm9udC1mYW1pbHk9IkhlbHZldGljYSBOZXVlIiBmb250LXNpemU9IjE2IiBmaWxsPSJ3aGl0ZSIgeD0iOC43ODIiIHk9IjE1Ij5GZXRjaGluZzwvdHNwYW4+CiAgICAgICAgPC90ZXh0PgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzExNyI+CiAgICAgICAgPHJlY3QgeD0iMzUzLjA5NTA1IiB5PSIyMDY0LjM5NiIgd2lkdGg9Ijg5LjUiIGhlaWdodD0iMjIiIGZpbGw9IiNmZWFlMDAiLz4KICAgICAgICA8dGV4dCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgzNTguMDk1MDUgMjA2Ni4xNzIpIiBmaWxsPSJ3aGl0ZSI+CiAgICAgICAgICA8dHNwYW4gZm9udC1mYW1pbHk9IkhlbHZldGljYSBOZXVlIiBmb250LXNpemU9IjE2IiBmaWxsPSJ3aGl0ZSIgeD0iMTQuMTEiIHk9IjE1Ij5MaW5raW5nPC90c3Bhbj4KICAgICAgICA8L3RleHQ+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfMTgyIj4KICAgICAgICA8cmVjdCB4PSIxNzQuMDk1MDUiIHk9IjE4MTUuNDQ4IiB3aWR0aD0iODIuMTI1OTIiIGhlaWdodD0iMjIiIGZpbGw9IiM2MGQ5MzYiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xODEiPgogICAgICAgIDxyZWN0IHg9IjQ1My45OTM2IiB5PSIxODE1LjQ0OCIgd2lkdGg9IjEwMC41NjIzNSIgaGVpZ2h0PSIyMiIgZmlsbD0iIzAwYTJmZiIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzE4MCI+CiAgICAgICAgPHJlY3QgeD0iNzUwLjY1MjUiIHk9IjE4MTUuNDQ4IiB3aWR0aD0iNDguNjA1MTM0IiBoZWlnaHQ9IjIyIiBmaWxsPSIjZmVhZTAwIi8+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfMTc5Ij4KICAgICAgICA8cmVjdCB4PSIxNzQuMDk1MDUiIHk9IjE4NDIuNDQ4IiB3aWR0aD0iNDEuMDYyOTYiIGhlaWdodD0iMjIiIGZpbGw9IiM2MGQ5MzYiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xNzgiPgogICAgICAgIDxyZWN0IHg9IjQ1My45OTM2IiB5PSIxODQyLjQ0OCIgd2lkdGg9IjY4LjI1NTAyIiBoZWlnaHQ9IjIyIiBmaWxsPSIjMDBhMmZmIi8+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfMTc3Ij4KICAgICAgICA8cmVjdCB4PSIyNTYuMjIwOTciIHk9IjE4NjkuNDQ4IiB3aWR0aD0iNDguNjA1MTM0IiBoZWlnaHQ9IjIyIiBmaWxsPSIjNjBkOTM2Ii8+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfMTc2Ij4KICAgICAgICA8cmVjdCB4PSIyNTYuMjIwOTciIHk9IjE4OTYuNDQ4IiB3aWR0aD0iODIuMTI1OTIiIGhlaWdodD0iMjIiIGZpbGw9IiM2MGQ5MzYiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xNzUiPgogICAgICAgIDxyZWN0IHg9IjMwNC44MjYxIiB5PSIxOTIzLjQ0OCIgd2lkdGg9IjU4LjY2MTM3IiBoZWlnaHQ9IjIyIiBmaWxsPSIjNjBkOTM2Ii8+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfMTc0Ij4KICAgICAgICA8cmVjdCB4PSIzNDAuMDIyOTIiIHk9IjE5NTAuNDQ4IiB3aWR0aD0iODIuMTI1OTIiIGhlaWdodD0iMjIiIGZpbGw9IiM2MGQ5MzYiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xNzMiPgogICAgICAgIDxyZWN0IHg9IjM2My40ODc0NyIgeT0iMTk3Ny40NDgiIHdpZHRoPSI0MS4wNjI5NiIgaGVpZ2h0PSIyMiIgZmlsbD0iIzYwZDkzNiIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzE3MiI+CiAgICAgICAgPHJlY3QgeD0iMzYzLjQ4NzQ3IiB5PSIyMDA0LjQ0OCIgd2lkdGg9IjkwLjUwNjExIiBoZWlnaHQ9IjIyIiBmaWxsPSIjNjBkOTM2Ii8+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfMTcxIj4KICAgICAgICA8cmVjdCB4PSI0NTMuOTkzNiIgeT0iMTg2OS40NDgiIHdpZHRoPSIxOTAuMjMwNDQiIGhlaWdodD0iMjIiIGZpbGw9IiMwMGEyZmYiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xNzAiPgogICAgICAgIDxyZWN0IHg9IjQ1My45OTM2IiB5PSIxODk2LjQ0OCIgd2lkdGg9IjI5Ni42NTg5MiIgaGVpZ2h0PSIyMiIgZmlsbD0iIzAwYTJmZiIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzE2OSI+CiAgICAgICAgPHJlY3QgeD0iNDUzLjk5MzYiIHk9IjE5MjMuMzMzNiIgd2lkdGg9IjE1OC4zODU3IiBoZWlnaHQ9IjIyIiBmaWxsPSIjMDBhMmZmIi8+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfMTY4Ij4KICAgICAgICA8cmVjdCB4PSI0NTMuOTkzNiIgeT0iMTk1MC4yMTkyIiB3aWR0aD0iMTUwLjAwNTUiIGhlaWdodD0iMjIiIGZpbGw9IiMwMGEyZmYiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xNjciPgogICAgICAgIDxyZWN0IHg9IjQ1My45OTM2IiB5PSIxOTc3LjMzMzYiIHdpZHRoPSIyNDkuNzI5ODMiIGhlaWdodD0iMjIiIGZpbGw9IiMwMGEyZmYiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xNjYiPgogICAgICAgIDxyZWN0IHg9IjQ1My45OTM2IiB5PSIyMDA0LjQ0OCIgd2lkdGg9IjE1MC4wMDU1IiBoZWlnaHQ9IjIyIiBmaWxsPSIjMDBhMmZmIi8+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkxpbmVfMTY1Ij4KICAgICAgICA8cGF0aCBkPSJNIDQ1My45OTM2IDE4MDEuNDQ4IEwgNDU0LjExOCAxODQxLjIzNzUgTCA0NTMuOTkzNiAxOTEwLjU0MSBMIDQ1NC4xMTggMjAzNS43NSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2UtZGFzaGFycmF5PSI0LjAsNC4wIiBzdHJva2Utd2lkdGg9IjEiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xNjQiPgogICAgICAgIDxyZWN0IHg9Ijc1MC42NTI1IiB5PSIxODQyLjQ0OCIgd2lkdGg9IjMyLjI2Mzc1MyIgaGVpZ2h0PSIyMiIgZmlsbD0iI2ZlYWUwMCIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzE2MyI+CiAgICAgICAgPHJlY3QgeD0iNzUwLjY1MjUiIHk9IjE4NjkuNDQ4IiB3aWR0aD0iNjguMjU1MDIiIGhlaWdodD0iMjIiIGZpbGw9IiNmZWFlMDAiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xNjIiPgogICAgICAgIDxyZWN0IHg9Ijc1MC42NTI1IiB5PSIxODk2LjQ0OCIgd2lkdGg9IjEwMC41NjIzNSIgaGVpZ2h0PSIyMiIgZmlsbD0iI2ZlYWUwMCIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzE2MSI+CiAgICAgICAgPHJlY3QgeD0iNzUwLjY1MjUiIHk9IjE5MjIuOTkwNCIgd2lkdGg9IjQ3Ljc2NzExNSIgaGVpZ2h0PSIyMiIgZmlsbD0iI2ZlYWUwMCIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzE2MCI+CiAgICAgICAgPHJlY3QgeD0iNzUwLjY1MjUiIHk9IjE5NTAuMjE5MiIgd2lkdGg9IjEwMC41NjIzNSIgaGVpZ2h0PSIyMiIgZmlsbD0iI2ZlYWUwMCIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzE1OSI+CiAgICAgICAgPHJlY3QgeD0iNzUwLjY1MjUiIHk9IjE5NzcuNDQ4IiB3aWR0aD0iNTguNjYxMzciIGhlaWdodD0iMjIiIGZpbGw9IiNmZWFlMDAiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xNTgiPgogICAgICAgIDxyZWN0IHg9Ijc1MC42NTI1IiB5PSIyMDAzLjk5MDQiIHdpZHRoPSI1OC42NjEzNyIgaGVpZ2h0PSIyMiIgZmlsbD0iI2ZlYWUwMCIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJMaW5lXzE1NyI+CiAgICAgICAgPHBhdGggZD0iTSA3NTAuNjUyNSAxODAxLjQ0OCBMIDc1MC43NzY5IDE4NDEuNDkxNSBMIDc1MC42NTI1IDE5MTEuMjM3MyBMIDc1MC43NzY5IDIwMzYuNzUiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLWRhc2hhcnJheT0iNC4wLDQuMCIgc3Ryb2tlLXdpZHRoPSIxIi8+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkxpbmVfMTU2Ij4KICAgICAgICA8cGF0aCBkPSJNIDE3My45NzA2NiAxODAxLjQ0OCBMIDE3NC4wOTUwNSAxODQxLjU3NyBMIDE3My45NzA2NiAxOTExLjQ3MTQgTCAxNzMuMDk1MDUgMjAzOC4yNSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2UtZGFzaGFycmF5PSI0LjAsNC4wIiBzdHJva2Utd2lkdGg9IjEiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iTGluZV8xNTUiPgogICAgICAgIDxwYXRoIGQ9Ik0gODUxLjIxNDkgMTgwMS40NDggTCA4NTEuMzM5MiAxODQxLjA3IEwgODUxLjIxNDkgMTkxMC4wODE3IEwgODUyLjIxNDkgMjAzNiIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2UtZGFzaGFycmF5PSI0LjAsNC4wIiBzdHJva2Utd2lkdGg9IjEiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xNTQiPgogICAgICAgIDx0ZXh0IHRyYW5zZm9ybT0idHJhbnNsYXRlKDMwOS41OTYzIDE3ODcpIiBmaWxsPSJibGFjayI+CiAgICAgICAgICA8dHNwYW4gZm9udC1mYW1pbHk9IkhlbHZldGljYSBOZXVlIiBmb250LXNpemU9IjE2IiBmaWxsPSJibGFjayIgeD0iMzE5NzQ0MjNlLTIwIiB5PSIxNSI+MTwvdHNwYW4+CiAgICAgICAgPC90ZXh0PgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJMaW5lXzE1MyI+CiAgICAgICAgPGxpbmUgeDE9IjE3My45OTQ4OCIgeTE9IjE4MDkuMjY0IiB4Mj0iNDQ0LjExNzgiIHkyPSIxODA5LjE5MjUiIG1hcmtlci1lbmQ9InVybCgjRmlsbGVkQXJyb3dfTWFya2VyKSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjEiLz4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iTGluZV8xNTIiPgogICAgICAgIDxsaW5lIHgxPSI0NTYuMDg4NjMiIHkxPSIxODA5LjQ0OCIgeDI9Ijc0MC43NzgxIiB5Mj0iMTgwOS42ODkyIiBtYXJrZXItZW5kPSJ1cmwoI0ZpbGxlZEFycm93X01hcmtlcikiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIxIi8+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkxpbmVfMTUxIj4KICAgICAgICA8bGluZSB4MT0iNzUwLjY3NjYiIHkxPSIxODA5LjIxNzUiIHgyPSI4NDEuMzM5MSIgeTI9IjE4MDkuMTg5MyIgbWFya2VyLWVuZD0idXJsKCNGaWxsZWRBcnJvd19NYXJrZXIpIiBzdHJva2U9ImJsYWNrIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMSIvPgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzE1MCI+CiAgICAgICAgPHRleHQgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNjA5LjEwMTE1IDE3ODcpIiBmaWxsPSJibGFjayI+CiAgICAgICAgICA8dHNwYW4gZm9udC1mYW1pbHk9IkhlbHZldGljYSBOZXVlIiBmb250LXNpemU9IjE2IiBmaWxsPSJibGFjayIgeD0iMzE5NzQ0MjNlLTIwIiB5PSIxNSI+MjwvdHNwYW4+CiAgICAgICAgPC90ZXh0PgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzE0OSI+CiAgICAgICAgPHRleHQgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNzkzLjczODggMTc4NykiIGZpbGw9ImJsYWNrIj4KICAgICAgICAgIDx0c3BhbiBmb250LWZhbWlseT0iSGVsdmV0aWNhIE5ldWUiIGZvbnQtc2l6ZT0iMTYiIGZpbGw9ImJsYWNrIiB4PSI2LjY4Mzg3NyIgeT0iMTUiPjM8L3RzcGFuPgogICAgICAgIDwvdGV4dD4KICAgICAgPC9nPgogICAgPC9nPgogIDwvZz4KPC9zdmc+Cg==) Creating a non-flat node\_modules directory[​](https://pnpm.io/9.x/motivation#creating-a-non-flat-node_modules-directory "Direct link to Creating a non-flat node_modules directory") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- When installing dependencies with npm or Yarn Classic, all packages are hoisted to the root of the modules directory. As a result, source code has access to dependencies that are not added as dependencies to the project. By default, pnpm uses symlinks to add only the direct dependencies of the project into the root of the modules directory. ![An illustration of a node_modules directory created by pnpm. Packages in the root node_modules are symlinks to directories inside the node_modules/.pnpm directory](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgeG1sbnM6eGw9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjE1Ny40NTMxMiAxNjQgMjI0Ljc2NTYzIDMyMy4zNTkzOCIgd2lkdGg9IjIyNC43NjU2MyIgaGVpZ2h0PSIzMjMuMzU5MzgiPgogIDxkZWZzPgogICAgPG1hcmtlciBvcmllbnQ9ImF1dG8iIG92ZXJmbG93PSJ2aXNpYmxlIiBtYXJrZXJVbml0cz0ic3Ryb2tlV2lkdGgiIGlkPSJGaWxsZWRBcnJvd19NYXJrZXIiIHN0cm9rZS1saW5lam9pbj0ibWl0ZXIiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgdmlld0JveD0iLTEgLTQgMTAgOCIgbWFya2VyV2lkdGg9IjEwIiBtYXJrZXJIZWlnaHQ9IjgiIGNvbG9yPSIjN2Y4MDgwIj4KICAgICAgPGc+CiAgICAgICAgPHBhdGggZD0iTSA4IDAgTCAwIC0zIEwgMCAzIFoiIGZpbGw9ImN1cnJlbnRDb2xvciIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMSIvPgogICAgICA8L2c+CiAgICA8L21hcmtlcj4KICA8L2RlZnM+CiAgPGcgaWQ9IkNhbnZhc18xIiBzdHJva2UtZGFzaGFycmF5PSJub25lIiBmaWxsPSJub25lIiBzdHJva2Utb3BhY2l0eT0iMSIgZmlsbC1vcGFjaXR5PSIxIiBzdHJva2U9Im5vbmUiPgogICAgPHRpdGxlPkNhbnZhcyAxPC90aXRsZT4KICAgIDxyZWN0IGZpbGw9IndoaXRlIiB4PSIxNTcuNDUzMTIiIHk9IjE2NCIgd2lkdGg9IjIyNC43NjU2MyIgaGVpZ2h0PSIzMjMuMzU5MzgiLz4KICAgIDxnIGlkPSJDYW52YXNfMV9MYXllcl8xIj4KICAgICAgPHRpdGxlPkxheWVyIDE8L3RpdGxlPgogICAgICA8ZyBpZD0iR3JhcGhpY18yIj4KICAgICAgICA8dGV4dCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNjcuNDUzMTIgMTc0KSIgZmlsbD0iYmxhY2siPgogICAgICAgICAgPHRzcGFuIGZvbnQtZmFtaWx5PSJNb25hY28iIGZvbnQtc2l6ZT0iMTYiIGZpbGw9ImJsYWNrIiB4PSIwIiB5PSIxNiI+bm9kZV9tb2R1bGVzPC90c3Bhbj4KICAgICAgICA8L3RleHQ+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfMyI+CiAgICAgICAgPHRleHQgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTk3IDIwNS4zMzU5NCkiIGZpbGw9IiMwMDk2ZmYiPgogICAgICAgICAgPHRzcGFuIGZvbnQtZmFtaWx5PSJNb25hY28iIGZvbnQtc2l6ZT0iMTYiIGZpbGw9IiMwMDk2ZmYiIHg9IjAiIHk9IjE2Ij5leHByZXNzPC90c3Bhbj4KICAgICAgICA8L3RleHQ+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfNCI+CiAgICAgICAgPHRleHQgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTk3IDIzNi42NzE4OCkiIGZpbGw9ImJsYWNrIj4KICAgICAgICAgIDx0c3BhbiBmb250LWZhbWlseT0iTW9uYWNvIiBmb250LXNpemU9IjE2IiBmaWxsPSJibGFjayIgeD0iMCIgeT0iMTYiPi5wbnBtPC90c3Bhbj4KICAgICAgICA8L3RleHQ+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfNSI+CiAgICAgICAgPHRleHQgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMjI3IDI2OC4wMDc4KSIgZmlsbD0iYmxhY2siPgogICAgICAgICAgPHRzcGFuIGZvbnQtZmFtaWx5PSJNb25hY28iIGZvbnQtc2l6ZT0iMTYiIGZpbGw9ImJsYWNrIiB4PSIwIiB5PSIxNiI+ZXhwcmVzc0A0LjE3LjM8L3RzcGFuPgogICAgICAgIDwvdGV4dD4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY182Ij4KICAgICAgICA8dGV4dCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyNTcgMjk5LjM0Mzc1KSIgZmlsbD0iYmxhY2siPgogICAgICAgICAgPHRzcGFuIGZvbnQtZmFtaWx5PSJNb25hY28iIGZvbnQtc2l6ZT0iMTYiIGZpbGw9ImJsYWNrIiB4PSIwIiB5PSIxNiI+bm9kZV9tb2R1bGVzPC90c3Bhbj4KICAgICAgICA8L3RleHQ+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfNyI+CiAgICAgICAgPHRleHQgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMjg3IDMzMC42Nzk3KSIgZmlsbD0iYmxhY2siPgogICAgICAgICAgPHRzcGFuIGZvbnQtZmFtaWx5PSJNb25hY28iIGZvbnQtc2l6ZT0iMTYiIGZpbGw9ImJsYWNrIiB4PSIwIiB5PSIxNiI+ZXhwcmVzczwvdHNwYW4+CiAgICAgICAgPC90ZXh0PgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzgiPgogICAgICAgIDx0ZXh0IHRyYW5zZm9ybT0idHJhbnNsYXRlKDI4NyAzNjIuMDE1NjIpIiBmaWxsPSIjMDA5NmZmIj4KICAgICAgICAgIDx0c3BhbiBmb250LWZhbWlseT0iTW9uYWNvIiBmb250LXNpemU9IjE2IiBmaWxsPSIjMDA5NmZmIiB4PSIwIiB5PSIxNiI+Y29va2llPC90c3Bhbj4KICAgICAgICA8L3RleHQ+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkdyYXBoaWNfOSI+CiAgICAgICAgPHRleHQgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMjI3IDM5My4zNTE1NikiIGZpbGw9ImJsYWNrIj4KICAgICAgICAgIDx0c3BhbiBmb250LWZhbWlseT0iTW9uYWNvIiBmb250LXNpemU9IjE2IiBmaWxsPSJibGFjayIgeD0iMCIgeT0iMTYiPmNvb2tpZUAwLjQuMjwvdHNwYW4+CiAgICAgICAgPC90ZXh0PgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJHcmFwaGljXzEwIj4KICAgICAgICA8dGV4dCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyNTcgNDI0LjY4NzUpIiBmaWxsPSJibGFjayI+CiAgICAgICAgICA8dHNwYW4gZm9udC1mYW1pbHk9Ik1vbmFjbyIgZm9udC1zaXplPSIxNiIgZmlsbD0iYmxhY2siIHg9IjAiIHk9IjE2Ij5ub2RlX21vZHVsZXM8L3RzcGFuPgogICAgICAgIDwvdGV4dD4KICAgICAgPC9nPgogICAgICA8ZyBpZD0iR3JhcGhpY18xMSI+CiAgICAgICAgPHRleHQgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMjg3IDQ1Ni4wMjM0NCkiIGZpbGw9ImJsYWNrIj4KICAgICAgICAgIDx0c3BhbiBmb250LWZhbWlseT0iTW9uYWNvIiBmb250LXNpemU9IjE2IiBmaWxsPSJibGFjayIgeD0iMCIgeT0iMTYiPmNvb2tpZTwvdHNwYW4+CiAgICAgICAgPC90ZXh0PgogICAgICA8L2c+CiAgICAgIDxnIGlkPSJMaW5lXzIwIj4KICAgICAgICA8cGF0aCBkPSJNIDE5MiAyMTYuMDAzOSBMIDE4MiAyMTYuMDAzOSBMIDE4MC43NSAyMTYuMTI1IEwgMTc5LjUgMjE2LjEyNSBMIDE3OS41IDM0MS4zNDc2NiBMIDI3Mi4xIDM0MS4zNDc2NiIgbWFya2VyLWVuZD0idXJsKCNGaWxsZWRBcnJvd19NYXJrZXIpIiBzdHJva2U9IiM3ZjgwODAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIxIi8+CiAgICAgIDwvZz4KICAgICAgPGcgaWQ9IkxpbmVfMjEiPgogICAgICAgIDxwYXRoIGQ9Ik0gMjgyIDM3Mi42ODM2IEwgMjcyIDM3Mi42ODM2IEwgMjE3LjUgMzczIEwgMjE4IDQ1Ny41IEwgMjE4IDQ2Ni42OTE0IEwgMjcyLjEgNDY2LjY5MTQiIG1hcmtlci1lbmQ9InVybCgjRmlsbGVkQXJyb3dfTWFya2VyKSIgc3Ryb2tlPSIjN2Y4MDgwIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMSIvPgogICAgICA8L2c+CiAgICA8L2c+CiAgPC9nPgo8L3N2Zz4K) If you'd like more details about the unique `node_modules` structure that pnpm creates and why it works fine with the Node.js ecosystem, read: * [Flat node\_modules is not the only way](https://pnpm.io/blog/2020/05/27/flat-node-modules-is-not-the-only-way) * [Symlinked node\_modules structure](https://pnpm.io/9.x/symlinked-node-modules-structure) tip If your tooling doesn't work well with symlinks, you may still use pnpm and set the [node-linker](https://pnpm.io/9.x/npmrc#node-linker) setting to `hoisted`. This will instruct pnpm to create a node\_modules directory that is similar to those created by npm and Yarn Classic. * [Saving disk space](https://pnpm.io/9.x/motivation#saving-disk-space) * [Boosting installation speed](https://pnpm.io/9.x/motivation#boosting-installation-speed) * [Creating a non-flat node\_modules directory](https://pnpm.io/9.x/motivation#creating-a-non-flat-node_modules-directory) --- # Settings (.npmrc) | pnpm [Skip to main content](https://pnpm.io/9.x/npmrc#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/motivation) ** (10.x). Version: 9.x On this page pnpm gets its configuration from the command line, environment variables, and `.npmrc` files. The `pnpm config` command can be used to update and edit the contents of the user and global `.npmrc` files. The four relevant files are: * per-project configuration file (`/path/to/my/project/.npmrc`) * per-workspace configuration file (the directory that contains the `pnpm-workspace.yaml` file) * per-user configuration file (`~/.npmrc`) * global configuration file (`/etc/npmrc`) All `.npmrc` files are an [INI-formatted](https://en.wikipedia.org/wiki/INI_file) list of `key = value` parameters. Values in the `.npmrc` files may contain env variables using the `${NAME}` syntax. The env variables may also be specified with default values. Using `${NAME-fallback}` will return `fallback` if `NAME` isn't set. `${NAME:-fallback}` will return `fallback` if `NAME` isn't set, or is an empty string. Dependency Hoisting Settings[​](https://pnpm.io/9.x/npmrc#dependency-hoisting-settings "Direct link to Dependency Hoisting Settings") -------------------------------------------------------------------------------------------------------------------------------------- ### hoist[​](https://pnpm.io/9.x/npmrc#hoist "Direct link to hoist") * Default: **true** * Type: **boolean** When `true`, all dependencies are hoisted to `node_modules/.pnpm/node_modules`. This makes unlisted dependencies accessible to all packages inside `node_modules`. ### hoist-workspace-packages[​](https://pnpm.io/9.x/npmrc#hoist-workspace-packages "Direct link to hoist-workspace-packages") * Default: **true** * Type: **boolean** When `true`, packages from the workspaces are symlinked to either `/node_modules/.pnpm/node_modules` or to `/node_modules` depending on other hoisting settings (`hoist-pattern` and `public-hoist-pattern`). ### hoist-pattern[​](https://pnpm.io/9.x/npmrc#hoist-pattern "Direct link to hoist-pattern") * Default: **\['\*'\]** * Type: **string\[\]** Tells pnpm which packages should be hoisted to `node_modules/.pnpm/node_modules`. By default, all packages are hoisted - however, if you know that only some flawed packages have phantom dependencies, you can use this option to exclusively hoist the phantom dependencies (recommended). For instance: hoist-pattern[]=*eslint*hoist-pattern[]=*babel* You may also exclude patterns from hoisting using `!`. For instance: hoist-pattern[]=*types*hoist-pattern[]=!@types/react ### public-hoist-pattern[​](https://pnpm.io/9.x/npmrc#public-hoist-pattern "Direct link to public-hoist-pattern") * Default: **\['\*eslint\*', '\*prettier\*'\]** * Type: **string\[\]** Unlike `hoist-pattern`, which hoists dependencies to a hidden modules directory inside the virtual store, `public-hoist-pattern` hoists dependencies matching the pattern to the root modules directory. Hoisting to the root modules directory means that application code will have access to phantom dependencies, even if they modify the resolution strategy improperly. This setting is useful when dealing with some flawed pluggable tools that don't resolve dependencies properly. For instance: public-hoist-pattern[]=*plugin* Note: Setting `shamefully-hoist` to `true` is the same as setting `public-hoist-pattern` to `*`. You may also exclude patterns from hoisting using `!`. For instance: public-hoist-pattern[]=*types*public-hoist-pattern[]=!@types/react ### shamefully-hoist[​](https://pnpm.io/9.x/npmrc#shamefully-hoist "Direct link to shamefully-hoist") * Default: **false** * Type: **Boolean** By default, pnpm creates a semistrict `node_modules`, meaning dependencies have access to undeclared dependencies but modules outside of `node_modules` do not. With this layout, most of the packages in the ecosystem work with no issues. However, if some tooling only works when the hoisted dependencies are in the root of `node_modules`, you can set this to `true` to hoist them for you. Node-Modules Settings[​](https://pnpm.io/9.x/npmrc#node-modules-settings "Direct link to Node-Modules Settings") ----------------------------------------------------------------------------------------------------------------- ### modules-dir[​](https://pnpm.io/9.x/npmrc#modules-dir "Direct link to modules-dir") * Default: **node\_modules** * Type: **path** The directory in which dependencies will be installed (instead of `node_modules`). ### node-linker[​](https://pnpm.io/9.x/npmrc#node-linker "Direct link to node-linker") * Default: **isolated** * Type: **isolated**, **hoisted**, **pnp** Defines what linker should be used for installing Node packages. * **isolated** - dependencies are symlinked from a virtual store at `node_modules/.pnpm`. * **hoisted** - a flat `node_modules` without symlinks is created. Same as the `node_modules` created by npm or Yarn Classic. One of Yarn's libraries is used for hoisting, when this setting is used. Legitimate reasons to use this setting: 1. Your tooling doesn't work well with symlinks. A React Native project will most probably only work if you use a hoisted `node_modules`. 2. Your project is deployed to a serverless hosting provider. Some serverless providers (for instance, AWS Lambda) don't support symlinks. An alternative solution for this problem is to bundle your application before deployment. 3. If you want to publish your package with [`"bundledDependencies"`](https://docs.npmjs.com/cli/v8/configuring-npm/package-json#bundleddependencies) . 4. If you are running Node.js with the [\--preserve-symlinks](https://nodejs.org/api/cli.html#cli_preserve_symlinks) flag. * **pnp** - no `node_modules`. Plug'n'Play is an innovative strategy for Node that is [used by Yarn Berry](https://yarnpkg.com/features/pnp) . It is recommended to also set `symlink` setting to `false` when using `pnp` as your linker. ### symlink[​](https://pnpm.io/9.x/npmrc#symlink "Direct link to symlink") * Default: **true** * Type: **Boolean** When `symlink` is set to `false`, pnpm creates a virtual store directory without any symlinks. It is a useful setting together with `node-linker=pnp`. ### enable-modules-dir[​](https://pnpm.io/9.x/npmrc#enable-modules-dir "Direct link to enable-modules-dir") * Default: **true** * Type: **Boolean** When `false`, pnpm will not write any files to the modules directory (`node_modules`). This is useful for when the modules directory is mounted with filesystem in userspace (FUSE). There is an experimental CLI that allows you to mount a modules directory with FUSE: [@pnpm/mount-modules](https://www.npmjs.com/package/@pnpm/mount-modules) . ### virtual-store-dir[​](https://pnpm.io/9.x/npmrc#virtual-store-dir "Direct link to virtual-store-dir") * Default: **node\_modules/.pnpm** * Types: **path** The directory with links to the store. All direct and indirect dependencies of the project are linked into this directory. This is a useful setting that can solve issues with long paths on Windows. If you have some dependencies with very long paths, you can select a virtual store in the root of your drive (for instance `C:\my-project-store`). Or you can set the virtual store to `.pnpm` and add it to `.gitignore`. This will make stacktraces cleaner as paths to dependencies will be one directory higher. **NOTE:** the virtual store cannot be shared between several projects. Every project should have its own virtual store (except for in workspaces where the root is shared). ### virtual-store-dir-max-length[​](https://pnpm.io/9.x/npmrc#virtual-store-dir-max-length "Direct link to virtual-store-dir-max-length") Added in: v9.1.0 * Default: **120** * Types: **number** Sets the maximum allowed length of directory names inside the virtual store directory (`node_modules/.pnpm`). You may set this to a lower number if you encounter long path issues on Windows. ### package-import-method[​](https://pnpm.io/9.x/npmrc#package-import-method "Direct link to package-import-method") * Default: **auto** * Type: **auto**, **hardlink**, **copy**, **clone**, **clone-or-copy** Controls the way packages are imported from the store (if you want to disable symlinks inside `node_modules`, then you need to change the [node-linker](https://pnpm.io/9.x/npmrc#node-linker) setting, not this one). * **auto** - try to clone packages from the store. If cloning is not supported then hardlink packages from the store. If neither cloning nor linking is possible, fall back to copying * **hardlink** - hard link packages from the store * **clone-or-copy** - try to clone packages from the store. If cloning is not supported then fall back to copying * **copy** - copy packages from the store * **clone** - clone (AKA copy-on-write or reference link) packages from the store Cloning is the best way to write packages to node\_modules. It is the fastest way and safest way. When cloning is used, you may edit files in your node\_modules and they will not be modified in the central content-addressable store. Unfortunately, not all file systems support cloning. We recommend using a copy-on-write (CoW) file system (for instance, Btrfs instead of Ext4 on Linux) for the best experience with pnpm. ### modules-cache-max-age[​](https://pnpm.io/9.x/npmrc#modules-cache-max-age "Direct link to modules-cache-max-age") * Default: **10080** (7 days in minutes) * Type: **number** The time in minutes after which orphan packages from the modules directory should be removed. pnpm keeps a cache of packages in the modules directory. This boosts installation speed when switching branches or downgrading dependencies. ### dlx-cache-max-age[​](https://pnpm.io/9.x/npmrc#dlx-cache-max-age "Direct link to dlx-cache-max-age") * Default: **1440** (1 day in minutes) * Type: **number** The time in minutes after which dlx cache expires. After executing a dlx command, pnpm keeps a cache that omits the installation step for subsequent calls to the same dlx command. Store Settings[​](https://pnpm.io/9.x/npmrc#store-settings "Direct link to Store Settings") -------------------------------------------------------------------------------------------- ### store-dir[​](https://pnpm.io/9.x/npmrc#store-dir "Direct link to store-dir") * Default: * If the **$PNPM\_HOME** env variable is set, then **$PNPM\_HOME/store** * If the **$XDG\_DATA\_HOME** env variable is set, then **$XDG\_DATA\_HOME/pnpm/store** * On Windows: **~/AppData/Local/pnpm/store** * On macOS: **~/Library/pnpm/store** * On Linux: **~/.local/share/pnpm/store** * Type: **path** The location where all the packages are saved on the disk. The store should be always on the same disk on which installation is happening, so there will be one store per disk. If there is a home directory on the current disk, then the store is created inside it. If there is no home on the disk, then the store is created at the root of the filesystem. For example, if installation is happening on a filesystem mounted at `/mnt`, then the store will be created at `/mnt/.pnpm-store`. The same goes for Windows systems. It is possible to set a store from a different disk but in that case pnpm will copy packages from the store instead of hard-linking them, as hard links are only possible on the same filesystem. ### verify-store-integrity[​](https://pnpm.io/9.x/npmrc#verify-store-integrity "Direct link to verify-store-integrity") * Default: **true** * Type: **Boolean** By default, if a file in the store has been modified, the content of this file is checked before linking it to a project's `node_modules`. If `verify-store-integrity` is set to `false`, files in the content-addressable store will not be checked during installation. ### use-running-store-server[​](https://pnpm.io/9.x/npmrc#use-running-store-server "Direct link to use-running-store-server") danger Deprecated feature * Default: **false** * Type: **Boolean** Only allows installation with a store server. If no store server is running, installation will fail. ### strict-store-pkg-content-check[​](https://pnpm.io/9.x/npmrc#strict-store-pkg-content-check "Direct link to strict-store-pkg-content-check") Added in: v9.4.0 * Default: **true** * Type: **Boolean** Some registries allow the exact same content to be published under different package names and/or versions. This breaks the validity checks of packages in the store. To avoid errors when verifying the names and versions of such packages in the store, you may set the `strict-store-pkg-content-check` setting to `false`. Lockfile Settings[​](https://pnpm.io/9.x/npmrc#lockfile-settings "Direct link to Lockfile Settings") ----------------------------------------------------------------------------------------------------- ### lockfile[​](https://pnpm.io/9.x/npmrc#lockfile "Direct link to lockfile") * Default: **true** * Type: **Boolean** When set to `false`, pnpm won't read or generate a `pnpm-lock.yaml` file. ### prefer-frozen-lockfile[​](https://pnpm.io/9.x/npmrc#prefer-frozen-lockfile "Direct link to prefer-frozen-lockfile") * Default: **true** * Type: **Boolean** When set to `true` and the available `pnpm-lock.yaml` satisfies the `package.json` dependencies directive, a headless installation is performed. A headless installation skips all dependency resolution as it does not need to modify the lockfile. ### lockfile-include-tarball-url[​](https://pnpm.io/9.x/npmrc#lockfile-include-tarball-url "Direct link to lockfile-include-tarball-url") * Default: **false** * Type: **Boolean** Add the full URL to the package's tarball to every entry in `pnpm-lock.yaml`. ### git-branch-lockfile[​](https://pnpm.io/9.x/npmrc#git-branch-lockfile "Direct link to git-branch-lockfile") * Default: **false** * Type: **Boolean** When set to `true`, the generated lockfile name after installation will be named based on the current branch name to completely avoid merge conflicts. For example, if the current branch name is `feature-foo`, the corresponding lockfile name will be `pnpm-lock.feature-foo.yaml` instead of `pnpm-lock.yaml`. It is typically used in conjunction with the command line argument `--merge-git-branch-lockfiles` or by setting `merge-git-branch-lockfiles-branch-pattern` in the `.npmrc` file. ### merge-git-branch-lockfiles-branch-pattern[​](https://pnpm.io/9.x/npmrc#merge-git-branch-lockfiles-branch-pattern "Direct link to merge-git-branch-lockfiles-branch-pattern") * Default: **null** * Type: **Array or null** This configuration matches the current branch name to determine whether to merge all git branch lockfile files. By default, you need to manually pass the `--merge-git-branch-lockfiles` command line parameter. This configuration allows this process to be automatically completed. For instance: merge-git-branch-lockfiles-branch-pattern[]=mainmerge-git-branch-lockfiles-branch-pattern[]=release* You may also exclude patterns using `!`. ### peers-suffix-max-length[​](https://pnpm.io/9.x/npmrc#peers-suffix-max-length "Direct link to peers-suffix-max-length") Added in: v9.3.0 * Default: **1000** * Type: **number** Max length of the peer IDs suffix added to dependency keys in the lockfile. If the suffix is longer, it is replaced with a hash. Registry & Authentication Settings[​](https://pnpm.io/9.x/npmrc#registry--authentication-settings "Direct link to Registry & Authentication Settings") ------------------------------------------------------------------------------------------------------------------------------------------------------- ### registry[​](https://pnpm.io/9.x/npmrc#registry "Direct link to registry") * Default: **[https://registry.npmjs.org/](https://registry.npmjs.org/) ** * Type: **url** The base URL of the npm package registry (trailing slash included). #### :registry[​](https://pnpm.io/9.x/npmrc#scope "Direct link to scope") The npm registry that should be used for packages of the specified scope. For example, setting `@babel:registry=https://example.com/packages/npm/` will enforce that when you use `pnpm add @babel/core`, or any `@babel` scoped package, the package will be fetched from `https://example.com/packages/npm` instead of the default registry. ### :\_authToken[​](https://pnpm.io/9.x/npmrc#url_authtoken "Direct link to :_authToken") Define the authentication bearer token to use when accessing the specified registry. For example: //registry.npmjs.org/:_authToken=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx You may also use an environment variable. For example: //registry.npmjs.org/:_authToken=${NPM_TOKEN} Or you may just use an environment variable directly, without changing `.npmrc` at all: npm_config_//registry.npmjs.org/:_authToken=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx ### :tokenHelper[​](https://pnpm.io/9.x/npmrc#urltokenhelper "Direct link to :tokenHelper") A token helper is an executable which outputs an auth token. This can be used in situations where the authToken is not a constant value but is something that refreshes regularly, where a script or other tool can use an existing refresh token to obtain a new access token. The configuration for the path to the helper must be an absolute path, with no arguments. In order to be secure, it is only permitted to set this value in the user `.npmrc`. Otherwise a project could place a value in a project's local `.npmrc` and run arbitrary executables. Setting a token helper for the default registry: tokenHelper=/home/ivan/token-generator Setting a token helper for the specified registry: //registry.corp.com:tokenHelper=/home/ivan/token-generator Request Settings[​](https://pnpm.io/9.x/npmrc#request-settings "Direct link to Request Settings") -------------------------------------------------------------------------------------------------- ### ca[​](https://pnpm.io/9.x/npmrc#ca "Direct link to ca") * Default: **The npm CA certificate** * Type: **String, Array or null** The Certificate Authority signing certificate that is trusted for SSL connections to the registry. Values should be in PEM format (AKA "Base-64 encoded X.509 (.CER)"). For example: ca="-----BEGIN CERTIFICATE-----\nXXXX\nXXXX\n-----END CERTIFICATE-----" Set to null to only allow known registrars, or to a specific CA cert to trust only that specific signing authority. Multiple CAs can be trusted by specifying an array of certificates: ca[]="..."ca[]="..." See also the `strict-ssl` config. ### cafile[​](https://pnpm.io/9.x/npmrc#cafile "Direct link to cafile") * Default: **null** * Type: **path** A path to a file containing one or multiple Certificate Authority signing certificates. Similar to the `ca` setting, but allows for multiple CAs, as well as for the CA information to be stored in a file instead of being specified via CLI. ### :cafile[​](https://pnpm.io/9.x/npmrc#urlcafile "Direct link to :cafile") Define the path to a Certificate Authority file to use when accessing the specified registry. For example: //registry.npmjs.org/:keyfile=client-cert.pem ### cert[​](https://pnpm.io/9.x/npmrc#cert "Direct link to cert") * Default: **null** * Type: **String** A client certificate to pass when accessing the registry. Values should be in PEM format (AKA "Base-64 encoded X.509 (.CER)"). For example: cert="-----BEGIN CERTIFICATE-----\nXXXX\nXXXX\n-----END CERTIFICATE-----" It is not the path to a certificate file. ### :certfile[​](https://pnpm.io/9.x/npmrc#urlcertfile "Direct link to :certfile") Define the path to a certificate file to use when accessing the specified registry. For example: //registry.npmjs.org/:certfile=server-cert.pem ### key[​](https://pnpm.io/9.x/npmrc#key "Direct link to key") * Default: **null** * Type: **String** A client key to pass when accessing the registry. Values should be in PEM format (AKA "Base-64 encoded X.509 (.CER)"). For example: key="-----BEGIN PRIVATE KEY-----\nXXXX\nXXXX\n-----END PRIVATE KEY-----" It is not the path to a key file (and there is no `keyfile` option). This setting contains sensitive information. Don't write it to a local `.npmrc` file committed to the repository. ### :keyfile[​](https://pnpm.io/9.x/npmrc#urlkeyfile "Direct link to :keyfile") Define the path to a client key file to use when accessing the specified registry. For example: //registry.npmjs.org/:keyfile=server-key.pem ### git-shallow-hosts[​](https://pnpm.io/9.x/npmrc#git-shallow-hosts "Direct link to git-shallow-hosts") * Default: **\['github.com', 'gist.github.com', 'gitlab.com', 'bitbucket.com', 'bitbucket.org'\]** * Type: **string\[\]** When fetching dependencies that are Git repositories, if the host is listed in this setting, pnpm will use shallow cloning to fetch only the needed commit, not all the history. ### https-proxy[​](https://pnpm.io/9.x/npmrc#https-proxy "Direct link to https-proxy") * Default: **null** * Type: **url** A proxy to use for outgoing HTTPS requests. If the `HTTPS_PROXY`, `https_proxy`, `HTTP_PROXY` or `http_proxy` environment variables are set, their values will be used instead. If your proxy URL contains a username and password, make sure to URL-encode them. For instance: https-proxy=https://use%21r:pas%2As@my.proxy:1234/foo Do not encode the colon (`:`) between the username and password. ### http-proxy[​](https://pnpm.io/9.x/npmrc#http-proxy "Direct link to http-proxy") ### proxy[​](https://pnpm.io/9.x/npmrc#proxy "Direct link to proxy") * Default: **null** * Type: **url** A proxy to use for outgoing http requests. If the HTTP\_PROXY or http\_proxy environment variables are set, proxy settings will be honored by the underlying request library. ### local-address[​](https://pnpm.io/9.x/npmrc#local-address "Direct link to local-address") * Default: **undefined** * Type: **IP Address** The IP address of the local interface to use when making connections to the npm registry. ### maxsockets[​](https://pnpm.io/9.x/npmrc#maxsockets "Direct link to maxsockets") * Default: **network-concurrency x 3** * Type: **Number** The maximum number of connections to use per origin (protocol/host/port combination). ### noproxy[​](https://pnpm.io/9.x/npmrc#noproxy "Direct link to noproxy") * Default: **null** * Type: **String** A comma-separated string of domain extensions that a proxy should not be used for. ### strict-ssl[​](https://pnpm.io/9.x/npmrc#strict-ssl "Direct link to strict-ssl") * Default: **true** * Type: **Boolean** Whether or not to do SSL key validation when making requests to the registry via HTTPS. See also the `ca` option. ### network-concurrency[​](https://pnpm.io/9.x/npmrc#network-concurrency "Direct link to network-concurrency") * Default: **16** * Type: **Number** Controls the maximum number of HTTP(S) requests to process simultaneously. ### fetch-retries[​](https://pnpm.io/9.x/npmrc#fetch-retries "Direct link to fetch-retries") * Default: **2** * Type: **Number** How many times to retry if pnpm fails to fetch from the registry. ### fetch-retry-factor[​](https://pnpm.io/9.x/npmrc#fetch-retry-factor "Direct link to fetch-retry-factor") * Default: **10** * Type: **Number** The exponential factor for retry backoff. ### fetch-retry-mintimeout[​](https://pnpm.io/9.x/npmrc#fetch-retry-mintimeout "Direct link to fetch-retry-mintimeout") * Default: **10000 (10 seconds)** * Type: **Number** The minimum (base) timeout for retrying requests. ### fetch-retry-maxtimeout[​](https://pnpm.io/9.x/npmrc#fetch-retry-maxtimeout "Direct link to fetch-retry-maxtimeout") * Default: **60000 (1 minute)** * Type: **Number** The maximum fallback timeout to ensure the retry factor does not make requests too long. ### fetch-timeout[​](https://pnpm.io/9.x/npmrc#fetch-timeout "Direct link to fetch-timeout") * Default: **60000 (1 minute)** * Type: **Number** The maximum amount of time to wait for HTTP requests to complete. Peer Dependency Settings[​](https://pnpm.io/9.x/npmrc#peer-dependency-settings "Direct link to Peer Dependency Settings") -------------------------------------------------------------------------------------------------------------------------- ### auto-install-peers[​](https://pnpm.io/9.x/npmrc#auto-install-peers "Direct link to auto-install-peers") * Default: **true** * Type: **Boolean** When `true`, any missing non-optional peer dependencies are automatically installed. #### Version Conflicts[​](https://pnpm.io/9.x/npmrc#version-conflicts "Direct link to Version Conflicts") If there are conflicting version requirements for a peer dependency from different packages, pnpm will not install any version of the conflicting peer dependency automatically. Instead, a warning is printed. For example, if one dependency requires `react@^16.0.0` and another requires `react@^17.0.0`, these requirements conflict, and no automatic installation will occur. #### Conflict Resolution[​](https://pnpm.io/9.x/npmrc#conflict-resolution "Direct link to Conflict Resolution") In case of a version conflict, you'll need to evaluate which version of the peer dependency to install yourself, or update the dependencies to align their peer dependency requirements. ### dedupe-peer-dependents[​](https://pnpm.io/9.x/npmrc#dedupe-peer-dependents "Direct link to dedupe-peer-dependents") * Default: **true** * Type: **Boolean** When this setting is set to `true`, packages with peer dependencies will be deduplicated after peers resolution. For instance, let's say we have a workspace with two projects and both of them have `webpack` in their dependencies. `webpack` has `esbuild` in its optional peer dependencies, and one of the projects has `esbuild` in its dependencies. In this case, pnpm will link two instances of `webpack` to the `node_modules/.pnpm` directory: one with `esbuild` and another one without it: node_modules .pnpm webpack@1.0.0_esbuild@1.0.0 webpack@1.0.0project1 node_modules webpack -> ../../node_modules/.pnpm/webpack@1.0.0/node_modules/webpackproject2 node_modules webpack -> ../../node_modules/.pnpm/webpack@1.0.0_esbuild@1.0.0/node_modules/webpack esbuild This makes sense because `webpack` is used in two projects, and one of the projects doesn't have `esbuild`, so the two projects cannot share the same instance of `webpack`. However, this is not what most developers expect, especially since in a hoisted `node_modules`, there would only be one instance of `webpack`. Therefore, you may now use the `dedupe-peer-dependents` setting to deduplicate `webpack` when it has no conflicting peer dependencies (explanation at the end). In this case, if we set `dedupe-peer-dependents` to `true`, both projects will use the same `webpack` instance, which is the one that has `esbuild` resolved: node_modules .pnpm webpack@1.0.0_esbuild@1.0.0project1 node_modules webpack -> ../../node_modules/.pnpm/webpack@1.0.0_esbuild@1.0.0/node_modules/webpackproject2 node_modules webpack -> ../../node_modules/.pnpm/webpack@1.0.0_esbuild@1.0.0/node_modules/webpack esbuild **What are conflicting peer dependencies?** By conflicting peer dependencies we mean a scenario like the following one: node_modules .pnpm webpack@1.0.0_react@16.0.0_esbuild@1.0.0 webpack@1.0.0_react@17.0.0project1 node_modules webpack -> ../../node_modules/.pnpm/webpack@1.0.0/node_modules/webpack react (v17)project2 node_modules webpack -> ../../node_modules/.pnpm/webpack@1.0.0_esbuild@1.0.0/node_modules/webpack esbuild react (v16) In this case, we cannot dedupe `webpack` as `webpack` has `react` in its peer dependencies and `react` is resolved from two different versions in the context of the two projects. ### strict-peer-dependencies[​](https://pnpm.io/9.x/npmrc#strict-peer-dependencies "Direct link to strict-peer-dependencies") * Default: **false** * Type: **Boolean** If this is enabled, commands will fail if there is a missing or invalid peer dependency in the tree. ### resolve-peers-from-workspace-root[​](https://pnpm.io/9.x/npmrc#resolve-peers-from-workspace-root "Direct link to resolve-peers-from-workspace-root") * Default: **true** * Type: **Boolean** When enabled, dependencies of the root workspace project are used to resolve peer dependencies of any projects in the workspace. It is a useful feature as you can install your peer dependencies only in the root of the workspace, and you can be sure that all projects in the workspace use the same versions of the peer dependencies. CLI Settings[​](https://pnpm.io/9.x/npmrc#cli-settings "Direct link to CLI Settings") -------------------------------------------------------------------------------------- ### \[no-\]color[​](https://pnpm.io/9.x/npmrc#no-color "Direct link to [no-]color") * Default: **auto** * Type: **auto**, **always**, **never** Controls colors in the output. * **auto** - output uses colors when the standard output is a terminal or TTY. * **always** - ignore the difference between terminals and pipes. You’ll rarely want this; in most scenarios, if you want color codes in your redirected output, you can instead pass a `--color` flag to the pnpm command to force it to use color codes. The default setting is almost always what you’ll want. * **never** - turns off colors. This is the setting used by `--no-color`. ### loglevel[​](https://pnpm.io/9.x/npmrc#loglevel "Direct link to loglevel") * Default: **info** * Type: **debug**, **info**, **warn**, **error** Any logs at or higher than the given level will be shown. You can instead pass `--silent` to turn off all output logs. ### use-beta-cli[​](https://pnpm.io/9.x/npmrc#use-beta-cli "Direct link to use-beta-cli") * Default: **false** * Type: **Boolean** Experimental option that enables beta features of the CLI. This means that you may get some changes to the CLI functionality that are breaking changes, or potentially bugs. ### recursive-install[​](https://pnpm.io/9.x/npmrc#recursive-install "Direct link to recursive-install") * Default: **true** * Type: **Boolean** If this is enabled, the primary behaviour of `pnpm install` becomes that of `pnpm install -r`, meaning the install is performed on all workspace or subdirectory packages. Else, `pnpm install` will exclusively build the package in the current directory. ### engine-strict[​](https://pnpm.io/9.x/npmrc#engine-strict "Direct link to engine-strict") * Default: **false** * Type: **Boolean** If this is enabled, pnpm will not install any package that claims to not be compatible with the current Node version. Regardless of this configuration, installation will always fail if a project (not a dependency) specifies an incompatible version in its `engines` field. ### npm-path[​](https://pnpm.io/9.x/npmrc#npm-path "Direct link to npm-path") * Type: **path** The location of the npm binary that pnpm uses for some actions, like publishing. ### package-manager-strict[​](https://pnpm.io/9.x/npmrc#package-manager-strict "Direct link to package-manager-strict") * Default: **true** * Type: **Boolean** If this setting is disabled, pnpm will not fail if a different package manager is specified in the `packageManager` field of `package.json`. When enabled, only the package name is checked (since pnpm v9.2.0), so you can still run any version of pnpm regardless of the version specified in the `packageManager` field. Alternatively, you can disable this setting by setting the `COREPACK_ENABLE_STRICT` environment variable to `0`. ### package-manager-strict-version[​](https://pnpm.io/9.x/npmrc#package-manager-strict-version "Direct link to package-manager-strict-version") Added in: v9.2.0 * Default: **false** * Type: **Boolean** When enabled, pnpm will fail if its version doesn't exactly match the version specified in the `packageManager` field of `package.json`. ### manage-package-manager-versions[​](https://pnpm.io/9.x/npmrc#manage-package-manager-versions "Direct link to manage-package-manager-versions") Added in: v9.7.0 * Default: **false** * Type: **Boolean** When enabled, pnpm will automatically download and run the version of pnpm specified in the `packageManager` field of `package.json`. This is the same field used by Corepack. Example: { "packageManager": "pnpm@9.3.0"} Build Settings[​](https://pnpm.io/9.x/npmrc#build-settings "Direct link to Build Settings") -------------------------------------------------------------------------------------------- ### ignore-scripts[​](https://pnpm.io/9.x/npmrc#ignore-scripts "Direct link to ignore-scripts") * Default: **false** * Type: **Boolean** Do not execute any scripts defined in the project `package.json` and its dependencies. note This flag does not prevent the execution of [.pnpmfile.cjs](https://pnpm.io/9.x/pnpmfile) ### ignore-dep-scripts[​](https://pnpm.io/9.x/npmrc#ignore-dep-scripts "Direct link to ignore-dep-scripts") * Default: **false** * Type: **Boolean** Do not execute any scripts of the installed packages. Scripts of the projects are executed. ### child-concurrency[​](https://pnpm.io/9.x/npmrc#child-concurrency "Direct link to child-concurrency") * Default: **5** * Type: **Number** The maximum number of child processes to allocate simultaneously to build node\_modules. ### side-effects-cache[​](https://pnpm.io/9.x/npmrc#side-effects-cache "Direct link to side-effects-cache") * Default: **true** * Type: **Boolean** Use and cache the results of (pre/post)install hooks. ### side-effects-cache-readonly[​](https://pnpm.io/9.x/npmrc#side-effects-cache-readonly "Direct link to side-effects-cache-readonly") * Default: **false** * Type: **Boolean** Only use the side effects cache if present, do not create it for new packages. ### unsafe-perm[​](https://pnpm.io/9.x/npmrc#unsafe-perm "Direct link to unsafe-perm") * Default: **false** IF running as root, ELSE **true** * Type: **Boolean** Set to true to enable UID/GID switching when running package scripts. If set explicitly to false, then installing as a non-root user will fail. ### node-options[​](https://pnpm.io/9.x/npmrc#node-options "Direct link to node-options") * Default: **NULL** * Type: **String** Options to pass through to Node.js via the `NODE_OPTIONS` environment variable. This does not impact how pnpm itself is executed but it does impact how lifecycle scripts are called. Node.js Settings[​](https://pnpm.io/9.x/npmrc#nodejs-settings "Direct link to Node.js Settings") ------------------------------------------------------------------------------------------------- ### use-node-version[​](https://pnpm.io/9.x/npmrc#use-node-version "Direct link to use-node-version") * Default: **undefined** * Type: **semver** Specifies which exact Node.js version should be used for the project's runtime. pnpm will automatically install the specified version of Node.js and use it for running `pnpm run` commands or the `pnpm node` command. This may be used instead of `.nvmrc` and `nvm`. Instead of the following `.nvmrc` file: 16.16.0 Use this `.npmrc` file: use-node-version=16.16.0 This setting works only in a `.npmrc` file that is in the root of your workspace. If you need to specify a custom Node.js for a project in the workspace, use the [`pnpm.executionEnv.nodeVersion`](https://pnpm.io/9.x/package_json#pnpmexecutionenvnodeversion) field of `package.json` instead. ### node-version[​](https://pnpm.io/9.x/npmrc#node-version "Direct link to node-version") * Default: the value returned by **node -v**, without the v prefix * Type: **semver** The Node.js version to use when checking a package's `engines` setting. If you want to prevent contributors of your project from adding new incompatible dependencies, use `node-version` and `engine-strict` in a `.npmrc` file at the root of the project: node-version=12.22.0engine-strict=true This way, even if someone is using Node.js v16, they will not be able to install a new dependency that doesn't support Node.js v12.22.0. ### node-mirror:[​](https://pnpm.io/9.x/npmrc#node-mirrorreleasedir "Direct link to node-mirror:") * Default: **`https://nodejs.org/download//`** * Type: **URL** Sets the base URL for downloading Node.js. The `` portion of this setting can be any directory from [https://nodejs.org/download](https://nodejs.org/download) : `release`, `rc`, `nightly`, `v8-canary`, etc. Here is how pnpm may be configured to download Node.js from Node.js mirror in China: node-mirror:release=https://npmmirror.com/mirrors/node/node-mirror:rc=https://npmmirror.com/mirrors/node-rc/node-mirror:nightly=https://npmmirror.com/mirrors/node-nightly/ Workspace Settings[​](https://pnpm.io/9.x/npmrc#workspace-settings "Direct link to Workspace Settings") -------------------------------------------------------------------------------------------------------- ### link-workspace-packages[​](https://pnpm.io/9.x/npmrc#link-workspace-packages "Direct link to link-workspace-packages") * Default: **false** * Type: **true**, **false**, **deep** If this is enabled, locally available packages are linked to `node_modules` instead of being downloaded from the registry. This is very convenient in a monorepo. If you need local packages to also be linked to subdependencies, you can use the `deep` setting. Else, packages are downloaded and installed from the registry. However, workspace packages can still be linked by using the `workspace:` range protocol. ### prefer-workspace-packages[​](https://pnpm.io/9.x/npmrc#prefer-workspace-packages "Direct link to prefer-workspace-packages") * Default: **false** * Type: **Boolean** If this is enabled, local packages from the workspace are preferred over packages from the registry, even if there is a newer version of the package in the registry. This setting is only useful if the workspace doesn't use `save-workspace-protocol`. ### shared-workspace-lockfile[​](https://pnpm.io/9.x/npmrc#shared-workspace-lockfile "Direct link to shared-workspace-lockfile") * Default: **true** * Type: **Boolean** If this is enabled, pnpm creates a single `pnpm-lock.yaml` file in the root of the workspace. This also means that all dependencies of workspace packages will be in a single `node_modules` (and get symlinked to their package `node_modules` folder for Node's module resolution). Advantages of this option: * every dependency is a singleton * faster installations in a monorepo * fewer changes in code reviews as they are all in one file note Even though all the dependencies will be hard linked into the root `node_modules`, packages will have access only to those dependencies that are declared in their `package.json`, so pnpm's strictness is preserved. This is a result of the aforementioned symbolic linking. ### save-workspace-protocol[​](https://pnpm.io/9.x/npmrc#save-workspace-protocol "Direct link to save-workspace-protocol") * Default: **rolling** * Type: **true**, **false**, **rolling** This setting controls how dependencies that are linked from the workspace are added to `package.json`. If `foo@1.0.0` is in the workspace and you run `pnpm add foo` in another project of the workspace, below is how `foo` will be added to the dependencies field. The `save-prefix` setting also influences how the spec is created. | save-workspace-protocol | save-prefix | spec | | --- | --- | --- | | false | `''` | `1.0.0` | | false | `'~'` | `~1.0.0` | | false | `'^'` | `^1.0.0` | | true | `''` | `workspace:1.0.0` | | true | `'~'` | `workspace:~1.0.0` | | true | `'^'` | `workspace:^1.0.0` | | rolling | `''` | `workspace:*` | | rolling | `'~'` | `workspace:~` | | rolling | `'^'` | `workspace:^` | ### include-workspace-root[​](https://pnpm.io/9.x/npmrc#include-workspace-root "Direct link to include-workspace-root") * Default: **false** * Type: **Boolean** When executing commands recursively in a workspace, execute them on the root workspace project as well. ### ignore-workspace-cycles[​](https://pnpm.io/9.x/npmrc#ignore-workspace-cycles "Direct link to ignore-workspace-cycles") * Default: **false** * Type: **Boolean** When set to `true`, no workspace cycle warnings will be printed. ### disallow-workspace-cycles[​](https://pnpm.io/9.x/npmrc#disallow-workspace-cycles "Direct link to disallow-workspace-cycles") * Default: **false** * Type: **Boolean** When set to `true`, installation will fail if the workspace has cycles. Other Settings[​](https://pnpm.io/9.x/npmrc#other-settings "Direct link to Other Settings") -------------------------------------------------------------------------------------------- ### save-prefix[​](https://pnpm.io/9.x/npmrc#save-prefix "Direct link to save-prefix") * Default: **'^'** * Type: **'^'**, **'~'**, **''** Configure how versions of packages installed to a `package.json` file get prefixed. For example, if a package has version `1.2.3`, by default its version is set to `^1.2.3` which allows minor upgrades for that package, but after `pnpm config set save-prefix='~'` it would be set to `~1.2.3` which only allows patch upgrades. This setting is ignored when the added package has a range specified. For instance, `pnpm add foo@2` will set the version of `foo` in `package.json` to `2`, regardless of the value of `save-prefix`. ### tag[​](https://pnpm.io/9.x/npmrc#tag "Direct link to tag") * Default: **latest** * Type: **String** If you `pnpm add` a package and you don't provide a specific version, then it will install the package at the version registered under the tag from this setting. This also sets the tag that is added to the `package@version` specified by the `pnpm tag` command if no explicit tag is given. ### global-dir[​](https://pnpm.io/9.x/npmrc#global-dir "Direct link to global-dir") * Default: * If the **$XDG\_DATA\_HOME** env variable is set, then **$XDG\_DATA\_HOME/pnpm/global** * On Windows: **~/AppData/Local/pnpm/global** * On macOS: **~/Library/pnpm/global** * On Linux: **~/.local/share/pnpm/global** * Type: **path** Specify a custom directory to store global packages. ### global-bin-dir[​](https://pnpm.io/9.x/npmrc#global-bin-dir "Direct link to global-bin-dir") * Default: * If the **$XDG\_DATA\_HOME** env variable is set, then **$XDG\_DATA\_HOME/pnpm** * On Windows: **~/AppData/Local/pnpm** * On macOS: **~/Library/pnpm** * On Linux: **~/.local/share/pnpm** * Type: **path** Allows to set the target directory for the bin files of globally installed packages. ### state-dir[​](https://pnpm.io/9.x/npmrc#state-dir "Direct link to state-dir") * Default: * If the **$XDG\_STATE\_HOME** env variable is set, then **$XDG\_STATE\_HOME/pnpm** * On Windows: **~/AppData/Local/pnpm-state** * On macOS: **~/.pnpm-state** * On Linux: **~/.local/state/pnpm** * Type: **path** The directory where pnpm creates the `pnpm-state.json` file that is currently used only by the update checker. ### cache-dir[​](https://pnpm.io/9.x/npmrc#cache-dir "Direct link to cache-dir") * Default: * If the **$XDG\_CACHE\_HOME** env variable is set, then **$XDG\_CACHE\_HOME/pnpm** * On Windows: **~/AppData/Local/pnpm-cache** * On macOS: **~/Library/Caches/pnpm** * On Linux: **~/.cache/pnpm** * Type: **path** The location of the cache (package metadata and dlx). ### use-stderr[​](https://pnpm.io/9.x/npmrc#use-stderr "Direct link to use-stderr") * Default: **false** * Type: **Boolean** When true, all the output is written to stderr. ### update-notifier[​](https://pnpm.io/9.x/npmrc#update-notifier "Direct link to update-notifier") * Default: **true** * Type: **Boolean** Set to `false` to suppress the update notification when using an older version of pnpm than the latest. ### prefer-symlinked-executables[​](https://pnpm.io/9.x/npmrc#prefer-symlinked-executables "Direct link to prefer-symlinked-executables") * Default: **true**, when **node-linker** is set to **hoisted** and the system is POSIX * Type: **Boolean** Create symlinks to executables in `node_modules/.bin` instead of command shims. This setting is ignored on Windows, where only command shims work. ### ignore-compatibility-db[​](https://pnpm.io/9.x/npmrc#ignore-compatibility-db "Direct link to ignore-compatibility-db") * Default: **false** * Type: **Boolean** During installation the dependencies of some packages are automatically patched. If you want to disable this, set this config to `false`. The patches are applied from Yarn's [`@yarnpkg/extensions`](https://github.com/yarnpkg/berry/blob/master/packages/yarnpkg-extensions/sources/index.ts) package. ### resolution-mode[​](https://pnpm.io/9.x/npmrc#resolution-mode "Direct link to resolution-mode") * Default: **highest** (was **lowest-direct** from v8.0.0 to v8.6.12) * Type: **highest**, **time-based**, **lowest-direct** When `resolution-mode` is set to `time-based`, dependencies will be resolved the following way: 1. Direct dependencies will be resolved to their lowest versions. So if there is `foo@^1.1.0` in the dependencies, then `1.1.0` will be installed. 2. Subdependencies will be resolved from versions that were published before the last direct dependency was published. With this resolution mode installations with warm cache are faster. It also reduces the chance of subdependency hijacking as subdependencies will be updated only if direct dependencies are updated. This resolution mode works only with npm's [full metadata](https://github.com/npm/registry/blob/master/docs/responses/package-metadata.md#full-metadata-format) . So it is slower in some scenarios. However, if you use [Verdaccio](https://verdaccio.org/) v5.15.1 or newer, you may set the `registry-supports-time-field` setting to `true`, and it will be really fast. When `resolution-mode` is set to `lowest-direct`, direct dependencies will be resolved to their lowest versions. ### registry-supports-time-field[​](https://pnpm.io/9.x/npmrc#registry-supports-time-field "Direct link to registry-supports-time-field") * Default: **false** * Type: **Boolean** Set this to `true` if the registry that you are using returns the "time" field in the abbreviated metadata. As of now, only [Verdaccio](https://verdaccio.org/) from v5.15.1 supports this. ### extend-node-path[​](https://pnpm.io/9.x/npmrc#extend-node-path "Direct link to extend-node-path") * Default: **true** * Type: **Boolean** When `false`, the `NODE_PATH` environment variable is not set in the command shims. ### deploy-all-files[​](https://pnpm.io/9.x/npmrc#deploy-all-files "Direct link to deploy-all-files") * Default: **false** * Type: **Boolean** When deploying a package or installing a local package, all files of the package are copied. By default, if the package has a `"files"` field in the `package.json`, then only the listed files and directories are copied. ### dedupe-direct-deps[​](https://pnpm.io/9.x/npmrc#dedupe-direct-deps "Direct link to dedupe-direct-deps") * Default: **false** * Type: **Boolean** When set to `true`, dependencies that are already symlinked to the root `node_modules` directory of the workspace will not be symlinked to subproject `node_modules` directories. ### dedupe-injected-deps[​](https://pnpm.io/9.x/npmrc#dedupe-injected-deps "Direct link to dedupe-injected-deps") * Default: **true** * Type: **Boolean** When this setting is enabled, [dependencies that are injected](https://pnpm.io/9.x/package_json#dependenciesmetainjected) will be symlinked from the workspace whenever possible. If the dependent project and the injected dependency reference the same peer dependencies, then it is not necessary to physically copy the injected dependency into the dependent's `node_modules`; a symlink is sufficient. * [Dependency Hoisting Settings](https://pnpm.io/9.x/npmrc#dependency-hoisting-settings) * [hoist](https://pnpm.io/9.x/npmrc#hoist) * [hoist-workspace-packages](https://pnpm.io/9.x/npmrc#hoist-workspace-packages) * [hoist-pattern](https://pnpm.io/9.x/npmrc#hoist-pattern) * [public-hoist-pattern](https://pnpm.io/9.x/npmrc#public-hoist-pattern) * [shamefully-hoist](https://pnpm.io/9.x/npmrc#shamefully-hoist) * [Node-Modules Settings](https://pnpm.io/9.x/npmrc#node-modules-settings) * [modules-dir](https://pnpm.io/9.x/npmrc#modules-dir) * [node-linker](https://pnpm.io/9.x/npmrc#node-linker) * [symlink](https://pnpm.io/9.x/npmrc#symlink) * [enable-modules-dir](https://pnpm.io/9.x/npmrc#enable-modules-dir) * [virtual-store-dir](https://pnpm.io/9.x/npmrc#virtual-store-dir) * [virtual-store-dir-max-length](https://pnpm.io/9.x/npmrc#virtual-store-dir-max-length) * [package-import-method](https://pnpm.io/9.x/npmrc#package-import-method) * [modules-cache-max-age](https://pnpm.io/9.x/npmrc#modules-cache-max-age) * [dlx-cache-max-age](https://pnpm.io/9.x/npmrc#dlx-cache-max-age) * [Store Settings](https://pnpm.io/9.x/npmrc#store-settings) * [store-dir](https://pnpm.io/9.x/npmrc#store-dir) * [verify-store-integrity](https://pnpm.io/9.x/npmrc#verify-store-integrity) * [use-running-store-server](https://pnpm.io/9.x/npmrc#use-running-store-server) * [strict-store-pkg-content-check](https://pnpm.io/9.x/npmrc#strict-store-pkg-content-check) * [Lockfile Settings](https://pnpm.io/9.x/npmrc#lockfile-settings) * [lockfile](https://pnpm.io/9.x/npmrc#lockfile) * [prefer-frozen-lockfile](https://pnpm.io/9.x/npmrc#prefer-frozen-lockfile) * [lockfile-include-tarball-url](https://pnpm.io/9.x/npmrc#lockfile-include-tarball-url) * [git-branch-lockfile](https://pnpm.io/9.x/npmrc#git-branch-lockfile) * [merge-git-branch-lockfiles-branch-pattern](https://pnpm.io/9.x/npmrc#merge-git-branch-lockfiles-branch-pattern) * [peers-suffix-max-length](https://pnpm.io/9.x/npmrc#peers-suffix-max-length) * [Registry & Authentication Settings](https://pnpm.io/9.x/npmrc#registry--authentication-settings) * [registry](https://pnpm.io/9.x/npmrc#registry) * [:\_authToken](https://pnpm.io/9.x/npmrc#url_authtoken) * [:tokenHelper](https://pnpm.io/9.x/npmrc#urltokenhelper) * [Request Settings](https://pnpm.io/9.x/npmrc#request-settings) * [ca](https://pnpm.io/9.x/npmrc#ca) * [cafile](https://pnpm.io/9.x/npmrc#cafile) * [:cafile](https://pnpm.io/9.x/npmrc#urlcafile) * [cert](https://pnpm.io/9.x/npmrc#cert) * [:certfile](https://pnpm.io/9.x/npmrc#urlcertfile) * [key](https://pnpm.io/9.x/npmrc#key) * [:keyfile](https://pnpm.io/9.x/npmrc#urlkeyfile) * [git-shallow-hosts](https://pnpm.io/9.x/npmrc#git-shallow-hosts) * [https-proxy](https://pnpm.io/9.x/npmrc#https-proxy) * [http-proxy](https://pnpm.io/9.x/npmrc#http-proxy) * [proxy](https://pnpm.io/9.x/npmrc#proxy) * [local-address](https://pnpm.io/9.x/npmrc#local-address) * [maxsockets](https://pnpm.io/9.x/npmrc#maxsockets) * [noproxy](https://pnpm.io/9.x/npmrc#noproxy) * [strict-ssl](https://pnpm.io/9.x/npmrc#strict-ssl) * [network-concurrency](https://pnpm.io/9.x/npmrc#network-concurrency) * [fetch-retries](https://pnpm.io/9.x/npmrc#fetch-retries) * [fetch-retry-factor](https://pnpm.io/9.x/npmrc#fetch-retry-factor) * [fetch-retry-mintimeout](https://pnpm.io/9.x/npmrc#fetch-retry-mintimeout) * [fetch-retry-maxtimeout](https://pnpm.io/9.x/npmrc#fetch-retry-maxtimeout) * [fetch-timeout](https://pnpm.io/9.x/npmrc#fetch-timeout) * [Peer Dependency Settings](https://pnpm.io/9.x/npmrc#peer-dependency-settings) * [auto-install-peers](https://pnpm.io/9.x/npmrc#auto-install-peers) * [dedupe-peer-dependents](https://pnpm.io/9.x/npmrc#dedupe-peer-dependents) * [strict-peer-dependencies](https://pnpm.io/9.x/npmrc#strict-peer-dependencies) * [resolve-peers-from-workspace-root](https://pnpm.io/9.x/npmrc#resolve-peers-from-workspace-root) * [CLI Settings](https://pnpm.io/9.x/npmrc#cli-settings) * [\[no-\]color](https://pnpm.io/9.x/npmrc#no-color) * [loglevel](https://pnpm.io/9.x/npmrc#loglevel) * [use-beta-cli](https://pnpm.io/9.x/npmrc#use-beta-cli) * [recursive-install](https://pnpm.io/9.x/npmrc#recursive-install) * [engine-strict](https://pnpm.io/9.x/npmrc#engine-strict) * [npm-path](https://pnpm.io/9.x/npmrc#npm-path) * [package-manager-strict](https://pnpm.io/9.x/npmrc#package-manager-strict) * [package-manager-strict-version](https://pnpm.io/9.x/npmrc#package-manager-strict-version) * [manage-package-manager-versions](https://pnpm.io/9.x/npmrc#manage-package-manager-versions) * [Build Settings](https://pnpm.io/9.x/npmrc#build-settings) * [ignore-scripts](https://pnpm.io/9.x/npmrc#ignore-scripts) * [ignore-dep-scripts](https://pnpm.io/9.x/npmrc#ignore-dep-scripts) * [child-concurrency](https://pnpm.io/9.x/npmrc#child-concurrency) * [side-effects-cache](https://pnpm.io/9.x/npmrc#side-effects-cache) * [side-effects-cache-readonly](https://pnpm.io/9.x/npmrc#side-effects-cache-readonly) * [unsafe-perm](https://pnpm.io/9.x/npmrc#unsafe-perm) * [node-options](https://pnpm.io/9.x/npmrc#node-options) * [Node.js Settings](https://pnpm.io/9.x/npmrc#nodejs-settings) * [use-node-version](https://pnpm.io/9.x/npmrc#use-node-version) * [node-version](https://pnpm.io/9.x/npmrc#node-version) * [node-mirror:](https://pnpm.io/9.x/npmrc#node-mirrorreleasedir) * [Workspace Settings](https://pnpm.io/9.x/npmrc#workspace-settings) * [link-workspace-packages](https://pnpm.io/9.x/npmrc#link-workspace-packages) * [prefer-workspace-packages](https://pnpm.io/9.x/npmrc#prefer-workspace-packages) * [shared-workspace-lockfile](https://pnpm.io/9.x/npmrc#shared-workspace-lockfile) * [save-workspace-protocol](https://pnpm.io/9.x/npmrc#save-workspace-protocol) * [include-workspace-root](https://pnpm.io/9.x/npmrc#include-workspace-root) * [ignore-workspace-cycles](https://pnpm.io/9.x/npmrc#ignore-workspace-cycles) * [disallow-workspace-cycles](https://pnpm.io/9.x/npmrc#disallow-workspace-cycles) * [Other Settings](https://pnpm.io/9.x/npmrc#other-settings) * [save-prefix](https://pnpm.io/9.x/npmrc#save-prefix) * [tag](https://pnpm.io/9.x/npmrc#tag) * [global-dir](https://pnpm.io/9.x/npmrc#global-dir) * [global-bin-dir](https://pnpm.io/9.x/npmrc#global-bin-dir) * [state-dir](https://pnpm.io/9.x/npmrc#state-dir) * [cache-dir](https://pnpm.io/9.x/npmrc#cache-dir) * [use-stderr](https://pnpm.io/9.x/npmrc#use-stderr) * [update-notifier](https://pnpm.io/9.x/npmrc#update-notifier) * [prefer-symlinked-executables](https://pnpm.io/9.x/npmrc#prefer-symlinked-executables) * [ignore-compatibility-db](https://pnpm.io/9.x/npmrc#ignore-compatibility-db) * [resolution-mode](https://pnpm.io/9.x/npmrc#resolution-mode) * [registry-supports-time-field](https://pnpm.io/9.x/npmrc#registry-supports-time-field) * [extend-node-path](https://pnpm.io/9.x/npmrc#extend-node-path) * [deploy-all-files](https://pnpm.io/9.x/npmrc#deploy-all-files) * [dedupe-direct-deps](https://pnpm.io/9.x/npmrc#dedupe-direct-deps) * [dedupe-injected-deps](https://pnpm.io/9.x/npmrc#dedupe-injected-deps) --- # pnpm CLI | pnpm [Skip to main content](https://pnpm.io/9.x/pnpm-cli#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/pnpm-cli) ** (10.x). Version: 9.x On this page Differences vs npm[​](https://pnpm.io/9.x/pnpm-cli#differences-vs-npm "Direct link to Differences vs npm") ----------------------------------------------------------------------------------------------------------- Unlike npm, pnpm validates all options. For example, `pnpm install --target_arch x64` will fail as `--target_arch` is not a valid option for `pnpm install`. However, some dependencies may use the `npm_config_` environment variable, which is populated from the CLI options. In this case, you have the following options: 1. explicitly set the env variable: `npm_config_target_arch=x64 pnpm install` 2. force the unknown option with `--config.`: `pnpm install --config.target_arch=x64` Options[​](https://pnpm.io/9.x/pnpm-cli#options "Direct link to Options") -------------------------------------------------------------------------- ### \-C , --dir [​](https://pnpm.io/9.x/pnpm-cli#-c-path---dir-path "Direct link to -C , --dir ") Run as if pnpm was started in `` instead of the current working directory. ### \-w, --workspace-root[​](https://pnpm.io/9.x/pnpm-cli#-w---workspace-root "Direct link to -w, --workspace-root") Run as if pnpm was started in the root of the [workspace](https://pnpm.io/9.x/workspaces) instead of the current working directory. Commands[​](https://pnpm.io/9.x/pnpm-cli#commands "Direct link to Commands") ----------------------------------------------------------------------------- For more information, see the documentation for individual CLI commands. Here is a list of handy npm equivalents to get you started: | npm command | pnpm equivalent | | --- | --- | | `npm install` | [`pnpm install`](https://pnpm.io/9.x/cli/install) | | `npm i ` | [`pnpm add `](https://pnpm.io/9.x/cli/add) | | `npm run ` | [`pnpm `](https://pnpm.io/9.x/cli/run) | When an unknown command is used, pnpm will search for a script with the given name, so `pnpm run lint` is the same as `pnpm lint`. If there is no script with the specified name, then pnpm will execute the command as a shell script, so you can do things like `pnpm eslint` (see [pnpm exec](https://pnpm.io/9.x/cli/exec) ). Environment variables[​](https://pnpm.io/9.x/pnpm-cli#environment-variables "Direct link to Environment variables") -------------------------------------------------------------------------------------------------------------------- Some environment variables that are not pnpm related might change the behaviour of pnpm: * [`CI`](https://pnpm.io/9.x/cli/install#frozen-lockfile) These environment variables may influence what directories pnpm will use for storing global information: * `XDG_CACHE_HOME` * `XDG_CONFIG_HOME` * `XDG_DATA_HOME` * `XDG_STATE_HOME` You can search the docs to find the settings that leverage these environment variables. * [Differences vs npm](https://pnpm.io/9.x/pnpm-cli#differences-vs-npm) * [Options](https://pnpm.io/9.x/pnpm-cli#options) * [\-C , --dir ](https://pnpm.io/9.x/pnpm-cli#-c-path---dir-path) * [\-w, --workspace-root](https://pnpm.io/9.x/pnpm-cli#-w---workspace-root) * [Commands](https://pnpm.io/9.x/pnpm-cli#commands) * [Environment variables](https://pnpm.io/9.x/pnpm-cli#environment-variables) --- # pnpm-workspace.yaml | pnpm [Skip to main content](https://pnpm.io/9.x/pnpm-workspace_yaml#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/pnpm-workspace_yaml) ** (10.x). Version: 9.x `pnpm-workspace.yaml` defines the root of the [workspace](https://pnpm.io/9.x/workspaces) and enables you to include / exclude directories from the workspace. By default, all packages of all subdirectories are included. For example: pnpm-workspace.yaml packages: # specify a package in a direct subdir of the root - 'my-app' # all packages in direct subdirs of packages/ - 'packages/*' # all packages in subdirs of components/ - 'components/**' # exclude packages that are inside test directories - '!**/test/**' The root package is always included, even when custom location wildcards are used. Catalogs are also defined in the `pnpm-workspace.yaml` file. See [_Catalogs_](https://pnpm.io/9.x/catalogs) for details. pnpm-workspace.yaml packages: - 'packages/*'catalog: chalk: ^4.1.2catalogs: react16: react: ^16.7.0 react-dom: ^16.7.0 react17: react: ^17.10.0 react-dom: ^17.10.0 --- # pnpm vs npm | pnpm [Skip to main content](https://pnpm.io/9.x/pnpm-vs-npm#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/pnpm-vs-npm) ** (10.x). Version: 9.x On this page npm's flat tree[​](https://pnpm.io/9.x/pnpm-vs-npm#npms-flat-tree "Direct link to npm's flat tree") ---------------------------------------------------------------------------------------------------- npm maintains a [flattened dependency tree](https://github.com/npm/npm/issues/6912) as of version 3. This leads to less disk space bloat, with a messy `node_modules` directory as a side effect. On the other hand, pnpm manages `node_modules` by using hard linking and symbolic linking to a global on-disk content-addressable store. This lets you get the benefits of far less disk space usage, while also keeping your `node_modules` clean. There is documentation on the [store layout](https://pnpm.io/9.x/symlinked-node-modules-structure) if you wish to learn more. The good thing about pnpm's proper `node_modules` structure is that it "[helps to avoid silly bugs](https://www.kochan.io/nodejs/pnpms-strictness-helps-to-avoid-silly-bugs.html) " by making it impossible to use modules that are not specified in the project's `package.json`. Installation[​](https://pnpm.io/9.x/pnpm-vs-npm#installation "Direct link to Installation") -------------------------------------------------------------------------------------------- pnpm does not allow installation of packages without saving them to `package.json`. If no parameters are passed to `pnpm add`, packages are saved as regular dependencies. Like with npm, `--save-dev` and `--save-optional` can be used to install packages as dev or optional dependencies. As a consequence of this limitation, projects won't have any extraneous packages when they use pnpm unless they remove a dependency and leave it orphaned. That's why pnpm's implementation of the [prune command](https://pnpm.io/9.x/cli/prune) does not allow you to specify packages to prune - it ALWAYS removes all extraneous and orphaned packages. Directory dependencies[​](https://pnpm.io/9.x/pnpm-vs-npm#directory-dependencies "Direct link to Directory dependencies") -------------------------------------------------------------------------------------------------------------------------- Directory dependencies start with the `file:` prefix and point to a directory in the filesystem. Like npm, pnpm symlinks those dependencies. Unlike npm, pnpm does not perform installation for the file dependencies. This means that if you have a package called `foo` (`/foo`) that has `bar@file:../bar` as a dependency, pnpm won't perform installation for `/bar` when you run `pnpm install` on `foo`. If you need to run installations in several packages at the same time, for instance in the case of a monorepo, you should look at the documentation for [`pnpm -r`](https://pnpm.io/9.x/cli/recursive) . * [npm's flat tree](https://pnpm.io/9.x/pnpm-vs-npm#npms-flat-tree) * [Installation](https://pnpm.io/9.x/pnpm-vs-npm#installation) * [Directory dependencies](https://pnpm.io/9.x/pnpm-vs-npm#directory-dependencies) --- # .pnpmfile.cjs | pnpm [Skip to main content](https://pnpm.io/9.x/pnpmfile#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/pnpmfile) ** (10.x). Version: 9.x On this page pnpm lets you hook directly into the installation process via special functions (hooks). Hooks can be declared in a file called `.pnpmfile.cjs`. By default, `.pnpmfile.cjs` should be located in the same directory as the lockfile. For instance, in a [workspace](https://pnpm.io/9.x/workspaces) with a shared lockfile, `.pnpmfile.cjs` should be in the root of the monorepo. Hooks[​](https://pnpm.io/9.x/pnpmfile#hooks "Direct link to Hooks") -------------------------------------------------------------------- ### TL;DR[​](https://pnpm.io/9.x/pnpmfile#tldr "Direct link to TL;DR") | Hook Function | Process | Uses | | --- | --- | --- | | `hooks.readPackage(pkg, context): pkg` | Called after pnpm parses the dependency's package manifest | Allows you to mutate a dependency's `package.json` | | `hooks.afterAllResolved(lockfile, context): lockfile` | Called after the dependencies have been resolved. | Allows you to mutate the lockfile. | ### `hooks.readPackage(pkg, context): pkg | Promise`[​](https://pnpm.io/9.x/pnpmfile#hooksreadpackagepkg-context-pkg--promisepkg "Direct link to hooksreadpackagepkg-context-pkg--promisepkg") Allows you to mutate a dependency's `package.json` after parsing and prior to resolution. These mutations are not saved to the filesystem, however, they will affect what gets resolved in the lockfile and therefore what gets installed. Note that you will need to delete the `pnpm-lock.yaml` if you have already resolved the dependency you want to modify. tip If you need changes to `package.json` saved to the filesystem, you need to use the [`pnpm patch`](https://pnpm.io/9.x/cli/patch) command and patch the `package.json` file. This might be useful if you want to remove the `bin` field of a dependency for instance. #### Arguments[​](https://pnpm.io/9.x/pnpmfile#arguments "Direct link to Arguments") * `pkg` - The manifest of the package. Either the response from the registry or the `package.json` content. * `context` - Context object for the step. Method `#log(msg)` allows you to use a debug log for the step. #### Usage[​](https://pnpm.io/9.x/pnpmfile#usage "Direct link to Usage") Example `.pnpmfile.cjs` (changes the dependencies of a dependency): function readPackage(pkg, context) { // Override the manifest of foo@1.x after downloading it from the registry if (pkg.name === 'foo' && pkg.version.startsWith('1.')) { // Replace bar@x.x.x with bar@2.0.0 pkg.dependencies = { ...pkg.dependencies, bar: '^2.0.0' } context.log('bar@1 => bar@2 in dependencies of foo') } // This will change any packages using baz@x.x.x to use baz@1.2.3 if (pkg.dependencies.baz) { pkg.dependencies.baz = '1.2.3'; } return pkg}module.exports = { hooks: { readPackage }} #### Known limitations[​](https://pnpm.io/9.x/pnpmfile#known-limitations "Direct link to Known limitations") Removing the `scripts` field from a dependency's manifest via `readPackage` will not prevent pnpm from building the dependency. When building a dependency, pnpm reads the `package.json` of the package from the package's archive, which is not affected by the hook. In order to ignore a package's build, use the [pnpm.neverBuiltDependencies](https://pnpm.io/9.x/package_json#pnpmneverbuiltdependencies) field. ### `hooks.afterAllResolved(lockfile, context): lockfile | Promise`[​](https://pnpm.io/9.x/pnpmfile#hooksafterallresolvedlockfile-context-lockfile--promiselockfile "Direct link to hooksafterallresolvedlockfile-context-lockfile--promiselockfile") Allows you to mutate the lockfile output before it is serialized. #### Arguments[​](https://pnpm.io/9.x/pnpmfile#arguments-1 "Direct link to Arguments") * `lockfile` - The lockfile resolutions object that is serialized to `pnpm-lock.yaml`. * `context` - Context object for the step. Method `#log(msg)` allows you to use a debug log for the step. #### Usage example[​](https://pnpm.io/9.x/pnpmfile#usage-example "Direct link to Usage example") .pnpmfile.cjs function afterAllResolved(lockfile, context) { // ... return lockfile}module.exports = { hooks: { afterAllResolved }} #### Known Limitations[​](https://pnpm.io/9.x/pnpmfile#known-limitations-1 "Direct link to Known Limitations") There are none - anything that can be done with the lockfile can be modified via this function, and you can even extend the lockfile's functionality. Related Configuration[​](https://pnpm.io/9.x/pnpmfile#related-configuration "Direct link to Related Configuration") -------------------------------------------------------------------------------------------------------------------- ### ignore-pnpmfile[​](https://pnpm.io/9.x/pnpmfile#ignore-pnpmfile "Direct link to ignore-pnpmfile") * Default: **false** * Type: **Boolean** `.pnpmfile.cjs` will be ignored. Useful together with `--ignore-scripts` when you want to make sure that no script gets executed during install. ### pnpmfile[​](https://pnpm.io/9.x/pnpmfile#pnpmfile "Direct link to pnpmfile") * Default: **.pnpmfile.cjs** * Type: **path** * Example: **.pnpm/.pnpmfile.cjs** The location of the local pnpmfile. ### global-pnpmfile[​](https://pnpm.io/9.x/pnpmfile#global-pnpmfile "Direct link to global-pnpmfile") * Default: **null** * Type: **path** * Example: **~/.pnpm/global\_pnpmfile.cjs** The location of a global pnpmfile. A global pnpmfile is used by all projects during installation. note It is recommended to use local pnpmfiles. Only use a global pnpmfile if you use pnpm on projects that don't use pnpm as the primary package manager. * [Hooks](https://pnpm.io/9.x/pnpmfile#hooks) * [TL;DR](https://pnpm.io/9.x/pnpmfile#tldr) * [`hooks.readPackage(pkg, context): pkg | Promise`](https://pnpm.io/9.x/pnpmfile#hooksreadpackagepkg-context-pkg--promisepkg) * [`hooks.afterAllResolved(lockfile, context): lockfile | Promise`](https://pnpm.io/9.x/pnpmfile#hooksafterallresolvedlockfile-context-lockfile--promiselockfile) * [Related Configuration](https://pnpm.io/9.x/pnpmfile#related-configuration) * [ignore-pnpmfile](https://pnpm.io/9.x/pnpmfile#ignore-pnpmfile) * [pnpmfile](https://pnpm.io/9.x/pnpmfile#pnpmfile) * [global-pnpmfile](https://pnpm.io/9.x/pnpmfile#global-pnpmfile) --- # Scripts | pnpm [Skip to main content](https://pnpm.io/9.x/scripts#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/scripts) ** (10.x). Version: 9.x On this page How pnpm handles the `scripts` field of `package.json`. Lifecycle Scripts[​](https://pnpm.io/9.x/scripts#lifecycle-scripts "Direct link to Lifecycle Scripts") ------------------------------------------------------------------------------------------------------- ### `pnpm:devPreinstall`[​](https://pnpm.io/9.x/scripts#pnpmdevpreinstall "Direct link to pnpmdevpreinstall") Runs only on local `pnpm install`. Runs before any dependency is installed. This script is executed only when set in the root project's `package.json`. * [Lifecycle Scripts](https://pnpm.io/9.x/scripts#lifecycle-scripts) * [`pnpm:devPreinstall`](https://pnpm.io/9.x/scripts#pnpmdevpreinstall) --- # Working with Podman | pnpm [Skip to main content](https://pnpm.io/9.x/podman#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/podman) ** (10.x). Version: 9.x On this page Sharing Files Between a Container and the Host Btrfs Filesystem[​](https://pnpm.io/9.x/podman#sharing-files-between-a-container-and-the-host-btrfs-filesystem "Direct link to Sharing Files Between a Container and the Host Btrfs Filesystem") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ note This method only works on copy-on-write filesystems supported by Podman, such as Btrfs. For other filesystems, like Ext4, pnpm will copy the files instead. Podman support copy-on-write filesystems like Btrfs. With Btrfs, container runtimes create actual Btrfs subvolumes for their mounted volumes. pnpm can leverage this behavior to reflink the files between different mounted volumes. To share files between the host and the container, mount the store directory and the `node_modules` directory from the host to the container. This allows pnpm inside the container to naturally reuse the files from the host as reflinks. Below is an example container setup for demonstration: Dockerfile FROM node:20-slim# corepack is an experimental feature in Node.js v20 which allows# installing and managing versions of pnpm, npm, yarnRUN corepack enableVOLUME [ "/pnpm-store", "/app/node_modules" ]RUN pnpm config --global set store-dir /pnpm-store# You may need to copy more files than just package.json in your codeCOPY package.json /app/package.jsonWORKDIR /appRUN pnpm installRUN pnpm run build Run the following command to build the podman image: podman build . --tag my-podman-image:latest -v "$HOME/.local/share/pnpm/store:/pnpm-store" -v "$(pwd)/node_modules:/app/node_modules" * [Sharing Files Between a Container and the Host Btrfs Filesystem](https://pnpm.io/9.x/podman#sharing-files-between-a-container-and-the-host-btrfs-filesystem) --- # pnpm cache | pnpm [Skip to main content](https://pnpm.io/next/cli/cache#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is unreleased documentation for pnpm **Next** version. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/cache) ** (10.x). Version: Next Commands: * [cache list](https://pnpm.io/next/cli/cache-list) * [cache list-registries](https://pnpm.io/next/cli/cache-list-registries) * [cache delete](https://pnpm.io/next/cli/cache-delete) * [cache view](https://pnpm.io/next/cli/cache-view) --- # pnpm cat-index | pnpm [Skip to main content](https://pnpm.io/next/cli/cat-index#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is unreleased documentation for pnpm **Next** version. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/cat-index) ** (10.x). Version: Next Prints the index file of a specific package from the store. The package is specified by its name and version: pnpm cat-index @ --- # pnpm cat-file | pnpm [Skip to main content](https://pnpm.io/next/cli/cat-file#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is unreleased documentation for pnpm **Next** version. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/cat-file) ** (10.x). Version: Next Prints the contents of a file based on the hash value stored in the index file. For example: pnpm cat-file sha512-mvavhfVcEREI7d8dfvfvIkuBLnx7+rrkHHnPi8mpEDUlNpY4CUY+CvJ5mrrLl18iQYo1odFwBV7z/cOypG7xxQ== --- # pnpm find-hash | pnpm [Skip to main content](https://pnpm.io/next/cli/find-hash#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is unreleased documentation for pnpm **Next** version. For up-to-date documentation, see the **[latest version](https://pnpm.io/cli/find-hash) ** (10.x). Version: Next warning This command is experimental Lists the packages that include the file with the specified hash. For example: pnpm find-hash sha512-mvavhfVcEREI7d8dfvfvIkuBLnx7+rrkHHnPi8mpEDUlNpY4CUY+CvJ5mrrLl18iQYo1odFwBV7z/cOypG7xxQ== --- # Uninstalling pnpm | pnpm [Skip to main content](https://pnpm.io/9.x/uninstall#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/uninstall) ** (10.x). Version: 9.x On this page Removing the globally installed packages[​](https://pnpm.io/9.x/uninstall#removing-the-globally-installed-packages "Direct link to Removing the globally installed packages") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Before removing the pnpm CLI, it might make sense to remove all global packages that were installed by pnpm. To list all the global packages, run `pnpm ls -g`. There are two ways to remove the global packages: 1. Run `pnpm rm -g ...` with each global package listed. 2. Run `pnpm root -g` to find the location of the global directory and remove it manually. Removing the pnpm CLI[​](https://pnpm.io/9.x/uninstall#removing-the-pnpm-cli "Direct link to Removing the pnpm CLI") --------------------------------------------------------------------------------------------------------------------- If you used the standalone script to install pnpm, then you should be able to uninstall the pnpm CLI by removing the pnpm home directory: rm -rf $PNPM_HOME You might also want to clean the `PNPM_HOME` env variable in your shell configuration file (`$HOME/.bashrc`, `$HOME/.zshrc` or `$HOME/.config/fish/config.fish`). If you used npm to install pnpm, then you should use npm to uninstall pnpm: npm rm -g pnpm Removing the global content-addressable store[​](https://pnpm.io/9.x/uninstall#removing-the-global-content-addressable-store "Direct link to Removing the global content-addressable store") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- rm -rf $(pnpm store path) If you used pnpm in non-primary disks, then you must run the above command in every disk, where pnpm was used. pnpm creates one store per disk. * [Removing the globally installed packages](https://pnpm.io/9.x/uninstall#removing-the-globally-installed-packages) * [Removing the pnpm CLI](https://pnpm.io/9.x/uninstall#removing-the-pnpm-cli) * [Removing the global content-addressable store](https://pnpm.io/9.x/uninstall#removing-the-global-content-addressable-store) --- # Symlinked `node_modules` structure | pnpm [Skip to main content](https://pnpm.io/9.x/symlinked-node-modules-structure#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/symlinked-node-modules-structure) ** (10.x). Version: 9.x info This article only describes how pnpm's `node_modules` are structured when there are no packages with peer dependencies. For the more complex scenario of dependencies with peers, see [how peers are resolved](https://pnpm.io/9.x/how-peers-are-resolved) . pnpm's `node_modules` layout uses symbolic links to create a nested structure of dependencies. Every file of every package inside `node_modules` is a hard link to the content-addressable store. Let's say you install `foo@1.0.0` that depends on `bar@1.0.0`. pnpm will hard link both packages to `node_modules` like this: node_modules└── .pnpm ├── bar@1.0.0 │ └── node_modules │ └── bar -> /bar │ ├── index.js │ └── package.json └── foo@1.0.0 └── node_modules └── foo -> /foo ├── index.js └── package.json These are the only "real" files in `node_modules`. Once all the packages are hard linked to `node_modules`, symbolic links are created to build the nested dependency graph structure. As you might have noticed, both packages are hard linked into a subfolder inside a `node_modules` folder (`foo@1.0.0/node_modules/foo`). This is needed to: 1. **allow packages to import themselves.** `foo` should be able to `require('foo/package.json')` or `import * as package from "foo/package.json"`. 2. **avoid circular symlinks.** Dependencies of packages are placed in the same folder in which the dependent packages are. For Node.js it doesn't make a difference whether dependencies are inside the package's `node_modules` or in any other `node_modules` in the parent directories. The next stage of installation is symlinking dependencies. `bar` is going to be symlinked to the `foo@1.0.0/node_modules` folder: node_modules└── .pnpm ├── bar@1.0.0 │ └── node_modules │ └── bar -> /bar └── foo@1.0.0 └── node_modules ├── foo -> /foo └── bar -> ../../bar@1.0.0/node_modules/bar Next, direct dependencies are handled. `foo` is going to be symlinked into the root `node_modules` folder because `foo` is a dependency of the project: node_modules├── foo -> ./.pnpm/foo@1.0.0/node_modules/foo└── .pnpm ├── bar@1.0.0 │ └── node_modules │ └── bar -> /bar └── foo@1.0.0 └── node_modules ├── foo -> /foo └── bar -> ../../bar@1.0.0/node_modules/bar This is a very simple example. However, the layout will maintain this structure regardless of the number of dependencies and the depth of the dependency graph. Let's add `qar@2.0.0` as a dependency of `bar` and `foo`. This is how the new structure will look: node_modules├── foo -> ./.pnpm/foo@1.0.0/node_modules/foo└── .pnpm ├── bar@1.0.0 │ └── node_modules │ ├── bar -> /bar │ └── qar -> ../../qar@2.0.0/node_modules/qar ├── foo@1.0.0 │ └── node_modules │ ├── foo -> /foo │ ├── bar -> ../../bar@1.0.0/node_modules/bar │ └── qar -> ../../qar@2.0.0/node_modules/qar └── qar@2.0.0 └── node_modules └── qar -> /qar As you may see, even though the graph is deeper now (`foo > bar > qar`), the directory depth in the file system is still the same. This layout might look weird at first glance, but it is completely compatible with Node's module resolution algorithm! When resolving modules, Node ignores symlinks, so when `bar` is required from `foo@1.0.0/node_modules/foo/index.js`, Node does not use `bar` at `foo@1.0.0/node_modules/bar`, but instead, `bar` is resolved to its real location (`bar@1.0.0/node_modules/bar`). As a consequence, `bar` can also resolve its dependencies which are in `bar@1.0.0/node_modules`. A great bonus of this layout is that only packages that are really in the dependencies are accessible. With a flattened `node_modules` structure, all hoisted packages are accessible. To read more about why this is an advantage, see "[pnpm's strictness helps to avoid silly bugs](https://www.kochan.io/nodejs/pnpms-strictness-helps-to-avoid-silly-bugs.html) " --- # package.json | pnpm [Skip to main content](https://pnpm.io/9.x/package_json#__docusaurus_skipToContent_fallback) Learn how to **[Mitigate supply chain attacks with pnpm](https://pnpm.io/supply-chain-security) ** This is documentation for pnpm **9.x**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://pnpm.io/package_json) ** (10.x). Version: 9.x On this page The manifest file of a package. It contains all the package's metadata, including dependencies, title, author, et cetera. This is a standard preserved across all major Node.JS package managers, including pnpm. engines[​](https://pnpm.io/9.x/package_json#engines "Direct link to engines") ------------------------------------------------------------------------------ You can specify the version of Node and pnpm that your software works on: { "engines": { "node": ">=10", "pnpm": ">=3" }} During local development, pnpm will always fail with an error message if its version does not match the one specified in the `engines` field. Unless the user has set the `engine-strict` config flag (see [.npmrc](https://pnpm.io/9.x/npmrc#engine-strict) ), this field is advisory only and will only produce warnings when your package is installed as a dependency. dependenciesMeta[​](https://pnpm.io/9.x/package_json#dependenciesmeta "Direct link to dependenciesMeta") --------------------------------------------------------------------------------------------------------- Additional meta information used for dependencies declared inside `dependencies`, `optionalDependencies`, and `devDependencies`. ### dependenciesMeta.\*.injected[​](https://pnpm.io/9.x/package_json#dependenciesmetainjected "Direct link to dependenciesMeta.*.injected") If this is set to `true` for a dependency that is a local workspace package, that package will be installed by creating a hard linked copy in the virtual store (`node_modules/.pnpm`). If this is set to `false` or not set, then the dependency will instead be installed by creating a `node_modules` symlink that points to the package's source directory in the workspace. This is the default, as it is faster and ensures that any modifications to the dependency will be immediately visible to its consumers. For example, suppose the following `package.json` is a local workspace package: { "name": "card", "dependencies": { "button": "workspace:1.0.0" }} The `button` dependency will normally be installed by creating a symlink in the `node_modules` directory of `card`, pointing to the development directory for `button`. But what if `button` specifies `react` in its `peerDependencies`? If all projects in the monorepo use the same version of `react`, then there is no problem. But what if `button` is required by `card` that uses `react@16` and `form` that uses `react@17`? Normally you'd have to choose a single version of `react` and specify it using `devDependencies` of `button`. Symlinking does not provide a way for the `react` peer dependency to be satisfied differently by different consumers such as `card` and `form`. The `injected` field solves this problem by installing a hard linked copies of `button` in the virtual store. To accomplish this, the `package.json` of `card` could be configured as follows: { "name": "card", "dependencies": { "button": "workspace:1.0.0", "react": "16" }, "dependenciesMeta": { "button": { "injected": true } }} Whereas the `package.json` of `form` could be configured as follows: { "name": "form", "dependencies": { "button": "workspace:1.0.0", "react": "17" }, "dependenciesMeta": { "button": { "injected": true } }} With these changes, we say that `button` is an "injected dependency" of `card` and `form`. When `button` imports `react`, it will resolve to `react@16` in the context of `card`, but resolve to `react@17` in the context of `form`. Because injected dependencies produce copies of their workspace source directory, these copies must be updated somehow whenever the code is modified; otherwise, the new state will not be reflected for consumers. When building multiple projects with a command such as `pnpm --recursive run build`, this update must occur after each injected package is rebuilt but before its consumers are rebuilt. For simple use cases, it can be accomplished by invoking `pnpm install` again, perhaps using a `package.json` lifecycle script such as `"prepare": "pnpm run build"` to rebuild that one project. Third party tools such as [pnpm-sync](https://www.npmjs.com/package/pnpm-sync-lib) and [pnpm-sync-dependencies-meta-injected](https://www.npmjs.com/package/pnpm-sync-dependencies-meta-injected) provide a more robust and efficient solution for updating injected dependencies, as well as watch mode support. peerDependenciesMeta[​](https://pnpm.io/9.x/package_json#peerdependenciesmeta "Direct link to peerDependenciesMeta") --------------------------------------------------------------------------------------------------------------------- This field lists some extra information related to the dependencies listed in the `peerDependencies` field. ### peerDependenciesMeta.\*.optional[​](https://pnpm.io/9.x/package_json#peerdependenciesmetaoptional "Direct link to peerDependenciesMeta.*.optional") If this is set to true, the selected peer dependency will be marked as optional by the package manager. Therefore, the consumer omitting it will no longer be reported as an error. For example: { "peerDependencies": { "foo": "1" }, "peerDependenciesMeta": { "foo": { "optional": true }, "bar": { "optional": true } }} Note that even though `bar` was not specified in `peerDependencies`, it is marked as optional. pnpm will therefore assume that any version of bar is fine. However, `foo` is optional, but only to the required version specification. publishConfig[​](https://pnpm.io/9.x/package_json#publishconfig "Direct link to publishConfig") ------------------------------------------------------------------------------------------------ It is possible to override some fields in the manifest before the package is packed. The following fields may be overridden: * [`bin`](https://github.com/stereobooster/package.json#bin) * [`main`](https://github.com/stereobooster/package.json#main) * [`exports`](https://nodejs.org/api/esm.html#esm_package_exports) * [`types` or `typings`](https://github.com/stereobooster/package.json#types) * [`module`](https://github.com/stereobooster/package.json#module) * [`browser`](https://github.com/stereobooster/package.json#browser) * [`esnext`](https://github.com/stereobooster/package.json#esnext) * [`es2015`](https://github.com/stereobooster/package.json#es2015) * [`unpkg`](https://github.com/stereobooster/package.json#unpkg-1) * [`umd:main`](https://github.com/stereobooster/package.json#microbundle) * [`typesVersions`](https://www.typescriptlang.org/docs/handbook/declaration-files/publishing.html#version-selection-with-typesversions) * cpu * os To override a field, add the publish version of the field to `publishConfig`. For instance, the following `package.json`: { "name": "foo", "version": "1.0.0", "main": "src/index.ts", "publishConfig": { "main": "lib/index.js", "typings": "lib/index.d.ts" }} Will be published as: { "name": "foo", "version": "1.0.0", "main": "lib/index.js", "typings": "lib/index.d.ts"} ### publishConfig.executableFiles[​](https://pnpm.io/9.x/package_json#publishconfigexecutablefiles "Direct link to publishConfig.executableFiles") By default, for portability reasons, no files except those listed in the bin field will be marked as executable in the resulting package archive. The `executableFiles` field lets you declare additional files that must have the executable flag (+x) set even if they aren't directly accessible through the bin field. { "publishConfig": { "executableFiles": [ "./dist/shim.js" ] }} ### publishConfig.directory[​](https://pnpm.io/9.x/package_json#publishconfigdirectory "Direct link to publishConfig.directory") You also can use the field `publishConfig.directory` to customize the published subdirectory relative to the current `package.json`. It is expected to have a modified version of the current package in the specified directory (usually using third party build tools). > In this example the `"dist"` folder must contain a `package.json` { "name": "foo", "version": "1.0.0", "publishConfig": { "directory": "dist" }} ### publishConfig.linkDirectory[​](https://pnpm.io/9.x/package_json#publishconfiglinkdirectory "Direct link to publishConfig.linkDirectory") * Default: **true** * Type: **Boolean** When set to `true`, the project will be symlinked from the `publishConfig.directory` location during local development. For example: { "name": "foo", "version": "1.0.0", "publishConfig": { "directory": "dist", "linkDirectory": true }} pnpm.overrides[​](https://pnpm.io/9.x/package_json#pnpmoverrides "Direct link to pnpm.overrides") -------------------------------------------------------------------------------------------------- This field allows you to instruct pnpm to override any dependency in the dependency graph. This is useful for enforcing all your packages to use a single version of a dependency, backporting a fix, replacing a dependency with a fork, or removing an unused dependency. Note that the overrides field can only be set at the root of the project. An example of the `"pnpm"."overrides"` field: { "pnpm": { "overrides": { "foo": "^1.0.0", "quux": "npm:@myorg/quux@^1.0.0", "bar@^2.1.0": "3.0.0", "qar@1>zoo": "2" } }} You may specify the package the overridden dependency belongs to by separating the package selector from the dependency selector with a ">", for example `qar@1>zoo` will only override the `zoo` dependency of `qar@1`, not for any other dependencies. An override may be defined as a reference to a direct dependency's spec. This is achieved by prefixing the name of the dependency with a `$`: { "dependencies": { "foo": "^1.0.0" }, "pnpm": { "overrides": { "foo": "$foo" } }} The referenced package does not need to match the overridden one: { "dependencies": { "foo": "^1.0.0" }, "pnpm": { "overrides": { "bar": "$foo" } }} Added in: v9.12.0 If you find that your use of a certain package doesn’t require one of its dependencies, you may use `-` to remove it. For example, if package `foo@1.0.0` requires a large package named `bar` for a function that you don’t use, removing it could reduce install time: { "pnpm": { "overrides": { "foo@1.0.0>bar": "-" } }} This feature is especially useful with `optionalDependencies`, where most optional packages can be safely skipped. pnpm.packageExtensions[​](https://pnpm.io/9.x/package_json#pnpmpackageextensions "Direct link to pnpm.packageExtensions") -------------------------------------------------------------------------------------------------------------------------- The `packageExtensions` fields offer a way to extend the existing package definitions with additional information. For example, if `react-redux` should have `react-dom` in its `peerDependencies` but it has not, it is possible to patch `react-redux` using `packageExtensions`: { "pnpm": { "packageExtensions": { "react-redux": { "peerDependencies": { "react-dom": "*" } } } }} The keys in `packageExtensions` are package names or package names and semver ranges, so it is possible to patch only some versions of a package: { "pnpm": { "packageExtensions": { "react-redux@1": { "peerDependencies": { "react-dom": "*" } } } }} The following fields may be extended using `packageExtensions`: `dependencies`, `optionalDependencies`, `peerDependencies`, and `peerDependenciesMeta`. A bigger example: { "pnpm": { "packageExtensions": { "express@1": { "optionalDependencies": { "typescript": "2" } }, "fork-ts-checker-webpack-plugin": { "dependencies": { "@babel/core": "1" }, "peerDependencies": { "eslint": ">= 6" }, "peerDependenciesMeta": { "eslint": { "optional": true } } } } }} tip Together with Yarn, we maintain a database of `packageExtensions` to patch broken packages in the ecosystem. If you use `packageExtensions`, consider sending a PR upstream and contributing your extension to the [`@yarnpkg/extensions`](https://github.com/yarnpkg/berry/blob/master/packages/yarnpkg-extensions/sources/index.ts) database. pnpm.peerDependencyRules[​](https://pnpm.io/9.x/package_json#pnpmpeerdependencyrules "Direct link to pnpm.peerDependencyRules") -------------------------------------------------------------------------------------------------------------------------------- ### pnpm.peerDependencyRules.ignoreMissing[​](https://pnpm.io/9.x/package_json#pnpmpeerdependencyrulesignoremissing "Direct link to pnpm.peerDependencyRules.ignoreMissing") pnpm will not print warnings about missing peer dependencies from this list. For instance, with the following configuration, pnpm will not print warnings if a dependency needs `react` but `react` is not installed: { "pnpm": { "peerDependencyRules": { "ignoreMissing": ["react"] } }} Package name patterns may also be used: { "pnpm": { "peerDependencyRules": { "ignoreMissing": ["@babel/*", "@eslint/*"] } }} ### pnpm.peerDependencyRules.allowedVersions[​](https://pnpm.io/9.x/package_json#pnpmpeerdependencyrulesallowedversions "Direct link to pnpm.peerDependencyRules.allowedVersions") Unmet peer dependency warnings will not be printed for peer dependencies of the specified range. For instance, if you have some dependencies that need `react@16` but you know that they work fine with `react@17`, then you may use the following configuration: { "pnpm": { "peerDependencyRules": { "allowedVersions": { "react": "17" } } }} This will tell pnpm that any dependency that has react in its peer dependencies should allow `react` v17 to be installed. It is also possible to suppress the warnings only for peer dependencies of specific packages. For instance, with the following configuration `react` v17 will be only allowed when it is in the peer dependencies of the `button` v2 package or in the dependencies of any `card` package: { "pnpm": { "peerDependencyRules": { "allowedVersions": { "button@2>react": "17", "card>react": "17" } } }} ### pnpm.peerDependencyRules.allowAny[​](https://pnpm.io/9.x/package_json#pnpmpeerdependencyrulesallowany "Direct link to pnpm.peerDependencyRules.allowAny") `allowAny` is an array of package name patterns, any peer dependency matching the pattern will be resolved from any version, regardless of the range specified in `peerDependencies`. For instance: { "pnpm": { "peerDependencyRules": { "allowAny": ["@babel/*", "eslint"] } }} The above setting will mute any warnings about peer dependency version mismatches related to `@babel/` packages or `eslint`. pnpm.neverBuiltDependencies[​](https://pnpm.io/9.x/package_json#pnpmneverbuiltdependencies "Direct link to pnpm.neverBuiltDependencies") ----------------------------------------------------------------------------------------------------------------------------------------- This field allows to ignore the builds of specific dependencies. The "preinstall", "install", and "postinstall" scripts of the listed packages will not be executed during installation. An example of the `"pnpm"."neverBuiltDependencies"` field: { "pnpm": { "neverBuiltDependencies": ["fsevents", "level"] }} pnpm.onlyBuiltDependencies[​](https://pnpm.io/9.x/package_json#pnpmonlybuiltdependencies "Direct link to pnpm.onlyBuiltDependencies") -------------------------------------------------------------------------------------------------------------------------------------- A list of package names that are allowed to be executed during installation. If this field exists, only the listed packages will be able to run install scripts. Example: { "pnpm": { "onlyBuiltDependencies": ["fsevents"] }} pnpm.onlyBuiltDependenciesFile[​](https://pnpm.io/9.x/package_json#pnpmonlybuiltdependenciesfile "Direct link to pnpm.onlyBuiltDependenciesFile") -------------------------------------------------------------------------------------------------------------------------------------------------- This configuration option allows users to specify a JSON file that lists the only packages permitted to run installation scripts during the pnpm install process. By using this, you can enhance security or ensure that only specific dependencies execute scripts during installation. Example: { "dependencies": { "@my-org/policy": "1.0.0" }, "pnpm": { "onlyBuiltDependenciesFile": "node_modules/@my-org/policy/onlyBuiltDependencies.json" }} The JSON file itself should contain an array of package names: node\_modules/@my-org/policy/onlyBuiltDependencies.json [ "fsevents"] pnpm.allowedDeprecatedVersions[​](https://pnpm.io/9.x/package_json#pnpmalloweddeprecatedversions "Direct link to pnpm.allowedDeprecatedVersions") -------------------------------------------------------------------------------------------------------------------------------------------------- This setting allows muting deprecation warnings of specific packages. Example: { "pnpm": { "allowedDeprecatedVersions": { "express": "1", "request": "*" } }} With the above configuration pnpm will not print deprecation warnings about any version of `request` and about v1 of `express`. pnpm.patchedDependencies[​](https://pnpm.io/9.x/package_json#pnpmpatcheddependencies "Direct link to pnpm.patchedDependencies") -------------------------------------------------------------------------------------------------------------------------------- This field is added/updated automatically when you run [pnpm patch-commit](https://pnpm.io/9.x/cli/patch-commit) . It is a dictionary where the key should be the package name and exact version. The value should be a relative path to a patch file. Example: { "pnpm": { "patchedDependencies": { "express@4.18.1": "patches/express@4.18.1.patch" } }} pnpm.allowNonAppliedPatches[​](https://pnpm.io/9.x/package_json#pnpmallownonappliedpatches "Direct link to pnpm.allowNonAppliedPatches") ----------------------------------------------------------------------------------------------------------------------------------------- When `true`, installation won't fail if some of the patches from the `patchedDependencies` field were not applied. { "pnpm": { "patchedDependencies": { "express@4.18.1": "patches/express@4.18.1.patch" }, "allowNonAppliedPatches": true} pnpm.updateConfig[​](https://pnpm.io/9.x/package_json#pnpmupdateconfig "Direct link to pnpm.updateConfig") ----------------------------------------------------------------------------------------------------------- ### pnpm.updateConfig.ignoreDependencies[​](https://pnpm.io/9.x/package_json#pnpmupdateconfigignoredependencies "Direct link to pnpm.updateConfig.ignoreDependencies") Sometimes you can't update a dependency. For instance, the latest version of the dependency started to use ESM but your project is not yet in ESM. Annoyingly, such a package will be always printed out by the `pnpm outdated` command and updated, when running `pnpm update --latest`. However, you may list packages that you don't want to upgrade in the `ignoreDependencies` field: { "pnpm": { "updateConfig": { "ignoreDependencies": ["load-json-file"] } }} Patterns are also supported, so you may ignore any packages from a scope: `@babel/*`. pnpm.auditConfig[​](https://pnpm.io/9.x/package_json#pnpmauditconfig "Direct link to pnpm.auditConfig") -------------------------------------------------------------------------------------------------------- ### pnpm.auditConfig.ignoreCves[​](https://pnpm.io/9.x/package_json#pnpmauditconfigignorecves "Direct link to pnpm.auditConfig.ignoreCves") A list of CVE IDs that will be ignored by the [`pnpm audit`](https://pnpm.io/9.x/cli/audit) command. { "pnpm": { "auditConfig": { "ignoreCves": [ "CVE-2022-36313" ] } }} ### pnpm.auditConfig.ignoreGhsas[​](https://pnpm.io/9.x/package_json#pnpmauditconfigignoreghsas "Direct link to pnpm.auditConfig.ignoreGhsas") Added in: v9.10.0 A list of GHSA Codes that will be ignored by the [`pnpm audit`](https://pnpm.io/9.x/cli/audit) command. { "pnpm": { "auditConfig": { "ignoreGhsas": [ "GHSA-42xw-2xvc-qx8m", "GHSA-4w2v-q235-vp99", "GHSA-cph5-m8f7-6c5x", "GHSA-vh95-rmgr-6w4m" ] } }} pnpm.requiredScripts[​](https://pnpm.io/9.x/package_json#pnpmrequiredscripts "Direct link to pnpm.requiredScripts") -------------------------------------------------------------------------------------------------------------------- Scripts listed in this array will be required in each project of the workspace. Otherwise, `pnpm -r run