# Affected Dependencies (/client/affected) In a monorepo, a change to one workspace rarely stays there. The *affected* set is the workspace you touched **plus everything that depends on it** — the packages whose tests, builds and publishes could break because of your change. vlt has no `affected` command. Affected is inherited state, so it is expressed with [Dependency Selector Syntax](/client/selectors) instead: [`:diff()`](/client/selectors/pseudo-classes/diff) finds what changed, and [`:has()`](/client/selectors/pseudo-classes/has) walks back up to what depends on it. ## What changed [`:diff()`](/client/selectors/pseudo-classes/diff) matches packages whose files changed against a git commitish, defaulting to `HEAD`: Terminal: ```bash # uncommitted changes $ vlt query ':workspace:diff()' ``` Terminal: ```bash # everything this branch changed $ vlt query ':workspace:diff(main...HEAD)' ``` Use the three-dot form. `:diff()` runs `git diff --name-only `, which compares that ref to your working tree in *both* directions — as soon as `main` moves ahead, everything changed on `main` is reported as changed here too. `main...HEAD` diffs against the merge base instead, which is what "changed on this branch" means. Quote any ref containing a `/`: `:diff("origin/main...HEAD")`. Bare, the selector parser rejects the slash and the query exits non-zero. `git diff` also ignores untracked files, so a brand new file only counts once it is staged or committed. ## Why the `:workspace` prefix `:diff()` matches the project root whenever *anything* in the repo changed, so a bare `:diff(main...HEAD)` almost always includes `.` as well. `:workspace` drops it. The trade-off: a change to root-level files only — `tsconfig.json`, a CI workflow, the lockfile — maps to the root package alone, so `:workspace:diff()` returns nothing at all for it. A gate built on `:workspace` skips the job on those changes. ## What depends on what changed [`:has()`](/client/selectors/pseudo-classes/has) matches packages with a **direct** dependency on a match: Terminal: ```bash $ vlt query ':workspace:has(:diff(main...HEAD))' ``` Nest it to reach further up the graph. Each level of `:has()` is one more hop away from the change: Terminal: ```bash # dependents of the dependents $ vlt query ':workspace:has(:has(:diff(main...HEAD)))' ``` ## The affected set Combine both with a comma. Selector lists are unioned, so this is "changed, or depending on something changed": Terminal: ```bash $ vlt query ':workspace:diff(main...HEAD), :workspace:has(:diff(main...HEAD))' ``` Given a monorepo where `packages/utils` changed on your branch: ``` my-monorepo ├── packages/utils/ ← files changed ├── packages/core/ depends on utils ├── packages/cli/ depends on core └── apps/docs/ depends on nothing ``` that union selects: ``` my-monorepo ├── packages/utils/ ✅ changed ├── packages/core/ ✅ depends on utils ├── packages/cli/ depends on core, two hops away └── apps/docs/ ``` `packages/cli` is two hops from the change, so it needs another level of `:has()`. Add one selector per hop your graph is deep: Terminal: ```bash $ vlt query ':workspace:diff(main...HEAD), :workspace:has(:diff(main...HEAD)), :workspace:has(:has(:diff(main...HEAD)))' ``` ## Running scripts on the affected set `vlt run` takes the same selector via `--scope`, so a CI job can test only what your branch could have broken: Terminal: ```bash $ vlt run test --scope=':workspace:diff(main...HEAD), :workspace:has(:diff(main...HEAD)), :workspace:has(:has(:diff(main...HEAD)))' ``` Matched workspaces run in dependency order, so changed workspaces run before their dependents. Workspaces without the script are skipped rather than failing: `--scope` implies `--if-present`, as do `--workspace`, `--workspace-group` and `--recursive`. `--workspace` and `--workspace-group` narrow by path glob or named group instead of by query, but they are not combinable with `--scope` — when `--scope` is given it wins and both are ignored. ## Gating a CI job `--expect-results` turns a query into a check: `vlt query` exits non-zero when the result count does not match, so a job can bail out early when nothing relevant changed. Terminal: ```bash $ vlt query ':workspace:diff("origin/main...HEAD")' --expect-results='>0' \\ || echo 'nothing affected, skipping' ``` Keep the ref quoted here. A parse error also exits non-zero, so an unquoted `origin/main` would be swallowed by the `||` and report "nothing affected" forever. Results are counted as graph edges, not as packages: one workspace depended on from several places counts more than once. `--view=json` emits those same edges — each entry is an edge with the package under `to` — so workspace paths need extracting and deduping: Terminal: ```bash $ vlt query ':workspace:diff("origin/main...HEAD")' --view=json \\ | jq -r '.[].to.location' | sort -u ``` ## See also * [`:diff()`](/client/selectors/pseudo-classes/diff) — match packages by git changes * [`:has()`](/client/selectors/pseudo-classes/has) — match packages by their dependencies * [Workspaces](/client/workspaces) — defining workspaces and groups * [`vlt run`](/client/commands/run) — running scripts across workspaces # Authentication (/client/auth) The vlt client supports logging into multiple different registries. When more than one is configured, scope an auth command to a specific one with [`vlt registry `](/client/commands/registry) (for example `vlt registry main whoami`). See [Targeting a specific registry](/client/registries#targeting-a-specific-registry). If you're setting up a vlt.io account for the first time, start with [`vlt setup`](/client/registries#getting-started-with-vlt-setup) — it authenticates and configures your account's registry aliases in one step. The commands below cover logging into individual registries directly. ## npm Web Login To log into a registry that supports the npm web login, such as the public npm registry, use the `vlt login` command. For example, to log into the default registry: Terminal: ```bash $ vlt login ``` To log into a custom registry that supports npm web login, run the same command, specifying the registry to log into: Terminal: ```bash $ vlt login --registry=https://my-custom-registry.mycompany.local/ ``` To remove your authorization to a given registry, including attempting to destroy the token on the server side, use the `vlt logout` command. ## Other Registries If your registry provides a bearer token that should be presented for authentication, it can be added using the `vlt token add` command. This will prompt you to paste in the token. To remove a token from vlt's keychain, use the `vlt token rm` command. Note that this will *not* delete the token from the server; it only removes it from the local keychain store. A token follows redirects that stay on the same origin (scheme, host and port), even to paths outside the registry URL, and is dropped when a redirect changes origin. ## CI (and Other Headless Environments) A token for the default registry can be provided in the `VLT_TOKEN` environment variable. For example: ``` VLT_TOKEN="helloworldtokendeadbeef" vlt install ``` To provide a token for other registries, set a `VLT_TOKEN_{...}` variable named after the registry URL: drop the trailing `/` and replace each run of non-alphanumeric characters with `_`. The path is part of the name, e.g. `https://registry.vlt.io/acme/main/` becomes `VLT_TOKEN_https_registry_vlt_io_acme_main`. ``` VLT_TOKEN_https_my_custom_registry_mycompany_local="helloworldtokendeadbeef" vlt install ``` These variables apply to configured registries (`registry`, `registries`, `scoped-registries` and `jsr-registries`, built-in `gh` and `jsr` included) and to registries you've logged in to. The token is only sent to URLs under that registry URL (plus same-origin redirects, see above). ## OIDC (OpenID Connect) If your CI provider supports OpenID Connect, vlt can authenticate with the registry automatically — no static tokens needed. vlt detects the CI environment, requests an OIDC ID token from the provider, and exchanges it with the registry for a short-lived publish token. Everything happens behind the scenes. Note that this requires a registry that supports OIDC trusted publishing. The vlt.io registry currently does not — use a [service token](/registry/publishing/ci) there. ### Supported Providers * **GitHub Actions** — native support, no extra config * **GitLab CI** — via `NPM_ID_TOKEN` environment variable * **CircleCI** — via `NPM_ID_TOKEN` environment variable ### GitHub Actions Add `id-token: write` to the job's permissions and vlt handles the rest: github-actions.yml: ```yaml jobs: publish: runs-on: ubuntu-latest permissions: contents: read id-token: write steps: - uses: actions/checkout@v4 - uses: vltpkg/setup-vlt@v1 - run: vlt publish ``` ### GitLab CI / CircleCI Set the `NPM_ID_TOKEN` environment variable with the OIDC ID token provided by your CI platform. vlt reads it automatically and exchanges it for a publish token. ### How It Works When you run `vlt publish`, vlt checks for an available OIDC ID token from the CI environment. It sends that token to the registry's token endpoint, which verifies the token and returns a short-lived credential. vlt uses that credential for the publish request. No tokens are stored, and nothing persists after the job finishes. ### Fallback Behavior If OIDC isn't available — for example, the registry doesn't support it, or the required permissions aren't configured — vlt silently falls back to `VLT_TOKEN` or keychain-based auth. No errors, no interruptions. ## OTP One-time password (OTP) and MFA is supported for non-headless environments by opening a web browser or prompting on the command line for a OTP from your authenticator app, when the registry prompts for multifactor auth. For headless environments, an OTP token may be provided in the `VLT_OTP` environment variable. ## Why Environment Variables and Not Config The vlt client is designed to make it less likely that passwords are leaked in configuration files that might be checked into source control, which is a surprisingly common security failure mode. With vlt, sensitive information is *only* kept in a tightly restricted keychain file, or in the environment. Of course, perfect security is often impossible, but it is nevertheless important to do our best to make it less likely that passwords can be leaked by accident. ## Credential Management Each "identity" in vlt is a set of authentication tokens for known registries. For example, you could have a `corp` identity with the credentials that you use for the work on corporate projects, and a `personal` account with your own personal npm registry login credentials. Running `vlt config set identity=corp` will switch into `corp` mode. `vlt config set identity=personal` will switch into `personal` mode. This can also be set in a project root with a `vlt.json` config file, to make it easier to set per project. For example, you could have this in your `vlt.json` in the project root: ```json { "identity": "corp" } ``` # Using Catalogs for Dependency Management (/client/catalogs) The vlt client provides robust catalog support for managing dependency versions across your projects and workspaces. This feature, heavily inspired by pnpm's implementation, allows you to define centralized dependency specifications that can be reused throughout your project, reducing duplication and simplifying version orchestration across shared dependencies. ## What are Catalogs? Catalogs are centralized repositories of dependency specifications defined in your `vlt.json` file. They allow you to: * **Centralize version management**: Define dependency versions once and reuse them across multiple workspaces * **Reduce duplication**: Eliminate the need to specify the same version ranges in multiple `package.json` files * **Simplify updates**: Update a dependency version in one place and have it apply everywhere it's used * **Maintain consistency**: Ensure all workspaces use the same versions of shared dependencies ## Catalog Configuration Catalogs are configured in your project's `vlt.json` file using two main fields: ### Default Catalog (`catalog`) The `catalog` field defines a default catalog of dependency specifications: vlt.json: ```json ``` ### Named Catalogs (`catalogs`) The `catalogs` field allows you to define multiple named catalogs for different purposes: vlt.json: ```json ``` You can combine both approaches in the same configuration: vlt.json: ```json ``` ## Using the `catalog:` Protocol Once you've defined catalogs in your `vlt.json`, you can reference them in your `package.json` files using the `catalog:` protocol. ### Default Catalog Reference To reference a dependency from the default catalog, use `catalog:` without specifying a catalog name: package.json: ```json ``` ### Named Catalog Reference To reference a dependency from a named catalog, use `catalog:`: package.json: ```json ``` ## Installation Examples ### Installing from Catalogs You can install packages directly using the catalog protocol: Terminal: ```bash $ vlt install typescript@catalog: ``` Terminal: ```bash $ vlt install vitest@catalog:testing ``` ### Adding Dependencies to Catalogs When you install a new dependency, you can add it to a catalog by first updating your `vlt.json`: vlt.json: ```json ``` Then reference it in your `package.json`: package.json: ```json ``` ## Real-World Example Here's how the vlt project itself uses catalogs in its `vlt.json`: vlt.json: ```json ``` And how it's used in workspace packages: src/spec/package.json: ```json ``` ## Updating a Catalog Entry Editing a catalog value in `vlt.json` is applied by the next `vlt install`: every dependency that reads the entry is re-resolved and the new value is recorded in `vlt-lock.json`, even when no resolution changes. Until that install runs, `vlt install --frozen-lockfile` and `vlt ci` fail and name the entry that differs: Terminal: ```bash Lockfile is out of sync with package.json. Run "vlt install" to update. Configuration options have changed: catalog: typescript "^5.0.0" -> "^5.9.0" ``` ## Advanced Usage You can even chain catalog references with other protocols. For example, using catalog with named registries: package.json: ```json ``` Where your `vlt.json` might look like: vlt.json: ```json ``` ## Best Practices 1. **Group Related Dependencies**: Use named catalogs to group dependencies by purpose (build tools, testing, etc.) 2. **Use Semantic Versioning**: Define version ranges in catalogs using semantic versioning principles 3. **Keep Catalogs Updated**: Regularly review and update catalog entries to maintain security and compatibility 4. **Start with Common Dependencies**: Begin by cataloging dependencies that are used across multiple workspaces ## Error Handling If you reference a catalog or dependency that doesn't exist, vlt will provide helpful error messages: * **Missing default catalog**: `Default catalog not found for ` * **Missing named catalog**: `Catalog "" not found for ` * **Missing dependency in catalog**: `Package "" not found in default catalog` or `Package "" not found in catalog ""` * **Catalog entry using `catalog:`**: `Catalog entry "" in catalog "" cannot be a catalog: spec` For example: ``` Config Error: Default catalog not found for abbrev@catalog: From: ./packages/a/package.json (dependencies) Wanted: [ 'catalog:dev' ] Valid Options: [ 'catalog:dev', 'catalog:tools' ] ``` `From` is the `package.json` and dependency type declaring the spec (prefixed with `vlt-lock.json` when the spec was read from the lockfile, eg: `vlt ci`), `Wanted` lists the catalogs that define the dependency and `Valid Options` lists all defined catalogs. ## Migration from Other Package Managers If you're migrating from pnpm, the catalog syntax is largely compatible. Simply move your pnpm catalog definitions from `pnpm-workspace.yaml` to the `catalog` and `catalogs` fields in `vlt.json`. # vlt bugs (/client/commands/bugs) Usage: Terminal: ```bash $ vlt bugs [] [--target=] ``` Open bug tracker for a package in a web browser. ## How It Works The `vlt bugs` command locates and opens the bug tracker for any package in your dependency graph. It follows the following resolution strategy to find the best bug tracker URL: 1. **Bugs field (string)** – Uses the `bugs` property directly if it's a string URL 2. **Bugs field (object with url)** – Uses `bugs.url` if available 3. **Bugs field (object with email)** – Creates a `mailto:` link if only email is provided 4. **Repository Resolution** – Falls back to the package's `repository` field. For known git hosts (GitHub, GitLab, Bitbucket, etc.), generates the canonical issues URL 5. **Fallback** – If no bugs or repository info is found, falls back to the [vlt.io](https://vlt.io) package page This means you always get taken to the most relevant bug tracker. ## Basic Usage ### Open bugs for current project When run without arguments, `vlt bugs` reads your local `package.json` and opens the bug tracker for your current project: Terminal: ```bash $ vlt bugs ``` This is particularly useful when working on a project and you want to quickly access your own issue tracker. ### Open bugs for any package Provide a package spec to open the bug tracker for any package, whether it's installed in your project or not: Terminal: ```bash # Open bugs for a specific package $ vlt bugs express # Open bugs for a specific version $ vlt bugs typescript@5.0.0 # Open bugs for a scoped package $ vlt bugs @vltpkg/graph ``` The command fetches the package manifest from the registry and determines the best bug tracker URL to open. ### Query packages using --target Use the `--target` option with DSS query syntax to find bug trackers for packages in your dependency graph: Terminal: ```bash # Open bugs for a specific package in your graph $ vlt bugs --target="#lodash" # List bug tracker URLs for all direct dependencies $ vlt bugs --target=":root > \*" # Find bugs for all packages from a specific scope $ vlt bugs --target="[name^=@types]" ``` Note: When the query matches multiple packages, bug tracker URLs are listed instead of being opened automatically. ## Use Cases ### Reporting Issues Quickly report bugs in dependencies: Terminal: ```bash # Found a bug in a package? Report it $ vlt bugs problematic-package # Report issues for packages in your graph $ vlt bugs --target="#problematic-package" ``` ### Checking for Known Issues Before diving into debugging, check if others have reported the same issue: Terminal: ```bash # Check issues for a troublesome dependency $ vlt bugs --target="#failing-dep" # Check issues for multiple packages $ vlt bugs --target=":root > \*" ``` ## Options ### `--target=` Filter packages using DSS query syntax. When a single package matches, its bug tracker opens in your browser. When multiple packages match, their URLs are listed. Terminal: ```bash # Open bugs for a single package $ vlt bugs --target="#express" # List bugs for all direct dependencies $ vlt bugs --target=":root > \*" # List bugs for dev dependencies $ vlt bugs --target=":type(dev)" ``` # vlt build (/client/commands/build) Usage: Terminal: ```bash $ vlt build [options] ``` The `vlt build` command represents a fundamental shift in how JavaScript package managers handle post-installation tasks. By separating the build phase from installation, `vlt` gives you unprecedented control over which packages run lifecycle scripts in your project. ## Breaking the Traditional Model Traditional package managers conflate installation with building – when you run `npm install`, packages are downloaded, extracted, and their lifecycle scripts run automatically. This monolithic approach has several drawbacks: * **Security risks**: Malicious packages can execute arbitrary code during installation * **Limited control**: You can't selectively enable or disable scripts for specific packages With `vlt`, we've reimagined this process as two distinct phases: 1. **`vlt install`** – Downloads and extracts packages into `node_modules` 2. **`vlt build`** – Runs lifecycle scripts and performs additional binary linking when needed This separation leverages the full power of our Dependency Selector Syntax (DSS) query language, allowing you to precisely control which packages are allowed to execute scripts. ## Basic Usage The simplest workflow mirrors traditional package managers but with explicit steps: Terminal: ```bash # Step 1: Install packages (no scripts run) $ vlt install # Step 2: Build all packages that need building $ vlt build ``` The build process is idempotent – it only performs work that's actually needed based on the current state of your dependency graph. If a package has already been built, `vlt build` skips it automatically. ## Selective Building with DSS Queries The real power of `vlt build` comes from its integration with our query language. You can use any DSS selector to target specific packages as a positional argument to the `vlt build` command: Terminal: ```bash # Build only packages matching a specific target query $ vlt build ":root > *" # Build all packages except those marked as dev dependencies $ vlt build ":not(:dev)" ``` ### Using the target option Use the `--target` option to control precisely which packages to build. This gives you fine-grained control over script execution: Terminal: ```bash # Build only a specific package $ vlt build --target="#my-package" # Build everything except packages with no author $ vlt build --target=":not([author])" ``` If you want to persist target configuration you can store it to your `vlt.json` config file using the `vlt config` command: Terminal: ```bash # Persists a target query to the project vlt.json file $ vlt config set "command.build.target=" # Build (with no args) uses the target info from vlt.json $ vlt build ``` ## Default build target By default `vlt build` uses a target value of `:scripts:not(:built):not(:malware)` targetting only not build packages that have lifecycle scripts (or a root `binding.gyp`) and do not have any malware alerts associated with it. npm registry packages with no security data, because the request timed out or Socket has not scanned them yet, are skipped and reported as not built. See [Understanding Security Data](/client/security#understanding-security-data). ## Examples ### Excluding malware and any package not from a specific scope In this example we're only allowing scripts from packages that do not have a `malware` alert associated to it and packages from a specific, well known scope name. Terminal: ```bash # Install without running any scripts $ vlt install # Look up if there are packages with malware alerts in my current install $ vlt query ":malware" # Look up what packages have build scripts and are not from a known scope $ vlt query ":scripts:not([name^=@myscope])" # Build only packages from my known scope that are NOT flagged as malware $ vlt build --target="\*[name^=@myscope]:not(:malware)" ``` ### Exact dependency names Maybe you only trust certain critical build tools to run scripts: Terminal: ```bash # Install packages $ vlt install # Only build the specific tools you trust $ vlt build --target="#esbuild, #typescript" ``` ## Options ### `--target` The `--target` option accepts any valid DSS query to filter which packages to build: Terminal: ```bash # Build only direct dependencies $ vlt build --target=":root > *" # Build only packages with native bindings $ vlt build --target=":has-binary" ``` It's usage is interchangeable with a positional argument, you should use either one or the other. ### Build State Persistence The build state is tracked in vlt's `node_modules` metadata. Each package node stores its build state (`needed`, `built`, or `failed`). It's possible to retrieve the already built files using the `:built` query selector: Terminal: ```bash # Query all built packages $ vlt query ":built" # Return all packages that have scripts that needs to be built $ vlt query ":scripts:not(:built)" ``` ## Best Practices 1. **Start with `vlt install`** – Always install first, then decide what to build 2. **Use queries for precision** – Target specific packages or patterns rather than building everything 3. **Persist your choices** – Save your target query to `vlt.json` for consistent builds 4. **Review regularly** – Periodically audit your target query to ensure it matches your security requirements, continuing to maintain and evolve it as you add and update packages ## Migration from Traditional Package Managers If you're coming from npm, running install followed by build is the functional equivalent of the traditional package manager behavior: Terminal: ```bash # Traditional approach $ vlt install $ vlt build ``` The difference being that, as mentioned previously, `vlt build` by default protects you from running scripts of dependencies with known malware. If you are really trying to emulate the legacy npm behavior of running all lifecycle scripts, you can use the `--allow-scripts="*"` options to opt-in to all scripts and have the `vlt` client work as a traditional package manager would: Terminal: ```bash # Bad: Legacy npm-style installation (not recommended) $ vlt install --allow-scripts="*" ``` # vlt cache (/client/commands/cache) Usage: Terminal: ```bash $ vlt cache [flags] ``` Work with vlt cache folders ## Subcommands ### add Resolve the referenced package identifiers and ensure they are cached. Terminal: ```bash $ vlt cache add [...] ``` ### ls Show cache entries. If no keys are provided, then a list of available keys will be printed. If one or more keys are provided, then details will be shown for the specified items. Terminal: ```bash $ vlt cache ls [...] ``` ### info Print metadata details for the specified cache key to stderr, and the response body to stdout. Terminal: ```bash $ vlt cache info ``` ### clean Purge expired cache entries. If one or more keys are provided, then only those cache entries will be considered. Terminal: ```bash $ vlt cache clean [...] ``` ### delete Purge items explicitly, whether expired or not. If one or more keys are provided, then only those cache entries will be considered. Terminal: ```bash $ vlt cache delete [...] ``` ### delete-before Purge all cache items from before a given date, and global store entries written before it. Date can be provided in any format that JavaScript can parse. Terminal: ```bash $ vlt cache delete-before ``` ### delete-all Delete the entire cache folder to make vlt slower. Terminal: ```bash $ vlt cache delete-all ``` ### verify Check global store entries against their cached tarballs (file list, contents, exec bits) and remove any that differ or have no cached tarball, e.g. after a file in `node_modules` was edited in place. Terminal: ```bash $ vlt cache verify [...] $ vlt cache verify --all ``` ### prune-store Remove global store entries that no `node_modules` folder links to. Copies do not show use: an entry copied or cloned from (install scripts, `store-linker=copy`, macOS, a cache on another drive) stays if that last happened after ``, or in the last 30 days without one. Terminal: ```bash $ vlt cache prune-store $ vlt cache prune-store 2026-01-01 ``` ## Global store The global store holds cached registry package tarballs unpacked, under `/store`. A background process fills it after each install, and later installs place package files from it instead of unpacking tarballs again: hardlinked on Linux, cloned copy-on-write (`clonefile`) on macOS with a Node that has `node:ffi` (26.1 and later, and `--allow-ffi` under `--permission`). By default (`store-linker=auto`) that is all: Windows, and macOS without `node:ffi`, unpack tarballs as before, unless `store-linker` is set to `hardlink`, `clone` or `copy`. Where a clone fails (a volume without clones, a project on another volume), the package is unpacked. A hardlinked package is copied right before its install scripts run, so they don't change its files in the store; a cloned one needs no copy. When installed with `auto` on Linux or with `hardlink`, files in `node_modules` are hardlinks into the global store, so editing one in place changes it for every project on the machine. To edit `node_modules` in place (debugging, patching), set [`store-linker=copy`](/client/configuring#--store-linkerauto--hardlink--clone--copy--unpack) and reinstall from scratch (remove `node_modules` first), so its files are copies. If files were already edited through a hardlink, run `vlt cache verify --all` to drop the changed entries, then remove `node_modules` and reinstall in every project that linked them: their files are still the edited ones. A clone shares storage with the global store only until it is written to, so editing a cloned `node_modules` in place is safe. `store-linker=unpack` (or `VLT_STORE_LINKER=unpack`) skips the global store entirely. The global store is a cache: deleting it, whole or in part, never breaks an installed project. `delete`, `delete-before` and `clean` also remove the global store entries of the tarballs they remove, `delete-all` removes the whole global store, and `prune-store` removes entries no project links to and no install copied or cloned from lately. Nothing links to the global store on macOS, where packages are cloned, so there `prune-store` (or `delete-before`) is what keeps it from growing. ## Examples Show cache metadata for a given registry URL: Terminal: ```bash $ vlt cache ls https://registry.npmjs.org/typescript ``` Add a given package specifier to the cache by fetching its resolved value: Terminal: ```bash $ vlt cache add eslint@latest ``` Print the cache metadata to stderr, and write the tarball on stdout, redirecting to a file: Terminal: ```bash $ vlt cache info https://registry.npmjs.org/eslint/-/eslint-9.25.1.tgz > eslint.tgz ``` Delete all entries created before Jan 1, 2025: Terminal: ```bash $ vlt cache delete-before 2025-01-01 ``` Check every global store entry: Terminal: ```bash $ vlt cache verify --all ``` # vlt ci (/client/commands/ci) Usage: Terminal: ```bash $ vlt ci ``` Clean install for CI pipelines. Removes `node_modules` and installs dependencies exactly as specified in `vlt-lock.json`, failing if the lockfile is missing or out of date. ## Lifecycle scripts Like [`vlt install`](/client/commands/install), `vlt ci` runs **no lifecycle scripts** of dependencies by default. To opt in: Terminal: ```bash # Allow scripts for specific packages $ vlt ci --allow-scripts="#esbuild" # Persist the query for ci in vlt.json $ vlt config set "command.ci.allow-scripts=#esbuild" # Or build after install (skips packages with malware alerts) $ vlt ci && vlt build ``` See [`vlt build`](/client/commands/build) for build targets. ## Workspaces `vlt ci` reads workspaces from `vlt.json` only. If they are declared only in `package.json` or `pnpm-workspace.yaml`, it warns and ignores them: run `vlt install` and commit `vlt.json` (see [Workspaces](/client/workspaces#saving-workspaces-to-vltjson)). ## Options | Flag | Description | | ------------------------- | ----------------------------------------------------------------------------------------------------- | | `--allow-scripts=` | Allow matching packages to run lifecycle scripts | | `--allow-skills=` | Link the agent skills of matching packages (never saved), see [`vlt skills`](/client/commands/skills) | | `--skills-dir=` | Dirs to link agent skills into, see [`vlt skills`](/client/commands/skills) | # vlt config (/client/commands/config) Usage: Terminal: ```bash $ vlt config [flags] ``` Work with vlt configuration When no subcommand is provided, displays help information for the config command. ## Subcommands ### get Print the named config value(s). When no keys are provided, shows all configuration settings. When a single key is provided with `--config=all` (default), returns the merged configuration value. Use `--config=user` or `--config=project` to get values from specific configuration files only. Terminal: ```bash $ vlt config get [ [ ...]] [--config=] ``` ### pick Select and display specific configuration values. Similar to `get` but optimized for retrieving multiple specific keys. Terminal: ```bash $ vlt config pick [ [ ...]] [--config=] ``` ### list Print all configuration settings currently in effect as key=value pairs. Use `--config` to specify which configuration source to display. Terminal: ```bash $ vlt config list [--config=] ``` Aliases: `ls` ### set Set config values. By default, these are written to the project config file, `vlt.json` in the root of the project. To set things for all projects, run with `--config=user`. Note that `--config=all` defaults to `project` for write operations. Terminal: ```bash $ vlt config set = [= ...] [--config=] ``` ### delete Delete the named config fields. If no values remain in the config file, delete the file as well. By default, operates on the `vlt.json` file in the root of the current project. To delete a config field from the user config file, specify `--config=user`. Note that `--config=all` defaults to `project` for write operations. Terminal: ```bash $ vlt config delete [ ...] [--config=] ``` Aliases: `del`, `rm`, `remove`, `unset` ### edit Edit the configuration file. Note that `--config=all` defaults to `project` for write operations. Terminal: ```bash $ vlt config edit [--config=] ``` ### location Print the file path of the configuration file being used. Terminal: ```bash $ vlt config location [--config=] ``` ## Examples Get all configuration (merged from user and project): Terminal: ```bash $ vlt config get ``` Get a specific configuration value: Terminal: ```bash $ vlt config get registry ``` Get configuration from user config only: Terminal: ```bash $ vlt config get --config=user ``` Set a configuration value in the project config: Terminal: ```bash $ vlt config set registry=https://my-registry.com ``` Set a configuration value in the user config: Terminal: ```bash $ vlt config set color=true --config=user ``` List all configuration as key=value pairs: Terminal: ```bash $ vlt config list ``` List configuration using alias: Terminal: ```bash $ vlt config ls ``` Delete a configuration value: Terminal: ```bash $ vlt config delete registry ``` Delete a configuration value using alias: Terminal: ```bash $ vlt config del registry ``` Find the location of the project config file: Terminal: ```bash $ vlt config location --config=project ``` # vlt create (/client/commands/create) ## Usage Terminal: ```bash $ vlt create [args...] ``` Initialize a new project from a template package. ## Description The `vlt create` command works like `npm create` and `bun create`, automatically prepending "create-" to the package name and executing it. For example, running: Terminal: ```bash $ vlt create react-app my-app ``` Will fetch and execute the `create-react-app` package with the arguments `my-app`. If a satisfying instance of the create package exists in the local `node_modules` folder, then that will be used. Otherwise, vlt will install the package to its XDG data directory without modifying your local dependencies. ## Examples ### Start a Next.js Project Terminal: ```bash $ vlt create next-app my-app ``` This fetches and runs `create-next-app my-app`. You can also pass options through: Terminal: ```bash $ vlt create next-app my-app --typescript --tailwind --eslint $ vlt create next-app my-app --use-pnpm # or any create-next-app flag ``` ### Create a React App Terminal: ```bash $ vlt create react-app my-app ``` This executes `create-react-app my-app` ### Create a Vite Project Terminal: ```bash $ vlt create vite my-project ``` This executes `create-vite my-project` ### Create a SvelteKit Project Terminal: ```bash $ vlt create svelte@latest my-app ``` This executes `create-svelte@latest my-app` ### Use a Scoped Template Terminal: ```bash $ vlt create @scope/template my-app ``` This executes `@scope/create-template my-app` ### Skip Confirmation Prompts Use `--yes` to automatically accept the install prompt: Terminal: ```bash $ vlt create next-app my-app --yes ``` ## Options ### `--allow-scripts ` Filter which packages are allowed to run lifecycle scripts using DSS query syntax. Terminal: ```bash $ vlt create vite my-app --allow-scripts='create-*' ``` ## See Also * [vlt exec](/client/commands/exec) - Execute a command from a package * [vlt init](/client/commands/init) - Initialize a new package.json # vlt docs (/client/commands/docs) Usage: Terminal: ```bash $ vlt docs [] [--target=] ``` Open documentation for a package in a web browser. ## How It Works The `vlt docs` command locates and opens the documentation for any package in your dependency graph. It follows the following resolution strategy to find the best documentation URL: 1. **Homepage field** – Checks the package's `home` property in its `package.json` 2. **Repository Resolution** – Checks the package's `repository` field in its `package.json`. For known git hosts (GitHub, GitLab, Bitbucket, etc.), generates the canonical documentation URL 3. **Fallback** – If no repository is found or the git host is unknown, falls back to the [vlt.io](https://vlt.io) package page This means you always get taken to the most relevant documentation. ## Basic Usage ### Open docs for current project When run without arguments, `vlt docs` reads your local `package.json` and opens the documentation for your current project: Terminal: ```bash $ vlt docs ``` This is particularly useful when working on a project and you want to quickly view your own documentation or verify your repository URL is correctly configured. ### Open docs for any package Provide a package spec to open documentation for any package, whether it's installed in your project or not: Terminal: ```bash # Open docs for a specific package $ vlt docs express # Open docs for a specific version $ vlt docs typescript@5.0.0 # Open docs for a scoped package $ vlt docs @vltpkg/graph ``` The command fetches the package manifest from the registry and determines the best documentation URL to open. ### Query packages using --target Use the `--target` option with DSS query syntax to find documentation for packages in your dependency graph: Terminal: ```bash # Open docs for a specific package in your graph $ vlt docs --target="#lodash" # List documentation URLs for all direct dependencies $ vlt docs --target=":root > \*" # Find docs for all packages from a specific scope $ vlt docs --target="[name^=@types]" ``` Note: When the query matches multiple packages, documentation URLs are listed instead of being opened automatically. ## Use Cases ### Package Discovery Quickly research packages: Terminal: ```bash # Compare test frameworks $ vlt docs tap $ vlt docs jest $ vlt docs vitest ``` ### Debugging and Support Access documentation when troubleshooting issues: Terminal: ```bash # Error with a package? Read the docs $ vlt docs --target="#problematic-package" # Need API reference? $ vlt docs @vltpkg/spec ``` ### Learning and Exploration Explore the ecosystem and learn about packages: Terminal: ```bash # Learn about vlt packages $ vlt docs @vltpkg/graph $ vlt docs @vltpkg/query # Explore popular packages $ vlt docs express $ vlt docs react ``` ## Options ### `--target=` Filter packages using DSS query syntax. When a single package matches, its documentation opens in your browser. When multiple packages match, their documentation URLs are listed. Terminal: ```bash # Open docs for a single package $ vlt docs --target="#express" # List docs for all direct dependencies $ vlt docs --target=":root > \*" # List docs for packages with build scripts $ vlt docs --target=":scripts" ``` # vlt exec-cache (/client/commands/exec-cache) Usage: Terminal: ```bash $ vlt exec-cache [flags] ``` Work with vlt exec-cache folders ## Aliases ``` xc ``` ## Subcommands ### ls Show previously installed packages used for `vlt exec`. Key provided can be either the package name, or the full key. Terminal: ```bash $ vlt exec-cache ls ``` ### delete Delete previously installed packages used for `vlt exec`. If no keys are provided, then all entries will be deleted. Terminal: ```bash $ vlt exec-cache delete [...] ``` ### info Show extended information about a given `vlt exec` installation. Terminal: ```bash $ vlt exec-cache info ``` ### install Install the specified package(s) in the `vlt exec` central cache location. Metadata info about each installation will be printed. Terminal: ```bash $ vlt exec-cache install ... ``` ## Examples Show all the keys for the installations in the `vlt exec` cache: Terminal: ```bash $ vlt exec-cache ls ``` Delete all versions of typescript installed for vlt exec: Terminal: ```bash $ vlt exec-cache delete typescript ``` Show extended info about a specific version of typescript: Terminal: ```bash $ vlt exec-cache info typescript-695bf962 ``` # vlt exec-local (/client/commands/exec-local) Usage: Terminal: ```bash $ vlt exec-local [command] ``` Run an arbitrary command, with the local installed packages first in the PATH. Ie, this will run your locally installed package bins. If no command is provided, then a shell is spawned in the current working directory, with the locally installed package bins first in the PATH. Note that any vlt configs must be specified *before* the command, as the remainder of the command line options are provided to the exec process. ## Aliases ``` xl ``` # vlt exec (/client/commands/exec) Usage: Terminal: ```bash $ vlt exec [--package=] [--call=] [command...] ``` Run a command defined by a package, installing it if necessary. Also available as `vlx`. * If `--package` is set, that package's bins are used. * Otherwise, if the first argument is a bin in the local `node_modules/.bin`, it runs without installing anything. * Otherwise, the first argument is treated as the package, and its default bin is run: its single bin, or the bin named after the package. With no command, a shell is spawned with the bins in `PATH`. Flags for the bin go after `--`. Installs go to vlt's XDG data directory. Local `node_modules` is never changed. ## Local packages A path to a local directory (relative to the current directory) runs its bins in place. Nothing is installed, and its own `node_modules` is used as-is. Terminal: ```bash $ vlx . $ vlx . -- --help $ vlt exec --package=. other-bin ``` ## Aliases ``` x ``` # vlt help (/client/commands/help) Usage: Terminal: ```bash $ vlt help [] ``` Print the full help output for the CLI, or help for a specific command. If no command is specified, shows general CLI help. If a command name is provided, shows help for that specific command (equivalent to running `vlt --help`). ## Examples Show general CLI help: Terminal: ```bash $ vlt help ``` Show help for the install command: Terminal: ```bash $ vlt help install ``` Show help for the run command: Terminal: ```bash $ vlt help run ``` ## Aliases ``` h, ? ``` # CLI Commands (/client/commands) * [cache](/client/commands/cache) * [ci](/client/commands/ci) * [config](/client/commands/config) * [exec](/client/commands/exec) * [exec-cache](/client/commands/exec-cache) * [exec-local](/client/commands/exec-local) * [help](/client/commands/help) * [init](/client/commands/init) * [install](/client/commands/install) * [list](/client/commands/list) * [login](/client/commands/login) * [logout](/client/commands/logout) * [outdated](/client/commands/outdated) * [pkg](/client/commands/pkg) * [query](/client/commands/query) * [run-exec](/client/commands/run-exec) * [run](/client/commands/run) * [skills](/client/commands/skills) * [token](/client/commands/token) * [uninstall](/client/commands/uninstall) * [view](/client/commands/view) * [whoami](/client/commands/whoami) # vlt init (/client/commands/init) Usage: Terminal: ```bash $ vlt init ``` Create a new package.json file in the current directory. # vlt install (/client/commands/install) Usage: Terminal: ```bash $ 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`](/client/commands/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 `@` that is published to a configured registry * A `@` that is published to a configured registry * A `@` that points to a package in a configured registry * A `` by itself, which defaults to using the `latest` tag from a registry * A `:@` that points to a custom registry configured in `vlt.json` * A `registry:URL#@` that points to a custom registry url * A `` that resolves to a folder with a `package.json` file ## Basic Usage ### Install all dependencies Terminal: ```bash $ 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 Installing by name (a **bare spec**) requires a registry to be configured — the `npm` alias has no built-in URL. Run [`vlt setup`](/client/registries#getting-started-with-vlt-setup) once to configure your account's registries. `vlt install` (and `vlt update`, `vlt uninstall`, `vlt ci`, `vlx`/`vlt exec`) require `registries.npm` specifically — or, if you changed `default-registry-alias`, the alias it names — and fail with a config error when it is missing. Terminal: ```bash # 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: ```bash # 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: ```bash # 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: ```bash # 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://git@github.com: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:`, vlt looks for matching tags/refs in the remote repository. ### Tarballs Terminal: ```bash # Local tarball $ vlt install ./package.tgz # Remote tarball $ vlt install https://example.com/package.tgz ``` ### Local directories Terminal: ```bash # Relative path $ vlt install ./my-local-package # Install from parent directory $ vlt install ../shared-lib ``` ## Options ### Dependency type flags | Flag | Short | Description | | ----------------- | ----- | -------------------------------------------- | | `--save-prod` | `-P` | Add to `dependencies` (default) | | `--save-dev` | `-D` | Add to `devDependencies` | | `--save-optional` | `-O` | Add to `optionalDependencies` | | `--save-peer` | | Add to `peerDependencies` | | `--save-types` | | Add matching `@types/*` to `devDependencies` | [`--save-types`](/client/configuring#--save-types) skips packages that ship their own types: Terminal: ```bash # express ships no types: adds @types/express to devDependencies too $ vlt install express --save-types # zod ships its own types: adds zod only $ vlt install zod --save-types ``` ### Config options | Flag | Description | | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `--save-config` | Save registry and git host options given on the command line or via env to the project `vlt.json` (user one with `--config=user`), see [Registries](/client/registries#saving-registries-given-to-install) | ### Lockfile options | Flag | Description | | ------------------- | ------------------------------------------------------------------- | | `--frozen-lockfile` | Fail if lockfile is missing or out of sync with `package.json` | | `--expect-lockfile` | Fail if lockfile is missing or outdated | | `--lockfile-only` | Update only `vlt-lock.json` and `package.json`, skip `node_modules` | ### Script execution | Flag | Description | | ---------------------------- | --------------------------------------------------------------- | | `--allow-scripts=` | Allow specific packages to run lifecycle scripts during install | Terminal: ```bash # 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 > \*" ``` ### Agent skills | Flag | Description | | --------------------------- | ----------------------------------------------------------------------------------------------------------------------- | | `--allow-skills=` | Link the agent skills of matching packages into the agent skill dirs after install (default: none); saved to `vlt.json` | | `--skills-dir=` | Dirs to link agent skills into, replacing detection (`--skills-dir=` links nothing) | Terminal: ```bash # Link the agent skills of direct dependencies $ vlt install --allow-skills=":root > *" # Link one skill of one package $ vlt install --allow-skills="#agent-browser:skill(agent-browser)" ``` See [`vlt skills`](/client/commands/skills). ### Registry options | Flag | Description | | ----------------- | ---------------------------------------------- | | `--tag=` | Default dist-tag to use (default: `latest`) | | `--before=` | Install relative to the provided ISO 8601 date | Terminal: ```bash # 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 | Flag | Short | Description | | --------------------------- | ----- | -------------------------------------- | | `--workspace=` | `-w` | Limit operation to specific workspaces | | `--workspace-group=` | `-g` | Operate on named workspace groups | | `--no-migrate-workspaces` | | Don't save workspaces to `vlt.json` | Terminal: ```bash # 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: ```bash # 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`](/client/commands/build) documentation. ## Graph Modifiers Graph Modifiers provide precise control over dependency resolution using [Dependency Selector Syntax (DSS)](/client/commands/query). Configure them in your `vlt.json`: vlt.json: ```json { "modifiers": { "#react": "^19", ":root > #webpack > #browserslist": "^4.23.0" } } ``` ### Override all instances Pin a package version across the entire dependency graph: vlt.json: ```json { "modifiers": { "#lodash": "^4.17.21" } } ``` ### Override transitive dependencies Target specific dependency paths: vlt.json: ```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](/client/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](/client/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 * Workspaces read from `package.json` or `pnpm-workspace.yaml` are saved to `vlt.json` (not with `--frozen-lockfile` / `--expect-lockfile`), see [Workspaces](/client/workspaces#saving-workspaces-to-vltjson) * Use [`vlt ci`](/client/commands/ci) in CI pipelines: removes `node_modules`, installs exactly from `vlt-lock.json` (like `--expect-lockfile`) and, like `vlt install`, runs no dependency lifecycle scripts unless `--allow-scripts` is set; run `vlt build` after to build packages * Peer dependencies are handled automatically with context isolation when version conflicts arise ## Local directories (Linked Folders) Terminal: ```bash # Relative path $ vlt install ./my-local-package # Install from parent directory $ vlt install ../shared-lib ``` Local directories can be symlinked to a project via the `file:` protocol. Note that these differ from local tarballs (`file:./pkg.tgz`) which are extracted and treated as immutable. ### Installing from within a Linked Folder When you `cd` into a linked folder and run `vlt install`, the vlt cli allows you to add dependencies to that folder's `package.json`: Terminal: ```bash # Project has: "my-lib": "file:./libs/my-lib" $ cd libs/my-lib $ vlt install lodash@^4.17.0 # Adds lodash to libs/my-lib/package.json ``` `vlt` detects your current working directory relative to the project root and targets the appropriate `package.json`. Note: to use `vlt install` or `vlt uninstall` to manage dependencies of a local linked directory, that folder needs to be already in the chain of dependencies of either the root project or one of its workspaces in order for the `vlt` cli to properly manage the operation. ### Relative paths in Linked Folders File specs resolve relative to the linked folder's location: Terminal: ```bash # From libs/my-lib, reference ../shared $ cd libs/my-lib $ vlt install file:../shared ``` ## Aliases ``` i, add ``` # vlt list (/client/commands/list) Usage: Terminal: ```bash $ vlt ls $ vlt ls --view=[human | json | mermaid | svg | png | count] ``` List installed dependencies matching the provided query. Defaults to listing direct dependencies of a project and any configured workspace. The graph being listed is the one built by `vlt install`. In a project installed by another client (an `npm install` or `pnpm install` `node_modules`) there is no such graph, so the command errors instead of reporting every dependency as missing. Run `vlt install` first. `:host()` queries are the exception, since they load their graph from somewhere else. ## Examples List direct dependencies of the current project / workspace Terminal: ```bash $ vlt ls ``` List all dependencies for the current project / workspace Terminal: ```bash $ vlt ls * ``` List all dependencies named 'foo', 'bar', or 'baz' Terminal: ```bash $ vlt ls foo bar baz ``` Lists direct dependencies of a specific package Terminal: ```bash $ vlt ls '[name="@scoped/package"] > *' ``` List all peer dependencies of all workspaces Terminal: ```bash $ vlt ls '*:workspace > *:peer' ``` ## Options ### view Output format. Defaults to human-readable or json if no tty. Use `svg` or `png` to render the dependency graph as an image and open it automatically. ``` --view=[human | json | mermaid | svg | png | count] ``` # vlt login (/client/commands/login) Usage: Terminal: ```bash $ vlt login ``` Authenticate against a registry, and store the token in the appropriate config file for later use. There is no default registry, so a registry must either already be configured or be provided with `--registry=`. On success the registry is written to the project's `vlt.json`, so that it applies to this project only. ## Options | Flag | Description | | -------------------------- | ------------------------------------------------------------------ | | `--registry=` | Registry URL to authenticate against. Saved to `vlt.json`. | | `--identity=` | Identity namespace used to store auth tokens. | | `--config=` | Which config file to write the registry to. Defaults to `project`. | ## See also * [Working with Named Registries](/client/registries) * [Authentication](/client/auth) * [`vlt setup`](/client/commands/setup) # vlt logout (/client/commands/logout) Usage: Terminal: ```bash $ vlt logout ``` Log out of the default registry, deleting the token from the local keychain, as well as destroying it on the server. To target a specific configured registry by alias, use [`vlt registry logout`](/client/commands/registry). See [Targeting a specific registry](/client/registries#targeting-a-specific-registry). # vlt outdated (/client/commands/outdated) Usage: Terminal: ```bash $ vlt outdated $ vlt outdated [package-names...] $ vlt outdated [--target=] [--workspace=] $ vlt outdated [--view=human | json | count] ``` List dependencies that have newer versions available, and what is keeping them from being upgraded. For every registry dependency, the installed version is compared against the highest version that satisfies the declared range (wanted) and against the registry's `latest` dist-tag (latest). Only dependencies that are missing or behind on either count are reported. Each report goes beyond the version numbers: * the size of the jump (major, minor, patch) * whether the installed version is deprecated * security scores and alerts for the installed, wanted and latest versions, so an upgrade that fixes a vulnerability or one that introduces a flagged version stands out * other dependents whose ranges hold the package back * engine and peer dependency requirements of the latest version that this project does not meet * the command that performs the upgrade By default the direct dependencies of the project root and its workspaces are checked; `--workspace` and `--workspace-group` narrow that to the given workspaces. The `--target` option accepts a [DSS query selector](/client/selectors) instead, which can reach any dependency in the graph. Package names given as positional arguments filter either selection. The installed versions come from the graph built by `vlt install`, so the project must be installed by vlt first. Dependencies that do not resolve against a registry (git, file, remote tarball or workspace specs) are not checked. Catalog specs are checked against the range the catalog resolves them to. ## Examples Report outdated direct dependencies of the project and all its workspaces Terminal: ```bash $ vlt outdated ``` Only check the dependencies named `react` and `react-dom` Terminal: ```bash $ vlt outdated react react-dom ``` Only check the dependencies of a single workspace Terminal: ```bash $ vlt outdated --workspace=packages/app ``` Check every dependency in the graph, transitive ones included Terminal: ```bash $ vlt outdated --target="*" ``` Only check the dev dependencies of the project root Terminal: ```bash $ vlt outdated --target=":root > *:dev" ``` Only check dependencies with known vulnerabilities Terminal: ```bash $ vlt outdated --target="*:vuln" ``` Print the report as JSON Terminal: ```bash $ vlt outdated --view=json ``` ## Output The human-readable view is a table with one row per dependency and dependent. The `Why` column summarizes the jump size, deprecation, security changes between the installed version and the wanted or latest one (high and critical severity alerts fixed or added, and score drops), the dependents holding a transitive package back, and the engine or peer requirements of the latest version that are not met. The commands that perform the upgrades follow the table: `vlt update` for versions within the declared ranges, `vlt install` with new ranges for the rest, and the catalog entries to edit. The JSON view is an array of entries with these fields: * `name`, `spec`, `type`: the dependency as declared by its dependent * `current`, `wanted`, `latest`: the installed version (absent when missing), the highest version satisfying the spec, and the registry's `latest` * `dependent`, `location`: the importer name, or `name@version` of a transitive dependent, and its location * `kind`: `missing`, `major`, `minor`, `patch` or `prerelease` * `inRange`: whether `vlt update` picks up a newer version * `deprecated`: the deprecation message of the installed version * `heldBy`: transitive dependents whose ranges do not admit `latest` * `requires`: the `node` engine range and `peers` ranges of `latest` that this project does not satisfy * `security`: `score` (0 to 100) and `alerts` for `current`, `wanted` and `latest`, for the versions the security archive has reports on * `action`: the command that performs the upgrade, for dependencies of an importer ## Options ### target DSS query selector choosing the dependencies to check, in place of the direct dependencies of the selected importers. ``` --target= ``` ### workspace Limit the report to the dependencies of the given workspace(s). ``` --workspace= ``` ### workspace-group Limit the report to the dependencies of the workspaces in the given group(s). ``` --workspace-group= ``` ### view Output format. Defaults to human-readable or json if no tty. `count` outputs the number of outdated dependencies. ``` --view=[human | json | count] ``` # vlt pack (/client/commands/pack) Usage: Terminal: ```bash $ vlt pack ``` Create a tarball from a package in the current directory or specified folder. The tarball will be saved to the current directory with the name `-.tgz`. ## Options ### dry-run Show what would be packed without creating a tarball Terminal: ```bash $ vlt pack --dry-run ``` # vlt ping (/client/commands/ping) Usage: Terminal: ```bash $ vlt ping ``` Ping all configured registries to verify connectivity and check registry health. Registries that share the same URL as the default registry are deduplicated and only pinged once. ## Ping a specific registry Terminal: ```bash $ vlt ping [] ``` Ping a single registry by its alias. Registry aliases are configured via the `registries` field in `vlt.json` or with the `--registries` option. # vlt pkg (/client/commands/pkg) Usage: Terminal: ```bash $ vlt pkg [] [] ``` Get or manipulate package.json values ## Subcommands ### get Get a single value Terminal: ```bash $ vlt pkg get [] ``` ### init Initialize a new package.json file in the current directory Terminal: ```bash $ vlt pkg init ``` ### pick Get multiple values or the entire package Terminal: ```bash $ vlt pkg pick [ [ ...]] ``` ### set Set one or more key value pairs Terminal: ```bash $ vlt pkg set = [= ...] ``` ### delete Delete one or more keys from the package Terminal: ```bash $ vlt pkg delete [ ...] ``` ## Examples Set a value on an object inside an array Terminal: ```bash $ vlt pkg set "array[1].key=value" ``` Append a value to an array Terminal: ```bash $ vlt pkg set "array[]=value" ``` # vlt publish (/client/commands/publish) Usage: Terminal: ```bash $ vlt publish ``` Create a tarball from a package and publish it to the configured registry. This command will pack the package in the current directory or specified folder, and then upload it to the configured registry. The registry is the package's `publishConfig.registry` if set, else `--registry`, else a configured alias. `publishConfig.registry` alone is enough. ## Options ### tag Publish the package with the given tag Terminal: ```bash $ vlt publish --tag= ``` ### access Set access level (public or restricted) Terminal: ```bash $ vlt publish --access= ``` ### otp Provide an OTP to use when publishing a package. Terminal: ```bash $ vlt publish --otp= ``` ### publish-directory Directory to use for pack and publish operations instead of the current directory. The directory must exist and nothing will be copied to it. Terminal: ```bash $ vlt publish --publish-directory= ``` ## Publishing in CI ### Service token For the vlt.io registry, publish from CI with a **service token**. A personal token answers every publish with a one-time-password challenge and fails unattended with `EOTP`. Set it as `VLT_TOKEN`: github-actions.yml: ```yaml - run: vlt publish env: VLT_TOKEN: ${{ secrets.VLT_TOKEN }} ``` See [CI & automation](/registry/publishing/ci) for the full workflow, and [Authentication — CI](/client/auth#ci-and-other-headless-environments) for how token environment variables are named. ### OIDC If your CI provider supports OpenID Connect, vlt can publish without any stored tokens. On GitHub Actions, add `id-token: write` to your job's permissions and vlt handles authentication automatically. This requires a registry that supports OIDC trusted publishing. The vlt.io registry currently does not — use a service token there. See [Authentication — OIDC](/client/auth#oidc-openid-connect) for full details on supported providers and configuration. github-actions.yml: ```yaml jobs: publish: runs-on: ubuntu-latest permissions: contents: read id-token: write steps: - uses: actions/checkout@v4 - uses: vltpkg/setup-vlt@v1 - run: vlt publish ``` # vlt query (/client/commands/query) Usage: Terminal: ```bash $ vlt query $ vlt query --view=[human | json | mermaid | svg | png | count] ``` List installed dependencies matching the provided query. The graph being queried is the one built by `vlt install`. In a project installed by another client (an `npm install` or `pnpm install` `node_modules`) there is no such graph, so the command errors instead of reporting every dependency as missing. Run `vlt install` first. `:host()` queries are the exception, since they load their graph from somewhere else. ## Examples Query packages with the name "foo" Terminal: ```bash $ vlt query '#foo' ``` Query all peer dependencies of workspaces Terminal: ```bash $ vlt query '*:workspace > *:peer' ``` Query all direct project dependencies with a "build" script Terminal: ```bash $ vlt query ':project > *:attr(scripts, [build])' ``` Query packages with names starting with "@vltpkg" Terminal: ```bash $ vlt query '[name^="@vltpkg"]' ``` Find packages with uncommitted changes Terminal: ```bash $ vlt query ':diff()' ``` Find packages changed since main branch Terminal: ```bash $ vlt query ':diff(main)' ``` Find workspaces changed since last commit Terminal: ```bash $ vlt query ':workspace:diff(HEAD~1)' ``` Check for malware in dependencies Terminal: ```bash $ vlt query ':malware' ``` Find packages with critical security issues Terminal: ```bash $ vlt query ':malware(critical), :cve(*), :eval' ``` ## Options ### view Output format. Defaults to human-readable or json if no tty. Use `svg` or `png` to render the dependency graph as an image and open it automatically. ``` --view=[human | json | mermaid | svg | png | count] ``` ### expect-results Set expected result count for automation and CI/CD pipelines. Exits with error code if expectation is not met. ``` --expect-results= ``` **Examples:** * `--expect-results=0` - Expect no results (useful for security checks) * `--expect-results=">0"` - Expect at least one result * `--expect-results="<5"` - Expect fewer than 5 results * `--expect-results=">=10"` - Expect 10 or more results Terminal: ```bash # Security check that fails if malware is found $ vlt query ':malware' --expect-results=0 # Ensure at least one workspace exists $ vlt query ':workspace' --expect-results=">0" ``` # vlt registry (/client/commands/registry) Usage: Terminal: ```bash $ vlt registry [] ``` Run an account command against a specific configured registry, selected by its [`registries`](/client/registries) alias instead of a full URL. vlt has no default registry, so account and authentication commands need to know *which* registry to act against. `vlt registry ` scopes any of those commands to the registry configured under `` in your `vlt.json` — handy when you have more than one (for example the `npm` and `main` aliases created by [`vlt setup`](/client/commands/setup)). ## Groupable commands `` is any of the account/authentication commands: `whoami`, `logout`, `login`, `token`, `access`, `publish`, `unpublish`, `deprecate`, `dist-tag`, `profile`, `ping`. ## Alias resolution The registry is resolved in this order: 1. A `--registry=` on the command line always wins. 2. An explicit `` (as in `vlt registry main whoami`) is looked up in `registries`; an unknown alias is an error. 3. With no explicit target and a single configured registry, that one is used. 4. With multiple configured registries and no explicit target: * on an interactive terminal you are prompted to pick one (the [`--default-registry-alias`](/client/registries#bare-specs-and---default-registry-alias) is pre-selected); * otherwise (CI, pipes) it falls back to `--default-registry-alias`, erroring if that alias is not configured. The same resolution applies to the top-level commands, so `vlt whoami` behaves like `vlt registry whoami`. ## Examples Check who you are on the `main` registry: Terminal: ```bash $ vlt registry main whoami ``` List tokens for the `npm` registry: Terminal: ```bash $ vlt registry npm token list ``` Omit the alias to choose interactively (or fall back to the default alias when non-interactive): Terminal: ```bash $ vlt registry whoami ``` ## See also * [Working with Named Registries](/client/registries) * [`vlt setup`](/client/commands/setup) * [Authentication](/client/auth) # vlt repo (/client/commands/repo) Usage: Terminal: ```bash $ vlt repo [] [--target=] ``` Open repository page for a package in a web browser. ## How It Works The `vlt repo` command locates and opens the source repository for any package in your dependency graph. It follows the following resolution strategy to find the best repository URL: 1. **Repository field (string)** – Uses the `repository` property directly if it's a string URL 2. **Repository field (object with url)** – Uses `repository.url` if available 3. **Hosted Git Info** – For known git hosts (GitHub, GitLab, Bitbucket, etc.), generates the canonical repository browse URL 4. **Raw URL fallback** – If hosted-git-info can't parse the URL, uses the raw repository URL 5. **Homepage fallback** – Falls back to the `homepage` field if no repository is found 6. **Fallback** – If no repository or homepage info is found, falls back to the [vlt.io](https://vlt.io) package page This means you always get taken to the most relevant source repository. ## Basic Usage ### Open repo for current project When run without arguments, `vlt repo` reads your local `package.json` and opens the repository for your current project: Terminal: ```bash $ vlt repo ``` This is particularly useful when working on a project and you want to quickly access the source repository. ### Open repo for any package Provide a package spec to open the repository for any package, whether it's installed in your project or not: Terminal: ```bash # Open repo for a specific package $ vlt repo express # Open repo for a specific version $ vlt repo typescript@5.0.0 # Open repo for a scoped package $ vlt repo @vltpkg/graph ``` The command fetches the package manifest from the registry and determines the best repository URL to open. ### Query packages using --target Use the `--target` option with DSS query syntax to find repositories for packages in your dependency graph: Terminal: ```bash # Open repo for a specific package in your graph $ vlt repo --target="#lodash" # List repository URLs for all direct dependencies $ vlt repo --target=":root > \*" # Find repos for all packages from a specific scope $ vlt repo --target="[name^=@types]" ``` Note: When the query matches multiple packages, repository URLs are listed instead of being opened automatically. ## Use Cases ### Exploring Source Code Quickly navigate to the source code of a dependency: Terminal: ```bash # Browse source for a package $ vlt repo some-package # Browse source for packages in your graph $ vlt repo --target="#some-package" ``` ### Checking for Updates Before updating a dependency, review recent commits and changelog: Terminal: ```bash # Check the repo for a dependency $ vlt repo --target="#outdated-dep" # Check repos for all direct dependencies $ vlt repo --target=":root > \*" ``` ## Options ### `--target=` Filter packages using DSS query syntax. When a single package matches, its repository opens in your browser. When multiple packages match, their URLs are listed. Terminal: ```bash # Open repo for a single package $ vlt repo --target="#express" # List repos for all direct dependencies $ vlt repo --target=":root > \*" # List repos for dev dependencies $ vlt repo --target=":type(dev)" ``` # vlt run-exec (/client/commands/run-exec) Usage: Terminal: ```bash $ vlt run-exec [command ...] ``` If the first argument is a defined script in package.json, then this is equivalent to `vlt run`. If not, then this is equivalent to `vlt exec`. ## Aliases ``` rx ``` # vlt run (/client/commands/run) Run a script defined in your `package.json` file. Scripts are the commands you define to automate common tasks like building, testing, or starting your application. ## Usage Terminal: ```bash vlt run