Skip to content

Usage:

Terminal
$ vlt install [packages ...]

Install dependencies into node_modules, updating package.json and vlt-lock.json appropriately.

By default, vlt install downloads and extracts packages without executing lifecycle scripts—enhancing security by preventing arbitrary code execution during installation. Use vlt build after installation to run scripts selectively.

What is a Package?

  • A folder containing a package.json file
  • A gzipped tarball containing a folder with a package.json file
  • A URL that resolves to a gzipped tarball
  • A <name>@<version> that is published to a configured registry
  • A <name>@<semver-range> that is published to a configured registry
  • A <name>@<tag> that points to a package in a configured registry
  • A <name> by itself, which defaults to using the latest tag from a registry
  • A <custom>:<name>@<version> that points to a custom registry configured in vlt.json
  • A registry:URL#<name>@<version> that points to a custom registry url
  • A <git remote url> that resolves to a folder with a package.json file

Basic Usage

Install all dependencies

Terminal
$ vlt install

Installs all dependencies from package.json without running scripts.

Adding new packages

Using positional arguments that use the valid package specification described above.

Registry packages

Terminal
# Latest version
$ vlt install express
# Scoped packages using semver ranges
$ vlt install @vltpkg/graph@^1.0.0

Aliases

Install multiple versions of the same package side-by-side:

Terminal
# Install react v18 as my-react
$ vlt install my-react@npm:react@18
# Install both major versions under aliased names
$ vlt install react18@npm:react@18 react19@npm:react@19

In the vlt cli the traditional aliases also enable installing from custom registries:

Terminal
# Install from vlt.json configured custom registry
$ vlt install custom:@org/pkg@^1.0.0
# Install using an aliased name, pointing to a custom registry
$ vlt install pkg@custom:@org/pkg

Git repositories

Terminal
# GitHub shorthand
$ vlt install github:user/repo
$ vlt install github:user/repo#v1.0.0
$ vlt install github:user/repo#semver:^1.0
# Full git URL
$ vlt install git+ssh://[email protected]:user/repo.git
# OR
$ vlt install git+https://github.com/user/repo.git#main
# GitLab
$ vlt install gitlab:user/repo
# Bitbucket
$ vlt install bitbucket:user/repo

When using #semver:<range>, vlt looks for matching tags/refs in the remote repository.

Tarballs

Terminal
# Local tarball
$ vlt install ./package.tgz
# Remote tarball
$ vlt install https://example.com/package.tgz

Local directories

Terminal
# Relative path
$ vlt install ./my-local-package
# Install from parent directory
$ vlt install ../shared-lib

Options

Dependency type flags

FlagShortDescription
--save-prod-PAdd to dependencies (default)
--save-dev-DAdd to devDependencies
--save-optional-OAdd to optionalDependencies
--save-peerAdd to peerDependencies

Lockfile options

FlagDescription
--frozen-lockfileFail if lockfile is missing or out of sync with package.json
--expect-lockfileFail if lockfile is missing or outdated
--lockfile-onlyUpdate only vlt-lock.json and package.json, skip node_modules

Script execution

FlagDescription
--allow-scripts=<selector>Allow specific packages to run lifecycle scripts during install
Terminal
# Allow specific packages to run scripts during install
$ vlt install --allow-scripts="#esbuild, #node-gyp"
# Allow only direct dependencies to run scripts
$ vlt install --allow-scripts=":root > *"

Registry options

FlagDescription
--tag=<tag>Default dist-tag to use (default: latest)
--before=<date>Install relative to the provided ISO 8601 date
Terminal
# Install from beta channel
$ vlt install express --tag=beta
# Install versions published before a specific date
$ vlt install lodash --before="2024-01-01"

Workspace options

FlagShortDescription
--workspace=<ws>-wLimit operation to specific workspaces
--workspace-group=<group>-gOperate on named workspace groups
Terminal
# Install in specific workspace
$ vlt install -w packages/core lodash
# Install in workspace group
$ vlt install -g apps express

Phased Package Installations

Traditional package managers run lifecycle scripts automatically during install—a security risk that allows malicious packages to execute arbitrary code.

vlt separates installation into two distinct phases:

  1. Install phase: Downloads and extracts packages (no scripts)
  2. Build phase: Runs lifecycle scripts for selected packages
Terminal
# Phase 1: Install packages safely
$ vlt install
# Phase 2: Build with control over what runs
$ vlt build

This separation enables you to:

  • Inspect dependencies before any code execution
  • Selectively allow scripts using DSS queries
  • Protect against supply chain attacks

By default, vlt build uses :scripts:not(:built):not(:malware) which excludes packages with known malware alerts.

For more details, see the vlt build documentation.

Graph Modifiers

Graph Modifiers provide precise control over dependency resolution using Dependency Selector Syntax (DSS). Configure them in your vlt.json:

vlt.json
{
"modifiers": {
"#react": "^19",
":root > #webpack > #browserslist": "^4.23.0"
}
}

Override all instances

Pin a package version across the entire dependency graph:

vlt.json
{
"modifiers": {
"#lodash": "^4.17.21"
}
}

Override transitive dependencies

Target specific dependency paths:

vlt.json
{
"modifiers": {
":root > #webpack > #terser-webpack-plugin > #terser": "^5.31.0"
}
}

When multiple selectors match, the most specific one wins.

For more details on Graph Modifiers, see the Graph Modifiers documentation.

Peer Dependencies

vlt handles peer dependencies by isolating their contexts, allowing multiple versions of the same package to coexist when necessary. When different parts of your dependency tree require incompatible peer versions, vlt automatically subdivides the graph into separate peer dependency contexts.

Key behavior: vlt always attempts to use a single version of a package for peer dependencies. When that’s not possible, it duplicates packages as needed, storing them in separate locations within node_modules/.vlt/ and linking appropriately so each package resolves to its correct peer version.

This happens automatically during vlt install—no configuration required.

For more details, see the Peer Dependencies documentation.

Notes

  • Running vlt install with no arguments installs all dependencies from package.json
  • The lockfile (vlt-lock.json) ensures reproducible installs across environments
  • Use vlt ci as a shorthand for vlt install --expect-lockfile in CI pipelines
  • Peer dependencies are handled automatically with context isolation when version conflicts arise

Aliases

i, add