pnpm Command: Install and Manage Node.js Packages

By 

Updated on

9 min read

Managing Node.js packages with pnpm commands in a terminal

Large Node.js projects can consume a surprising amount of disk space when every project keeps its own copies of the same packages. pnpm addresses this by storing package files in a shared content-addressable store and linking them into each project. It uses the npm registry and works with the same package.json files while providing stricter dependency handling and built-in workspace support.

This guide explains how to install pnpm on Linux, macOS, and Windows, then use it to create projects, install a Node.js runtime, add and update packages, run scripts, migrate from npm, and work across a monorepo.

Syntax

The general form of the command is:

txt
pnpm <command> [options]

Most pnpm commands have direct npm equivalents. For example, pnpm install installs project dependencies, pnpm add records a new dependency, and pnpm run executes a script from package.json.

How pnpm Stores Packages

pnpm keeps package files in a shared store on your machine. Projects link to those files instead of copying the same package contents into every node_modules directory. If ten projects use the same package version, pnpm stores its files once.

The resulting node_modules layout also prevents packages from importing dependencies they did not declare. This stricter behavior helps expose missing dependency declarations that npm’s flat dependency layout can sometimes hide.

You still commit package.json and the pnpm-lock.yaml lockfile to version control. The shared store and generated node_modules directory should not be committed.

Install pnpm

pnpm 12 is a native executable. After it is installed it runs without Node.js, so you can set up pnpm on a machine that has no Node.js yet and add a runtime afterwards. The npm method is the exception, and it needs Node.js 22.13 or newer to run the installer.

Install the Standalone Version

The standalone installer downloads the pnpm binary for your platform and does not require Node.js to be present. On Linux, macOS, and other POSIX systems, run:

Terminal
curl -fsSL https://get.pnpm.io/install.sh | sh -

If curl is not installed, wget works the same way:

Terminal
wget -qO- https://get.pnpm.io/install.sh | sh -
Warning
Piping a remote script into a shell runs code from the network as your user. Review the script before running it on a production system, or download it first and inspect the local file.

To install a particular release, set the PNPM_VERSION variable for the script:

Terminal
curl -fsSL https://get.pnpm.io/install.sh | env PNPM_VERSION=12.3.4 sh -

On Windows PowerShell, use:

powershell
Invoke-WebRequest https://get.pnpm.io/install.ps1 -UseBasicParsing | Invoke-Expression

Microsoft Defender sometimes blocks the pnpm executable installed this way. On Windows, the npm method below is the safer choice.

Install with npm

If you already have Node.js 22.13 or newer, run the npm installer:

Terminal
npx get-pnpm

Node.js is needed to run the installer, but not to run pnpm afterwards. If your Node.js release is older, follow our guide to install Node.js and npm on Ubuntu 26.04 , or let pnpm install the runtime for you as described in the next section.

Update an Existing Installation

From pnpm v11.10.0 onward, you can move to the current release in place:

Terminal
pnpm self-update

Open a new terminal after the installer finishes, then verify the command:

Terminal
pnpm --version
output
12.3.4

Pin pnpm for a Project

Recording a pnpm version in package.json keeps contributors and CI jobs on the same release. Add the field when you create the project:

Terminal
pnpm init --init-package-manager

This writes a packageManager entry with an exact pnpm version. In a project that already has one, pnpm self-update updates that entry and leaves your global install alone, and pnpm switches to the recorded release on the next command.

Corepack can also pin a package manager version, and it still works. It installs a JavaScript shim in place of pnpm, so every pnpm call starts Node.js before pnpm itself runs. The pnpm documentation now recommends installing pnpm directly.

Installing Node.js with pnpm

pnpm can install and manage the Node.js runtime itself. This is handy on a machine that got pnpm from the standalone script and has no Node.js at all.

Install the current LTS release and put it on your PATH with -g:

Terminal
pnpm runtime set node lts -g

You can also name a major version or ask for the newest release:

Terminal
pnpm runtime set node 22 -g
pnpm runtime set node latest -g

Check the result the usual way:

Terminal
node --version
output
v24.21.0

The same command installs other runtimes, for example pnpm runtime set deno 2 -g or pnpm runtime set bun latest -g.

Note
Older releases used pnpm env use --global lts for this. pnpm env is deprecated. Use pnpm runtime set node lts -g instead.

Initialize a Project

Create a directory and initialize a package.json file:

Terminal
mkdir example-app
cd example-app
pnpm init

pnpm writes a package.json with the default fields and does not ask any questions. Add --init-package-manager when you also want the project pinned to the pnpm version you are running. If you already have a project created with npm, pnpm can use its existing package.json without any conversion.

Install Packages

Add a runtime dependency with pnpm add:

Terminal
pnpm add express

pnpm installs the package, records it under dependencies in package.json, and creates or updates pnpm-lock.yaml.

Add development tools with -D (short for --save-dev):

Terminal
pnpm add -D eslint

To install a specific package version, append it after @:

Terminal
pnpm add express@5.1.0

When you clone an existing pnpm project, install everything declared in its package files with:

Terminal
pnpm install

For CI or another reproducible environment, prevent changes to the lockfile:

Terminal
pnpm install --frozen-lockfile

The command fails when package.json and pnpm-lock.yaml do not agree instead of resolving a new dependency tree. pnpm turns this mode on by itself once it detects a CI environment, so the flag mainly matters when you want the same behavior locally.

Install Global Packages

Install a command-line tool globally with -g:

