Introduction
A Rust-native package manager for JavaScript workspaces
snpm is a Rust-native package manager for Node.js projects, shaped around pnpm-style workflows: a shared package store, a node_modules/.snpm virtual store, workspace-aware installs, and a lockfile-first install path.
The core install, workspace, registry, cache, script-policy, and package workflow surfaces are in place. snpm reads pnpm/Bun/Yarn/npm lockfiles when its own is missing, then continues with snpm-lock.yaml as the source of truth.
What you get
- Drop-in workflow —
snpm install,snpm add,snpm run,snpm exec,snpm dlx, plus a script-name fallback (snpm buildrunsbuild). - Shared package store with hardlinks/symlinks/copies, and a project-local
node_modules/.snpmvirtual store keyed by version + dependency closure. - Workspaces discovered from
snpm-workspace.yaml,pnpm-workspace.yaml, orpackage.jsonworkspaces, with rich--filter/--filter-prodselectors (name, glob, path,pkg...,...pkg,[git-ref],!exclude). - Catalogs and overrides through
snpm-catalog.yaml,snpm-overrides.yaml, andpackage.jsonsnpm/pnpmblocks. - Lockfile imports —
pnpm-lock.yaml,bun.lock,yarn.lock,npm-shrinkwrap.json, andpackage-lock.jsonseed the first install ifsnpm-lock.yamlis missing. - Registry auth with Bearer/Basic schemes, scoped registries, and
.snpmrc/.npmrc/.pnpmrcparsing. - Security defaults — dependency lifecycle scripts blocked unless explicitly allowed,
SNPM_MIN_PACKAGE_AGE_DAYSto skip recent publishes, tarball auth scoped to the announcing registry origin. - First-party publishing —
pack,publish,pack --dry-run, distribution tags, OTP support. - Inspection —
audit(table/json/SARIF,--fix),why,licenses,store status,outdated,list. - Local development —
link,unlink,patch edit/commit/remove/list,rebuild. - Node version manager —
snpm node install,node use,.node-version/.nvmrc/engines.nodediscovery, shell hooks.
Quick start
# Install snpm
npm install -g snpm
# Work in a project
snpm install
snpm add react
snpm add -D typescript
snpm remove left-pad
snpm run build
snpm exec eslint .
snpm dlx cowsay "hello"In a workspace:
snpm install
snpm install -w @acme/api
snpm run build -r
snpm run test --filter "@acme/*"
snpm run test --filter api...
snpm add -r -D vitestIn CI:
snpm install --frozen-lockfile
snpm install --production --frozen-lockfile
SNPM_MIN_PACKAGE_AGE_DAYS=7 snpm install --frozen-lockfileHow it works
Shared store — Packages are downloaded once into <data_dir>/packages/<name>/<version>/ and linked into each project's node_modules/.snpm virtual store. The default linker is auto (hardlinks on Unix, copies on Windows), with hardlink, symlink, and copy backends available.
Virtual store — Each project gets a node_modules/.snpm directory keyed by package version and resolved dependency closure. Shared entries are pooled across projects when safe; patched, script-enabled, directory-backed file:, and resolver-walk-up-sensitive packages stay project-local automatically.
Lockfile — snpm-lock.yaml (schema version 1) is the source of truth. Installs validate cached state against a lockfile-derived hash stored in node_modules/.snpm-integrity; if it matches, install completes in milliseconds.
Script policy — Dependency lifecycle scripts are blocked by default. Root project scripts (preinstall, install, postinstall, prepare) still run during install. Allow specific dependency packages via SNPM_ALLOW_SCRIPTS=... or workspace onlyBuiltDependencies.
Registry compatibility — npm, jsr, file:, git:, workspace:, and catalog: protocols are supported. Auth is read from .snpmrc / .npmrc / .pnpmrc, environment variables, and the credentials saved by snpm login.