Basic Usage
The day-to-day snpm workflow
snpm is shaped like pnpm with familiar npm-style ergonomics. The same package.json works as-is.
Install dependencies
snpm installReads package.json, resolves the dependency graph, materializes packages into the shared store, and links them into node_modules/.snpm plus the root node_modules tree.
Useful flags:
--production— skipdevDependencies.--frozen-lockfile(alias--immutable) — fail if the lockfile is missing or out of date.--no-frozen-lockfile— ignore the lockfile and re-resolve.--prefer-frozen-lockfile— reuse the lockfile when valid, otherwise re-resolve.--fix-lockfile— re-resolve drifted entries while preserving the rest.-f, --force— ignore cached state and force a full install.-w, --workspace <name>— target a single workspace project from the workspace root.
snpm install --production --frozen-lockfile # CI / production
snpm install --fix-lockfile # repair lockfile drift
snpm install -w @acme/api # workspace-scoped installThe --frozen-lockfile, --no-frozen-lockfile, and --prefer-frozen-lockfile flags can also be set globally before the subcommand (snpm --frozen-lockfile install) and they propagate to any install-like command (add, remove, upgrade, run, exec).
Add and remove
snpm add react # latest matching version
snpm add react@18.2.0 # exact version
snpm add -D typescript # devDependency
snpm add react react-dom # multiple packages
snpm remove react
snpm remove -g create-react-appadd and remove accept the same workspace selectors as the rest of the CLI: -w <name>, -r/--recursive, --filter <selector>, and --filter-prod <selector>.
Run scripts
snpm run build # one-off
snpm run test -- --watch # pass args after --
snpm build # script-name fallback (unknown subcommands)Scripts auto-trigger a lazy install if package.json or snpm-lock.yaml has drifted from node_modules. Pass --skip-install to bypass that check.
Workspace selectors:
snpm run build -r # every project
snpm run test --filter "@acme/*" # name glob
snpm run test --filter ./packages/api # path
snpm run test --filter api... # api and its dependencies
snpm run test --filter ...api # api and its dependents
snpm run test --filter "[origin/main]" # projects changed since origin/main
snpm run test --filter "!@acme/docs" # exclude a project--filter-prod accepts the same selector grammar but restricts dependency/dependent walks to production dependencies only.
Execute binaries
snpm exec eslint . # run a binary from node_modules/.bin
snpm exec -c "eslint . | head" # shell mode for pipes/redirects
snpm exec --recursive tsc --buildOne-off packages
snpm dlx cowsay "moo" # download, run, discard
snpm dlx create-vite my-app -- --template react-ts
snpm dlx --offline tsc --version # fail if not cached
spx cowsay "moo" # multicall alias for snpm dlxsnpx and pnpx are also recognized as aliases for snpm dlx, and snpr is an alias for snpm run.
Lifecycle scripts
snpm supports the standard lifecycle stages for the root project (and workspace members), running them in order during install:
preinstallinstallpostinstallprepare(after install and before publish)
{
"scripts": {
"preinstall": "node scripts/check-env.js",
"install": "node-gyp rebuild",
"postinstall": "node scripts/postinstall.js",
"prepare": "npm run build"
}
}Dependency lifecycle scripts are blocked by default. To allow specific dependencies to run preinstall/install/postinstall, list them in SNPM_ALLOW_SCRIPTS=name1,name2 or the workspace onlyBuiltDependencies array. After changing the allow-list, run snpm rebuild to apply it to packages that already extracted.
Upgrade and outdated
snpm upgrade # delete the lockfile and re-resolve to latest in range
snpm upgrade react react-dom
snpm upgrade --production
snpm upgrade -r --filter "@acme/*"
snpm outdated # show pending updates
snpm outdated -r # across all workspace projectsInspection
snpm list # show project dependencies
snpm list -g # show global installs
snpm licenses # license per installed package
snpm licenses --json
snpm why typescript # show dependency paths into typescript
snpm why "babel-*" --json # glob support
snpm store status # store size / package countPerformance
Hot install — when package.json and snpm-lock.yaml agree with node_modules/.snpm-integrity, install finishes in tens of milliseconds.
Warm install — when the lockfile is valid and all tarballs are in the shared store, links and integrity markers refresh in a few seconds.
Cold install — fetches go in parallel (default concurrency 128, tunable with SNPM_REGISTRY_CONCURRENCY).
Where things live
| Path | Purpose |
|---|---|
<data_dir>/packages/<name>/<version>/ | Shared package store |
<data_dir>/virtual-store/ | Shared .snpm entries pooled across projects |
<data_dir>/global/ | Global installs (snpm add -g) |
<data_dir>/bin/ | Global bin shims |
<cache_dir>/metadata/ | Registry metadata cache |
node_modules/.snpm/ | Project virtual store |
node_modules/.snpm-integrity | Lockfile-derived hash for fast install detection |
On macOS, cache_dir and data_dir are platform-default (~/Library/Caches/snpm, ~/Library/Application Support/io.snpm.snpm). Override with SNPM_HOME=/path/to/snpm to get cache=$SNPM_HOME/cache, data=$SNPM_HOME/data.