pnpm Package Manager

pnpm cheatsheet — fast, disk-efficient Node.js package management. pnpm install, pnpm add, pnpm dlx, pnpm workspace. 3x faster than npm with hard-linked node_modules.

6 min read

What it is

A fast, disk-space-efficient package manager for Node.js, prioritizing speed and efficient dependency management.

Installation

Linux/macOS:

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

Windows (using npm):

npm install -g pnpm

Windows (using PowerShell):

iwr https://get.pnpm.io/install.ps1 -UseBasicParsing | Select-String -Pattern 'Invoke-Expression' | ForEach-Object { $_.Line } | Invoke-Expression

Core Concepts

  • Symlinked node_modules: pnpm uses a global, content-addressable store (~/.pnpm-store) for all packages. In your project, node_modules is populated with symlinks to these globally stored packages. This avoids duplicated packages across projects and saves disk space.
  • Non-flat node_modules: Unlike npm or yarn, pnpm creates a node_modules structure that mirrors your package.json dependencies, rather than flattening everything. This strictly enforces dependency rules, preventing accidental usage of undeclared dependencies.
  • Workspaces: pnpm has robust support for monorepos, allowing you to manage multiple related packages within a single repository.

Commands / Usage

Project Initialization & Setup

  • Initialize a new project:

    pnpm init
    

    Creates a package.json file for a new Node.js project.

  • Initialize a new project with a template:

    pnpm init typescript
    

    Initializes a project with a specific template (e.g., TypeScript).

Package Management

  • Add a dependency:

    pnpm add react
    

    Installs the react package and adds it to dependencies in package.json.

  • Add a dev dependency:

    pnpm add -D jest
    

    Installs the jest package and adds it to devDependencies in package.json.

  • Add a peer dependency:

    pnpm add -P eslint
    

    Installs the eslint package and adds it to peerDependencies in package.json.

  • Add a global dependency:

    pnpm add -g http-server
    

    Installs the http-server package globally, making it available as a command-line tool.

  • Install all dependencies from package.json:

    pnpm install
    

    Installs all dependencies listed in package.json and pnpm-lock.yaml.

  • Install specific dependencies:

    pnpm install lodash express
    

    Installs lodash and express and adds them to dependencies.

  • Install dependencies for production:

    pnpm install --prod
    

    Installs only production dependencies (skips devDependencies).

  • Install dependencies with a specific lockfile:

    pnpm install --frozen-lockfile
    

    Installs dependencies based strictly on the pnpm-lock.yaml, failing if package.json differs.

  • Remove a dependency:

    pnpm remove react
    

    Uninstalls the react package and removes it from package.json.

  • Remove a dev dependency:

    pnpm remove -D jest
    

    Uninstalls the jest package and removes it from devDependencies.

  • Update dependencies:

    pnpm update
    

    Updates all dependencies to their latest versions according to package.json and pnpm-lock.yaml.

  • Update a specific dependency:

    pnpm update react
    

    Updates the react package to its latest allowed version.

  • Update to a specific version:

    pnpm update react@^18.0.0
    

    Updates react to the latest version compatible with ^18.0.0.

  • List installed packages:

    pnpm list
    

    Lists all installed packages and their versions.

  • List dependencies of a specific package:

    pnpm list --depth=0
    

    Lists only the top-level dependencies.

  • Run a script defined in package.json:

    pnpm run build
    

    Executes the build script from your package.json.

  • Run a script with arguments:

    pnpm run test -- --watch
    

    Executes the test script and passes --watch as an argument to it.

  • Execute a package binary:

    pnpm exec eslint .
    

    Runs the eslint command from the installed packages.

Workspaces (Monorepos)

  • Install dependencies for all workspace packages:

    pnpm install
    

    Runs pnpm install at the root of a workspace.

  • Add a dependency to a specific workspace package:

    pnpm add lodash -C packages/backend
    

    Adds lodash to the packages/backend workspace package.

  • Run a script in all workspace packages:

    pnpm run build --filter ./packages/*
    

    Runs the build script in all packages under packages/.

  • Run a script in a specific workspace package:

    pnpm run test --filter @my-org/frontend
    

    Runs the test script in the @my-org/frontend package.

  • Run a script in packages that depend on another package:

    pnpm run build --filter @my-org/shared-ui...
    

    Runs build in packages that are direct or indirect dependents of @my-org/shared-ui.

  • Run a script in packages that a package depends on:

    pnpm run lint --filter ...@my-org/shared-ui
    

    Runs lint in packages that @my-org/shared-ui directly or indirectly depends on.

Configuration & Management

  • View pnpm configuration:

    pnpm config list
    

    Displays the current pnpm configuration values.

  • Set pnpm configuration:

    pnpm config set store-dir ~/.my-pnpm-store
    

    Sets the global store directory.

  • Remove the global store:

    pnpm store prune
    

    Removes unused packages from the global store.

  • Get the path to the pnpm store:

    pnpm store path
    

    Prints the absolute path to the global pnpm store.

Common Patterns

  • Clean install (remove node_modules and reinstall):

    rm -rf node_modules && pnpm install
    

    Ensures a fresh installation by removing the existing node_modules directory.

  • Install with specific Node.js version (using npx or volta):

    # Using npx (requires Node.js to be installed)
    npx pnpm install
    
    # Using volta (if installed)
    volta run pnpm install
    

    Ensures that the installation happens with a specific Node.js version managed by npx or volta.

  • Running a script and ignoring potential errors (for CI):

    pnpm install --ignore-scripts
    

    Installs dependencies without executing any lifecycle scripts.

  • Build a project for production:

    pnpm install --prod && pnpm run build
    

    Installs only production dependencies and then builds the project.

  • Updating dependencies and committing changes:

    pnpm update && git add pnpm-lock.yaml package.json && git commit -m "chore: update dependencies"
    

    A common workflow for updating all dependencies and committing the lockfile.

  • Checking for outdated packages:

    pnpm outdated
    

    Lists packages that have newer versions available than what’s currently installed.

Gotchas

  • Global package conflicts: While pnpm add -g is convenient, managing global packages can lead to conflicts if different projects require different versions of the same global tool. Consider using npx or pnpm exec for project-specific tool execution.
  • Symlink issues in some environments: In rare cases, particularly with older Windows versions or specific IDE configurations, symlinks might behave unexpectedly. pnpm’s strict dependency structure can sometimes expose these underlying OS behaviors.
  • pnpm-lock.yaml vs package-lock.json / yarn.lock: pnpm uses its own lockfile format. Do not mix or attempt to convert lockfiles from other package managers; use pnpm install to generate pnpm-lock.yaml.
  • Workspace filtering complexity: The --filter syntax can be powerful but also complex. Understanding the nuances of package names, paths, and the ... operator is key for effective monorepo management.
  • --frozen-lockfile behavior: This flag is crucial for CI/CD pipelines to ensure reproducible builds. If package.json has changed since the lockfile was last updated, pnpm install --frozen-lockfile will error out, which is the desired behavior to catch inconsistencies.