Quick Start
# Install vlt globally$ npm install -g vlt
# In your existing project, run:
$ vlt install $ vlt buildThat’s it for basic usage. vlt reads your existing package.json and
resolves dependencies. Below are the details on what’s different and
how to handle specific scenarios.
Command Mapping
| npm | vlt | Notes |
|---|---|---|
npm install | vlt install | Does not run lifecycle scripts |
npm install <pkg> | vlt install <pkg> | Same behavior |
npm install -D <pkg> | vlt install -D <pkg> | Same flags |
npm uninstall <pkg> | vlt uninstall <pkg> | Aliases: rm, u |
npm run <script> | vlt run <script> | Aliases: r, run-script |
npm test | vlt run test | No vlt test shorthand |
npm start | vlt run start | No vlt start shorthand |
npx <pkg> | vlx <pkg> | Run remote packages |
npm exec <cmd> | vlt exec <cmd> | Local bins on PATH |
npm init | vlt init | Creates package.json |
npm pack | vlt pack | |
npm publish | vlt publish | |
npm login | vlt login | |
npm whoami | vlt whoami | |
npm ls | vlt list | Alias: ls |
npm query | vlt query | Uses DSS, not CSS selectors |
npm ci | vlt install --expect-lockfile | Strict lockfile mode |
npm install --ignore-scripts | vlt install | Default behavior |
npm audit | vlt query ':malware' | More powerful; see Security |
npm config set <key>=<val> | vlt config set <key>=<val> | Writes to vlt.json |
npm overrides | Graph Modifiers | DSS-based, more precise |
Configuration
.npmrc → vlt.json
npm reads configuration from .npmrc files (INI format, multiple
locations). vlt uses a single vlt.json file in your project root,
plus an optional user-level vlt.json in the XDG config directory.
# .npmrc (npm)registry=https://registry.internal.company.com/@mycompany:registry=https://npm.mycompany.com/save-exact=true{ "registry": "https://registry.internal.company.com/", "scope-registries": { "@mycompany": "https://npm.mycompany.com/" }}To create this file interactively:
$ vlt config set registry=https://registry.internal.company.com/$ vlt config set scope-registries=@mycompany=https://npm.mycompany.com/User vs Project Config
| npm | vlt |
|---|---|
~/.npmrc (user) | XDG config dir vlt/vlt.json |
.npmrc (project) | vlt.json (project root) |
$PREFIX/etc/npmrc (global) | No global config file |
View config locations:
$ vlt config location --config=user$ vlt config location --config=projectRegistry Configuration
vlt handles registries similarly to npm, with some additions.
Scoped Registries
npm’s scoped registries map directly:
# npm (.npmrc)@mycompany:registry=https://npm.mycompany.com/{ "scope-registries": { "@mycompany": "https://npm.mycompany.com/" }}Named Registry Aliases
vlt also supports named registry aliases, which are more explicit than scope-based mapping. This is a vlt-specific feature:
{ "registries": { "internal": "https://npm.mycompany.com/" }}Then reference packages explicitly:
$ vlt install internal:@mycompany/utils@^2.0Authentication
Tokens
npm stores auth tokens in .npmrc. vlt stores them in an
XDG-compliant keychain file, which is less likely to be accidentally
committed to source control.
# npm: tokens live in .npmrc (risky if committed)//registry.npmjs.org/:_authToken=npm_abc123
# vlt: log in interactively
$ vlt login
# vlt: or for custom registries
$ vlt login --registry=https://npm.mycompany.com/CI Environments
# npmNPM_TOKEN=abc123 npm install
# vlt
VLT_TOKEN=abc123 vlt installFor non-default registries, replace non-alphanumeric characters in the
URL with _:
VLT_TOKEN_https_npm_mycompany_com=abc123 vlt installSee Authentication for full details.
Lockfile
npm uses package-lock.json. vlt uses vlt-lock.json.
When you first run vlt install, vlt resolves from your
package.json and creates vlt-lock.json. Your existing
package-lock.json is not read or migrated — vlt performs a fresh
resolution.
What to do:
- Run
vlt installto generatevlt-lock.json - Commit
vlt-lock.jsonto source control - Optionally remove
package-lock.json(or keep it if you’re running both tools during a transition period)
CI / Frozen Lockfile
# npm$ npm ci
# vlt
$ vlt install --expect-lockfileInstall Script Protection
This is the biggest behavioral difference from npm.
npm runs all lifecycle scripts (preinstall, install,
postinstall) automatically during npm install. This is a known
supply chain attack vector.
vlt separates installation into two phases:
vlt install— Downloads and extracts packages. No scripts run.vlt build— Runs lifecycle scripts selectively.
# Install packages (safe — no code executes)$ vlt install
# Run build scripts, automatically excluding packages flagged as malware
$ vlt buildBy default, vlt build uses the target
:scripts:not(:built):not(:malware), which skips packages with known
malware alerts.
You can be more selective:
# Only allow specific packages to run scripts$ vlt build --target="#esbuild, #node-gyp"
# Or allow scripts for direct dependencies only
$ vlt build --target=":root > :scripts"If you need legacy npm behavior (not recommended):
$ vlt install --allow-scripts='*'See vlt build for full details.
Workspaces
npm workspaces are defined in the root package.json:
{ "workspaces": [ "packages/*" ]}vlt workspaces are defined in vlt.json:
{ "workspaces": [ "packages/*" ]}Key Differences
- Definition location —
vlt.jsoninstead ofpackage.json - Named groups — vlt supports grouping workspaces for targeted operations:
{ "workspaces": { "apps": "apps/*", "libs": "packages/*" }}Workspace Commands
| npm | vlt |
|---|---|
npm run test -w packages/a | vlt run test -w packages/a |
npm run test --workspaces | vlt run test --recursive |
npm install <pkg> -w packages/a | vlt install <pkg> -w packages/a |
See Workspaces for full details.
Overrides → Graph Modifiers
npm uses overrides in package.json to force dependency versions.
vlt uses Graph Modifiers in vlt.json, which
are powered by DSS selectors and offer more precise targeting.
{ "overrides": { "lodash": "^4.17.21", "express>qs": "6.10.0" }}{ "modifiers": { "#lodash": "^4.17.21", ":root > #express > #qs": "=6.10.0" }}Graph Modifiers use CSS-like specificity rules when multiple selectors match the same dependency.
Migration Checklist
- Install vlt:
npm install -g vlt - In your project root, create
vlt.jsonwith your registry and workspace config (or usevlt config set) - Move any scoped registry config from
.npmrctovlt.json - Move workspace definitions from
package.jsontovlt.json - Move
overridesfrompackage.jsontomodifiersinvlt.json - Run
vlt installthenvlt build - Commit
vlt-lock.json - Update CI scripts: replace
npm ciwithvlt install --expect-lockfile && vlt build - Update CI auth: replace
NPM_TOKENwithVLT_TOKEN - Update any
npxusage tovlx