This guide covers migration from both yarn v1 (classic) and yarn v2+ (berry). Key differences are called out where they apply.
Quick Start
# Install vlt globally$ npm install -g vlt
# In your existing project, run:
$ vlt install $ vlt buildvlt reads your existing package.json files and resolves
dependencies. The yarn.lock file is not migrated — vlt performs a
fresh resolution and creates vlt-lock.json.
Command Mapping
| yarn | vlt | Notes |
|---|---|---|
yarn / yarn install | vlt install | Does not run lifecycle scripts |
yarn add <pkg> | vlt install <pkg> | |
yarn add -D <pkg> | vlt install -D <pkg> | |
yarn remove <pkg> | vlt uninstall <pkg> | |
yarn run <script> | vlt run <script> | |
yarn <script> | vlt run <script> | See fallback-command |
yarn dlx <pkg> / npx <pkg> | vlx <pkg> | Run remote packages |
yarn exec <cmd> | vlt exec <cmd> | |
yarn init | vlt init | |
yarn pack | vlt pack | |
yarn npm publish | vlt publish | |
yarn npm login | vlt login | |
yarn npm whoami | vlt whoami | |
yarn workspaces list | vlt list | |
yarn why <pkg> | vlt query '#<pkg>' | DSS query; see Selectors |
yarn install --frozen-lockfile | vlt install --frozen-lockfile | |
yarn install --immutable | vlt install --expect-lockfile | |
yarn config set <key> <val> | vlt config set <key>=<val> | |
yarn up <pkg> | vlt install <pkg> | Re-resolves to latest matching |
Shorthand Script Execution
Yarn lets you run scripts without run (e.g., yarn build). vlt
supports this via the fallback-command config:
$ vlt config set fallback-command=run-execAfter setting this, vlt build will first check for a vlt command
named build, and if none matches, look for a package.json script.
Configuration
.yarnrc.yml / .yarnrc → vlt.json
yarn v1 uses .yarnrc and .npmrc. yarn v2+ uses .yarnrc.yml. vlt
uses vlt.json.
yarn v2+ example:
# .yarnrc.yml (yarn berry)npmRegistryServer: "https://registry.internal.company.com/"npmScopes:mycompany: npmRegistryServer: "https://npm.mycompany.com/" npmAuthToken: "abc123"vlt equivalent:
{ "registry": "https://registry.internal.company.com/", "scope-registries": { "@mycompany": "https://npm.mycompany.com/" }}Auth tokens are stored separately in vlt’s keychain, not in config files. See Authentication below.
yarn v1 example:
# .npmrc (yarn classic)registry=https://registry.internal.company.com/@mycompany:registry=https://npm.mycompany.com/Same vlt.json as above.
Registry Configuration
Scoped Registries
Both yarn and vlt support scope-to-registry mapping:
{ "scope-registries": { "@mycompany": "https://npm.mycompany.com/" }}Named Registry Aliases
vlt also supports named registry aliases, which are more explicit than scoped registries. Dependencies reference a named registry directly, removing ambiguity:
{ "registries": { "internal": "https://npm.mycompany.com/" }}{ "dependencies": { "@mycompany/utils": "internal:@mycompany/utils@^2.0" }}Authentication
yarn v1 stores tokens in .npmrc. yarn v2+ stores them in
.yarnrc.yml. Both approaches risk accidental commits of secrets.
vlt stores auth tokens in an XDG-compliant keychain file, separate from project configuration.
# Log in to default registry$ vlt login
# Log in to a custom registry
$ vlt login --registry=https://npm.mycompany.com/CI Environments
# yarn v2+YARN_NPM_AUTH_TOKEN=abc123 yarn install
# vlt
VLT_TOKEN=abc123 vlt installSee Authentication for full details.
Lockfile
yarn v1 uses yarn.lock (custom format). yarn v2+ also uses
yarn.lock (YAML-based). vlt uses vlt-lock.json.
When you first run vlt install, vlt creates vlt-lock.json from a
fresh resolution. Your yarn.lock is not read.
What to do:
- Run
vlt installto generatevlt-lock.json - Commit
vlt-lock.json - Optionally remove
yarn.lockonce you’ve fully switched
Install Script Protection
This is a major difference from yarn.
yarn v1 runs all lifecycle scripts automatically. yarn v2+
runs scripts for direct dependencies but blocks transitive dependency
scripts by default (you can allowlist via .yarnrc.yml).
vlt goes further: vlt install runs no scripts at all by
default. The build step is completely separate:
# Phase 1: Install (no code executes)$ vlt install
# Phase 2: Build (runs scripts, skipping known malware)
$ vlt buildBy default, vlt build uses the target
:scripts:not(:built):not(:malware) — it only runs scripts for
packages that need building and aren’t flagged as malware by
Socket.
You can target scripts precisely:
# Only allow specific trusted packages$ vlt build --target="#esbuild, #node-gyp"
# Persist your choice
$ vlt config set "command.build.target=#esbuild, #node-gyp"See vlt build for full details.
Workspaces
yarn v1
yarn v1 defines workspaces in the root package.json:
{ "private": true, "workspaces": [ "packages/*" ]}yarn v2+
yarn v2+ is similar but also supports the workspaces field in
.yarnrc.yml for additional filtering.
vlt
vlt defines workspaces in vlt.json:
{ "workspaces": [ "packages/*" ]}vlt also supports named workspace groups for targeted operations:
{ "workspaces": { "apps": "apps/*", "libs": [ "packages/*", "shared/*" ] }}# Run tests only in the libs group$ vlt run test -g libs
# Run build across all workspaces
$ vlt run build --recursiveWorkspace Commands
| yarn | vlt |
|---|---|
yarn workspace <name> <cmd> | cd <path> && vlt <cmd> or vlt <cmd> -w <path> |
yarn workspaces foreach <cmd> | vlt <cmd> --recursive |
See Workspaces for full details.
Resolutions → Graph Modifiers
yarn uses resolutions in package.json to force dependency
versions. vlt uses Graph Modifiers in
vlt.json.
{ "resolutions": { "lodash": "^4.17.21", "express/qs": "6.10.0" }}{ "modifiers": { "#lodash": "^4.17.21", ":root > #express > #qs": "=6.10.0" }}Graph Modifiers use DSS selectors, which give you more precise control over which instances of a dependency are affected.
Plug’n’Play (PnP)
If you’re using yarn v2+ with Plug’n’Play (no node_modules), the
switch to vlt means going back to a node_modules-based layout. This
is generally straightforward — vlt creates a standard node_modules
directory.
If your project relies on PnP-specific features (like .pnp.cjs
loaders), you’ll need to remove those references from your build
tooling and runtime configuration.
Features Not in vlt
Some yarn-specific features don’t have direct equivalents:
- Plug’n’Play / Zero-Installs — vlt uses
node_modules - Constraints — Use vlt’s DSS query system for dependency policy enforcement
- Patches (
yarn patch) — Not yet available in vlt - Protocols (
portal:,patch:) — vlt supportsfile:,workspace:,git:, andregistry:specifiers
Migration Checklist
- Install vlt:
npm install -g vlt - Create
vlt.jsonwith registry and workspace configuration - Move scoped registry config from
.yarnrc.yml/.npmrctovlt.json - Move workspace definitions from
package.jsontovlt.json - Move
resolutionsfrompackage.jsontomodifiersinvlt.json - If using PnP, remove
.pnp.cjs,.pnp.loader.mjs, and related.yarnrc.ymlsettings - Run
vlt installthenvlt build - Commit
vlt-lock.json - Update CI scripts: replace
yarn install --immutablewithvlt install --expect-lockfile && vlt build - Update CI auth: replace
YARN_NPM_AUTH_TOKENwithVLT_TOKEN - Update any
yarn dlxusage tovlx