Skip to content
ClientRegistries

Working with Named Registries

The vlt client supports working with multiple registries in a variety of ways.

For a conceptual overview, see Named Registries.

Setting the Registry

vlt has no default registry. Before running any command that resolves or fetches packages, you have to say which registry to use. Commands that need one and do not have one fail with a config error:

Config Error: Missing registry configuration.
vlt has no default registry. Run `vlt setup` to get configured.
See https://docs.vlt.sh/cli for other ways to set a registry.

The guided path is vlt setup, which configures your account’s registry aliases so that vlt install <pkg> and vlx work out of the box.

There are three ways to configure the registry directly, in increasing order of precedence:

  1. A vlt.json file, either in your project or in your user config directory. Either write it by hand:

    {
    "config": {
    "registry": "https://registry.npmjs.org/"
    }
    }

    or set it with the CLI:

    Terminal window
    vlt config set registry=https://registry.npmjs.org/
  2. The VLT_REGISTRY environment variable, which is handy in CI:

    Terminal window
    VLT_REGISTRY=https://registry.npmjs.org/ vlt install
  3. The --registry flag, for a single command:

    Terminal window
    vlt install --registry=https://registry.npmjs.org/

Bootstrapping with vlt login

If you are starting from nothing, vlt login is the guided path. It authenticates against the registry you give it and then writes that registry into your project’s vlt.json, so subsequent commands are already configured:

Terminal window
vlt login --registry=https://registry.vlt.io/myorg/

There can be only one registry configured this way, and it is used as the fallback for all package registry resolutions. Normally, if an internal registry is used for all fetches, it effectively must serve all packages, meaning it has to be a caching proxy, as well as the repository for any of your organization’s internal code.

Note that the built-in registry aliases (gh:, jsr:) and the @jsr scope mapping still have built-in URLs. The npm: alias, however, is no longer built-in — it has no baked-in URL and must be configured (see The npm: alias below). All built-in aliases are user/service-overridable.

Bare specs and --default-registry-alias

A bare spec — a dependency written without a registry protocol, like vlt install foo or "foo": "^1.0.0" in package.json, as well as any transitive dependency that omits a registry — resolves its registry in the following order of precedence:

  1. a matching scoped-registries entry (for scoped names)
  2. the registry scalar (--registry / VLT_REGISTRY)
  3. registries[<default-registry-alias>]

--default-registry-alias defaults to npm, so by default a bare foo resolves through your configured registries.npm. Change it to route bare specs (including transitive deps without an explicit registry) through a different alias:

Terminal window
vlt config set default-registry-alias=main

Because the npm alias has no built-in URL, a fresh, unconfigured project cannot resolve bare specs until you configure one — the guided way to do that is vlt setup.

Getting started with vlt setup

vlt setup is the onboarding wizard for a vlt.io account. Sign up or log in at https://www.vlt.io first, then run:

Terminal window
vlt setup

It authenticates against your account and writes the two account registry aliases into your user vlt.json:

{
"registries": {
"npm": "https://registry.vlt.io/<account>/npm/",
"main": "https://registry.vlt.io/<account>/main/"
}
}
  • npm is the default bare-spec alias, so vlt install <pkg> and vlx work immediately.
  • main is your account’s primary private registry (named main: to match the service).

The wizard then loops to let you add any additional custom aliases (for partner or team registries), optionally authenticating against each. To run it unattended (for example in CI or a setup script):

Terminal window
vlt setup my-account --yes --registries team=https://registry.example.com/

Pass --config=project to write to the project’s vlt.json instead of your user config.

Targeting a specific registry

Account and authentication commands (whoami, logout, login, token, access, publish, unpublish, deprecate, dist-tag, profile, ping) need to know which registry to act against. When you have more than one configured, scope a command to a single alias with vlt registry <alias> <command>:

Terminal window
# act against the registry configured as `main`
vlt registry main whoami
# list tokens for the `npm` registry
vlt registry npm token list

You can also run the top-level command directly (vlt whoami). Either way, when the target is ambiguous vlt prompts you to pick a registry on an interactive terminal, and otherwise falls back to --default-registry-alias. A --registry=<url> on the command line always takes precedence.

Named Scope Registries (npm Compatibility)

Like the npm client, the vlt client allows you to map a given scope to a specific registry.

For example, you could make it so that all packages whose names start with @mycompany/... are served from your internal registry.

This can be a convenient way to make only certain packages come from internal private registries, while all the other packages come from a default public registry, meaning that you do not need to proxy everything.

To do this in vlt, use the scoped-registries configuration.

Terminal window
vlt config set scoped-registries=@mycompany=https://registry.local/

When you do this in your project, you will see that it adds the option to a vlt.json file in your project root.

Terminal window
$ cat vlt.json
{
"scoped-registries": {
"@mycompany": "https://registry.local/",
}
}

