SCAL-P supports npm and pnpm through an adapter interface that abstracts every package manager operation behind a common API. Both adapters implement the sameDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/CarlosEduJs/SCAL-P/llms.txt
Use this file to discover all available pages before exploring further.
PackageManager interface in internal/pkgmanager/pkgmanager.go, so every SCAL-P command — install, audit, CI, policy check — works identically regardless of which manager you use.
npm is the default. Switch to pnpm with the --pm flag.
Selecting a package manager
Use the--pm flag to choose between npm and pnpm. The flag applies to the current invocation only; it does not change the project default.
--pm is a per-subcommand flag. It can appear in any order relative to other named flags, but must come before any positional arguments (i.e., before the -- separator used to pass extra arguments to the package manager). For clarity, the convention used throughout the docs is to write --pm first.Command examples
- npm
- pnpm
npm is the default package manager. You do not need to pass npm resolves dependencies by running
--pm npm unless you want to be explicit.npm install --package-lock-only --ignore-scripts and reads package-lock.json (v2 or v3 format) for its lockfile. The dependency tree is produced with npm ls --all --json.Lockfile formats
Each adapter reads a different lockfile format. SCAL-P parses both into a common[]PackageNode flat list used by policy evaluation and hash verification.
| Package manager | Lockfile | Required version |
|---|---|---|
| npm | package-lock.json | v2 or v3 |
| pnpm | pnpm-lock.yaml | v5.4 through v9+ |
- npm lockfile
- pnpm lockfile
npm’s Lockfile v1 is not supported. Run
package-lock.json uses a packages map keyed by install path (e.g., node_modules/lodash). SCAL-P reads the version, resolved, and integrity fields from each entry and derives the depth from the nesting of node_modules segments in the key.package-lock.json (excerpt)
npm install with a modern npm to upgrade to v2 or v3.Adapter interface
Both adapters implement thePackageManager interface defined in internal/pkgmanager/pkgmanager.go. The interface is the single contract between SCAL-P’s command layer and any package manager backend.
internal/pkgmanager/pkgmanager.go
| Method | When it is called | npm implementation | pnpm implementation |
|---|---|---|---|
Name | Logging and error messages | Returns "npm" | Returns "pnpm" |
Resolve | Before policy evaluation — generates lockfile without installing | npm install --package-lock-only --ignore-scripts | pnpm install --lockfile-only |
GetTree | Dependency tree construction for trust scoring | npm ls --all --json | Parse pnpm-lock.yaml (fallback: pnpm ls --json --depth Infinity) |
Install | After policy passes, runs actual install | npm install [args] | pnpm install [args] |
ParseLockfile | Hash sync and flat node list for policy evaluation | Reads package-lock.json | Reads pnpm-lock.yaml |
LocalPath | Resolves on-disk path for a package name | node_modules/<name> | node_modules/<name> |
Registry and adapter registration
SCAL-P uses a thread-safe registry ininternal/pkgmanager/registry.go to map adapter names to constructor functions.
internal/pkgmanager/registry.go
pkgmanager.Register from its own Register() function:
internal/npm/npm.go
internal/pnpm/adapter.go
Adding a custom package manager
To add support for a new package manager, implement thePackageManager interface and register it before SCAL-P’s CLI router runs.
Create your adapter package
Add a new package under
internal/ (e.g., internal/yarn/) with a struct that implements all six interface methods.internal/yarn/adapter.go
Add a Register function
Add a
Register() function that calls pkgmanager.Register with your adapter’s name and constructor:internal/yarn/adapter.go
Call Register from main
Import your package and call its
Register() function before cli.Run() in cmd/scalp/main.go:cmd/scalp/main.go