Terminal
pnpm add -g http-server

If pnpm reports that it cannot find a global binary directory, run:

Terminal
pnpm setup

Open a new terminal so the updated PATH takes effect, then repeat the global install. Keep application dependencies local to each project and reserve global installs for commands you need across projects.

Update and Inspect Packages

Check which dependencies have newer versions available:

Terminal
pnpm outdated

Update dependencies within the version ranges in package.json:

Terminal
pnpm update

To update one package to its latest published release and change its declared range, run:

Terminal
pnpm update express --latest

List the direct dependencies in the current project with:

Terminal
pnpm list --depth 0

When you need to understand why a package is present, use:

Terminal
pnpm why express

Remove Packages

Remove a dependency from node_modules, package.json, and the lockfile with:

Terminal
pnpm remove express

For a globally installed package, add -g:

Terminal
pnpm remove -g http-server

Run Scripts and Package Binaries

pnpm reads the scripts section of package.json just like npm. Given this file:

package.jsonjson
{
  "scripts": {
    "start": "node index.js",
    "lint": "eslint ."
  }
}

Run a named script with:

Terminal
pnpm run lint

You can omit run when the script name does not conflict with a pnpm command:

Terminal
pnpm start

Use pnpm exec to run a binary installed in the current project:

Terminal
pnpm exec eslint .

For a one-off package that you do not want to add as a dependency, use pnpm dlx:

Terminal
pnpm dlx create-vite@latest my-app

pnpm exec runs an existing local dependency, while pnpm dlx fetches a package temporarily and runs its command.

Migrate a Project from npm

From a project containing package-lock.json, generate a pnpm lockfile with:

Terminal
pnpm import

The command reads the npm lockfile and creates pnpm-lock.yaml. Install the imported dependency tree next:

Terminal
pnpm install

Run the project’s tests and build before removing package-lock.json. Commit pnpm-lock.yaml, and update CI commands from npm ci to pnpm install --frozen-lockfile.

If the repository records its package manager in a packageManager field, update that pin with:

Terminal
pnpm self-update

Use pnpm Workspaces

A pnpm workspace groups multiple packages in one repository. Define its package locations in pnpm-workspace.yaml at the repository root:

pnpm-workspace.yamlyaml
packages:
  - "apps/*"
  - "packages/*"

Install dependencies for every workspace package from the root:

Terminal
pnpm install

Run a script recursively across all packages that define it:

Terminal
pnpm --recursive run build

Use --filter when a command should target one package:

Terminal
pnpm --filter web-app add zod
pnpm --filter web-app run test

Filters can select packages by name, directory, dependency relationship, or changed files, which makes them useful in larger monorepos and CI jobs.

Quick Reference

For a printable quick reference, see the pnpm cheatsheet .

TaskCommand
Check pnpm versionpnpm --version
Update pnpm itselfpnpm self-update
Install a Node.js runtimepnpm runtime set node lts -g
Initialize a projectpnpm init
Initialize and pin pnpmpnpm init --init-package-manager
Install project dependenciespnpm install
Install from an unchanged lockfilepnpm install --frozen-lockfile
Add a dependencypnpm add <pkg>
Add a development dependencypnpm add -D <pkg>
Add a global packagepnpm add -g <pkg>
Show outdated packagespnpm outdated
Update packagespnpm update
Update one package to latestpnpm update <pkg> --latest
Remove a packagepnpm remove <pkg>
Run a scriptpnpm run <script>
Run a local package binarypnpm exec <command>
Run a package temporarilypnpm dlx <pkg>
List direct dependenciespnpm list --depth 0
Explain an installed packagepnpm why <pkg>
Import an npm lockfilepnpm import
Run a command in all workspacespnpm --recursive <command>
Target one workspace packagepnpm --filter <name> <command>

Troubleshooting

pnpm: command not found after installation
Open a new terminal so your shell reloads the PATH changes made by the installer. If pnpm is still unavailable, check your shell configuration for the PNPM_HOME entry and reload the appropriate file, such as source ~/.bashrc or source ~/.zshrc. Run the standalone installer again if the entry is missing.

ERR_PNPM_UNSUPPORTED_ENGINE
One of the project packages requires a Node.js version you do not have. Install a matching runtime with pnpm runtime set node <version> -g. The same error can come from the npm installer itself, which needs Node.js 22.13 or newer; the standalone installer has no such requirement.

A package import worked with npm but fails with pnpm
The code may rely on a transitive dependency that is not declared in its own package.json. Add the missing package as a direct dependency instead of relying on npm’s flatter node_modules layout.

The lockfile was created by a newer version of pnpm
Since pnpm 11, an install in CI fails on a pnpm-lock.yaml written by a newer pnpm major version instead of quietly rewriting it. Match the pnpm version in CI to the one you use locally, most reliably by pinning it with a packageManager field.

ERR_PNPM_OUTDATED_LOCKFILE in CI
The committed pnpm-lock.yaml does not match package.json. Run pnpm install locally, review and commit the updated lockfile, then rerun pnpm install --frozen-lockfile in CI.

Conclusion

pnpm uses the familiar npm package ecosystem while reducing duplicate package storage and enforcing clearer dependency declarations. If you are comparing workflows, see the npm command guide for the equivalent npm commands and lockfile behavior.

Linuxize Weekly Newsletter

A quick weekly roundup of new tutorials, news, and tips.

About the authors

Dejan Panovski

Dejan Panovski

Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 1000+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.

View author page