If you run this command multiple times, you can set different registries for various different scopes.

Registry Aliases

Another way to provide very explicit registry behavior is to use a registry alias.

Similar to how a named package can be aliased to another name and version, the vlt client allows you to indicate that you want a given package to come from a specific named registry.

First, create a registry alias by adding an entry to the registries config:

Terminal window
$ vlt config set registries=bar=https://registry.example.com/

This will add the appropriate entry to the vlt.json file:

Terminal window
$ cat vlt.json
{
"registries": {
"bar": "https://registry.example.com/"
}
}

Now, if you have this in your package.json file:

{
"dependencies": {
"bloo": "bar:[email protected]"
}
}

then the bloo package will always come from my defined bar: registry alias.

You can also of course use this to install packages from a known registry by alias on the command line:

Terminal window
$ vlt install bar:[email protected]

Special Aliases:

npm:

The npm: alias is the default bare-spec alias (see --default-registry-alias), but it has no built-in URL — you must configure it. This is because real traffic is expected to flow through a per-account vlt mirror whose URL isn’t known ahead of time.

The easiest way to configure it is vlt setup, which points registries.npm at your account’s mirror. You can also set it directly, for example to the public npm registry or an internal caching proxy:

Terminal window
vlt config set registries=npm=https://registry.npmjs.org/

Until npm is configured, bare specs like [email protected] and foo@npm:[email protected] have no registry to resolve against and will fail with the missing-registry error.

jsr:

The jsr: alias is a special alias that allow you to install packages from JavaScript Registry (jsr).

For example, you can install a package from the JSR registry like this:

Terminal window
$ vlt install jsr:@am/[email protected]

The jsr: alias has a built-in URL (https://npm.jsr.io/). Unlike a bare spec, it is resolved from its own alias map and is not affected by the registry scalar; to point it at a different host (such as a caching proxy in your organization’s network), override it with --jsr-registries:

Terminal window
vlt config set jsr-registries=jsr=https://jsr.local/

gh:

The gh: alias is a special alias that allows you to install packages from GitHub Package Registry.

For example, you can install a package from the GitHub package registry like this:

Terminal window
$ vlt install gh:@octocat/[email protected]

This will fetch the package from https://npm.pkg.github.com/ instead of the registry a bare spec would use. Like jsr:, the built-in gh: URL can be overridden via --registries.

Registry Consistency

There is a common question that is brought up when discussing the use of multiple registries, which vlt handles properly.

The concern is this:

Consider a package foo that you wish to fetch from the registry https://registry.foo.com/. This package foo depends on a package bar, also in that same registry, with the expectation that you’re fetching all of your packages from that registry, and so, it does not use any kind of prefix or specifier to indicate where it can be found.

That is, inside of the foo package’s package.json file, it contains this:

{
"name": "foo",
"version": "1.2.3",
"dependencies": {
"bar": "1.x"
}
}

On the public npm registry a different package by the name of bar exists, which is not compatible with foo’s usage.

So the concern is, if I do vlt install foo:[email protected], then it’ll fetch the foo package from the foo registry just fine. So far so good. However, then it will attempt to resolve the dependencies of the foo package, [email protected]. Because [email protected] does not also have a registry specifier, you might think that it will attempt to fetch from the public npm registry, which would be wrong!

The vlt client handles this by defaulting every dependency to the same registry where its dependent came from, when resolving the dependency graph, so they are safe to use in your applications, without fear that the dependencies will be fetched from the incorrect registry later down the resolution process.

Caution: Registry Aliases Are Not For Published Packages

Except for the npm: alias, it is generally not advised to use registry alias specifiers in published package dependencies.

At the time of this writing, only the vlt client supports arbitrary registry alias specifiers, and there is no broad consensus on which aliases point to which registries, or even any clear understanding about how such consensus might be found.

While they are perfectly safe to use within your own application, they should not be used in library code that you publish for wider consumption by the open source community.

Registry URL Specifiers

The vlt client supports registry: Dependency Specifiers. This means that, even without a configured alias, the registry can always be specified explicitly by URL within any context where a dependency is defined.

In fact, this is what registry aliases desugar to, and they have the exact same behavior.

For example, like in the foo:foo@1 example above, we could have also done:

Terminal window
$ vlt install "foo@registry:https://foo.com#foo@1"

While registry: specifiers are quite verbose and ugly, they are also very explicit and can only be interpreted a single way, without requiring any special configuration.

While broad consensus on configuration would not be required in this case, it is still not recommended to use them in published library code, because currently only the vlt client has support for this type of specifier.

We hope that other package managers add support for registry: specifiers in the future. If they do, then it will be safe to use them in published open source library code as well.

See Also

If you are using custom registries, you are very likely going to be interested in setting up Authentication at some point.