pnpm dlx: run a package without installing it (the pnpm npx)
- tool
- pnpm
- versions
- pnpm 6.13+, pnpm 9
- os
- any
pnpm dlx cowsay hello downloads a package into a temporary location, runs its binary with the arguments you give, and leaves your project untouched: nothing is added to package.json, node_modules or pnpm-lock.yaml. It is the pnpm counterpart of npx and yarn dlx, used for one-off tools and project generators. Pin the version (cowsay@1.6.0) to get the same tool every time.
Run a package once
P="npx --yes pnpm@9"
$P --reporter=silent dlx cowsay@1.6.0 "hello from dlx"
for f in package.json node_modules pnpm-lock.yaml; do [ -e "$f" ] && echo "$f: created" || echo "$f: not created"; doneOutput
________________
< hello from dlx >
----------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
package.json: not created
node_modules: not created
pnpm-lock.yaml: not created--reporter=silent hides pnpm's download progress; the tool's own output is still printed. No package.json, node_modules or lockfile was created in the folder. The example starts pnpm itself through npx pnpm@9; with pnpm installed, the command is pnpm dlx cowsay@1.6.0 "hello from dlx".
Variants
| Command | What it does |
|---|---|
| pnpm dlx create-vite my-app | Run a project generator |
| pnpm create vite my-app | Shortcut for pnpm dlx create-vite |
| pnpm dlx prettier@3.3.3 --check . | Pin a version for reproducible results |
| pnpm --package=typescript dlx tsc --version | The binary name differs from the package name |
| pnpm --package=yo --package=generator-webapp dlx yo webapp | Several packages available to one command |
| pnpm --package=cowsay -c dlx "echo hi | cowsay" | Run a shell command with the packages on PATH (-c, --shell-mode) |
| pnpm exec eslint . | Run a binary already installed in the project |
How it picks the binary
When a package has a single binary, dlx runs it. When the package name and the binary name differ, as with typescript (binary tsc), name the package with --package and the binary as the command. Packages with several binaries need the binary named explicitly.
Pitfalls
- Unpinned versions change.
pnpm dlx toolresolves the latest version at the time it runs (subject to the dlx cache), so results can change between days. Pin versions in scripts and CI. - Typos run what exists. A misspelt package that happens to exist on the registry is downloaded and run. Check the name, and prefer scoped, well-known packages; a name that does not exist fails with a 404 like npm E404.
- It is not a dependency. Tools your project needs every day belong in
devDependencies(pnpm add -D tool) and are run withpnpm execor a script, so everybody uses the same version. - Lifecycle scripts. Packages that need a
postinstallstep to work (native binaries) may need--allow-build=pkgin pnpm 10, which does not run dependency build scripts by default.
How to confirm it worked
The tool's own output is the confirmation, and git status shows no new files in your project apart from what the tool itself creates (for a generator, the new project folder). pnpm dlx tool --version prints the version that was actually downloaded.
FAQ
What is the difference between pnpm dlx and pnpm exec?
pnpm dlx downloads the package into a temporary location and runs it, without touching your project. pnpm exec runs a binary that is already installed in the project's node_modules/.bin.
Does pnpm dlx cache packages?
Yes. Recent pnpm versions keep the temporary install in a dlx cache for a while, controlled by the dlx-cache-max-age setting, so a second run of the same package and version starts quickly.
How do I run create-vite or create-next-app with pnpm?
Use pnpm create vite or pnpm create next-app. pnpm create foo is a shortcut for pnpm dlx create-foo, so both forms run the same scaffolding package.