VOLT

VPM

The vpm command-line tool for the VOLT plugin registry, which packs, publishes, deprecates, searches and installs plugin bundles.

vpm is the command-line client of the VOLT plugin registry at https://registry.voltcloud.dev. You use it to publish a plugin's platform bundles, to deprecate a version, and to search, inspect and download packages into the local plugin cache. The marketplace in VOLT reads the same registry. Its source is VoltLabs-Research/vpm.

For how a plugin and its bundles are built, see Writing plugins.

Install

vpm needs Node.js 20 or later.

npm install -g @voltstack/vpm
vpm --version

This page documents the npm release, 1.0.2. The repository's main branch adds two commands, vpm version and vpm seal, and a check in vpm publish; run npm run build in a checkout to use them.

Sign in

vpm login

vpm login uses a device-code flow: it prints a URL and a code, opens the URL in your browser (pass --no-browser to skip that), and waits until you confirm the code there. It then stores the tokens and prints the account you signed in as.

CommandWhat it does
vpm login [--no-browser]Signs in with the device-code flow.
vpm whoamiPrints the account ID, email and username of the stored session.
vpm logout [--keep-remote]Revokes the session's refresh token on the console, unless --keep-remote, and deletes the stored credentials.

Credentials are kept in the operating system's keychain (service voltcloud, account default). When no keychain is available, or when VPM_NO_KEYRING is 1 or true, they go to $XDG_CONFIG_HOME/vpm/credentials (~/.config/vpm/credentials), readable only by you.

Personal access tokens

For CI, create a personal access token and pass it with --token to vpm publish and vpm deprecate:

vpm token create --label "GitHub Actions" --scope <scope>
vpm token list
vpm token revoke <id>
CommandOptions
vpm token create--label <label> (required), --scope <scope...> (one or more; read when omitted), --scope-mask <mask> (a numeric bitmask), --expires <iso> (an ISO 8601 timestamp). Prints the token once.
vpm token list, vpm token ls--json
vpm token revoke <id>

The plugin repositories' publish workflows set VPM_NO_KEYRING=1 and pass their token from the VPM_PUBLISH_TOKEN secret.

Package names and versions

A package is named @<username>/<name>. The username is lowercase letters, digits and dashes, starting with a letter or digit; the name may also contain dots and underscores. The registry answers 403 when your token may not publish under that username.

Commands that take a package accept a version after a second @:

FormMeaning
@voltlabs/opendxaThe latest dist-tag.
@voltlabs/opendxa@2.5.1That version.
@voltlabs/opendxa@latestA dist-tag.
@voltlabs/opendxa@^2.0.0The highest version that satisfies the semver range (vpm install only).

A version has one bundle per platform tag, such as linux-x86_64, darwin-arm64, windows-x86_64 or wasm-wasm32 (see Platforms and bundles). vpm install picks the tag of the machine it runs on: <system>-<machine>, with x64 written as x86_64.

The manifest: vpm.json

Every package has a vpm.json at its root. Commands that read it look in the given directory and then in each parent.

vpm.json
{
  "name": "@voltlabs/coordination-analysis",
  "version": "2.1.1",
  "kind": "workflow",
  "publisher": "voltlabs",
  "description": "Analyzes local atomic coordination by computing coordination numbers, the radial distribution function (RDF), and per-type-pair partial RDF histograms.",
  "license": "MIT",
  "homepage": "https://github.com/voltlabs-research/coordination-analysis",
  "repository": { "type": "git", "url": "https://github.com/voltlabs-research/coordination-analysis" },
  "entrypoints": { "binary": "coordination-analysis-plugin.zip", "workflow": "plugin.json" },
  "platforms": ["linux-x86_64", "darwin-arm64", "windows-x86_64", "wasm-wasm32"],
  "coretoolkit": "2.0.0",
  "files": ["plugin.json", "scripts", "bin", "lib"]
}
FieldRequiredDescription
nameyes@<username>/<name>.
versionyesThe version to publish. Keep it equal to the plugin.json modifier's version.
kindyesworkflow, engine or lib. Plugins are workflow; VOLT's marketplace searches only that kind.
publisheryesThe publisher's name, usually the username.
description, license, homepage, repository ({ type, url }), keywordsPackage metadata.
entrypoints{ binary?, workflow? }: the plugin's binary and workflow files.
platformsPlatform tags vpm publish requires a bundle for.
nodeTypes, voltsdk, coretoolkitFree-form metadata. coretoolkit records the CoreToolkit version the plugin targets.
filesWhat vpm pack puts in the tarball.

Commands

These options apply to every command:

OptionDescription
--registry <url>Registry URL. Default: VPM_REGISTRY, else https://registry.voltcloud.dev.
--console <url>Console URL, which handles sign-in and tokens. Default: VPM_CONSOLE, else https://server.console.voltcloud.dev.
--verboseVerbose logging.
-v, --versionPrint vpm's version.
-h, --helpHelp for vpm or for a command.

Discover

CommandOptionsWhat it does
vpm search <query>--kind <kind>, --page <n> (1), --page-size <n> (20), --jsonSearches the registry and prints each package with its latest version, kind, description and download counts.
vpm info <pkg>--jsonWithout a version: the package's kind, description, homepage, dist-tags, version count and downloads. With an exact version: when and by whom it was published, its size, SHA-256, platforms and deprecation.

Install

CommandOptionsWhat it does
vpm install <pkg>, vpm i--platform <tag>, --forceResolves the version, downloads the bundle for the platform and extracts it to the cache. Skips a version already installed unless --force. Fails, listing the platforms available, when the version has no bundle for yours. Warns when the version is deprecated.
vpm uninstall <pkg>, vpm rmRemoves one version, or every version when you give none.
vpm list, vpm ls--jsonLists the installed packages, versions and platforms.

The cache is VOLT_CACHE_DIR, else $XDG_CACHE_HOME/volt (~/.cache/volt). A bundle is extracted to plugins/<publisher>/<name>/<version>/<platform>/, and the files in its bin/ and scripts/ are made executable. For workflow packages, the version's manifest is also written to manifests/<username>/<name>.json. The Python SDK's plugin hub uses the same default directory and layout. Bundles may be gzip or Zstandard tarballs; vpm detects which.

Publish

CommandOptionsWhat it does
vpm init--name <@username/name> (required), --kind <kind> (lib), --publisher <publisher>, --description <description>Writes a vpm.json in the current directory, with version 0.1.0, license MIT and files: ["dist", "bin"]. Refuses to overwrite one.
vpm pack [dir]--out <file>Writes a gzip tarball of the package: vpm.json plus the entries of files that exist, or vpm.json, README.md, LICENSE, dist and bin when files is empty. The default name is <username>-<name>-<version>.tgz.
vpm publish [dir]--bundle <tag>=<path> (repeatable), --bundle-dir <dir>, --token <token>, --dry-runUploads the version with one bundle per platform tag.
vpm deprecate <pkg>@<version> <message>--token <token>Marks a published version as deprecated with a message, which vpm info and vpm install show.

vpm publish reads vpm.json from dir (the current directory by default) and collects the bundles:

  1. from --bundle <tag>=<path> options, if any;
  2. otherwise from --bundle-dir, or bundles/ next to vpm.json: every .tgz, .tar.gz or .tar.zst file, with the tag taken from the file name before its first dot (bundles/linux-x86_64.tar.zst).

When vpm.json lists platforms, every one of them needs a bundle; otherwise at least one bundle is required. The manifest, the package's README.md if it has one, and the bundles are uploaded in one request. --dry-run prints the version, the bundles with their sizes and whether a README was found, and uploads nothing; it still needs a token.

Registry answerMeaning
201Published. vpm prints the latest dist-tag.
401Bad or missing token.
403You may not publish under that username.
409The version already exists. Bump version.
422The manifest is invalid.

A typical CI publish, from the CoreToolkit workflow that builds C++ plugins:

vpm publish plugin --token "$VPM_PUBLISH_TOKEN" \
  --bundle linux-x86_64=artifacts/coordination-analysis-2.1.1-linux-x86_64.tar.zst \
  --bundle darwin-arm64=artifacts/coordination-analysis-2.1.1-darwin-arm64.tar.zst \
  --bundle windows-x86_64=artifacts/coordination-analysis-2.1.1-windows-x86_64.tar.zst \
  --bundle wasm-wasm32=artifacts/coordination-analysis-2.1.1-wasm-wasm32.tar.zst

Commands on the main branch

Built from the repository's main branch, vpm also has:

CommandOptionsWhat it does
vpm version [target]-C, --dir <path> (.), --checkSets version in vpm.json to major, minor, patch (a bump) or an explicit x.y.z, and writes the same version into the plugin.json modifier, changing only those strings. --check reports whether the two files agree, and exits with 1 when they do not.
vpm seal <bundle-dir...>--name <@publisher/plugin>Runs each built bundle's program with --describe and writes the option table into plugin.json as interface.params, with a checksum. It also checks that the flags the interface block binds exist. The name comes from vpm.json when you omit --name.

On that branch, vpm publish also refuses a bundle of a package that is not lib unless the bundle's plugin.json has an interface block (version 2) with a sealed interface.params.

Environment variables

VariableDefaultEffect
VPM_REGISTRYhttps://registry.voltcloud.devRegistry URL.
VPM_CONSOLEhttps://server.console.voltcloud.devConsole URL.
VOLT_CACHE_DIR$XDG_CACHE_HOME/voltPlugin cache.
VPM_NO_KEYRING1 or true stores credentials in a file instead of the keychain.
VPM_DEBUG1 prints stack traces with errors.

Registry API

vpm uses these endpoints, which other clients can use too:

EndpointReturns
GET /-/search?q=&kind=&page=&pageSize={ items, page, pageSize, total, facets }. facets counts the packages of each kind.
GET /packages/<username>/<name>The packument: fullName, kind, description, distTags, versions (each with its manifest, SHA-256, size, publish time and publisher, and platforms), downloads, readme.
GET /packages/<username>/<name>/<version>One version's metadata.
GET /packages/<username>/<name>/<version>/-/<platform>.tgzA 307 redirect to a signed download URL. With Accept: application/json, { sha256, sizeBytes, platform } instead. 404 when the version has no bundle for that platform.
PUT /packages/<username>/<name>Publishes a version: a multipart form with manifest (JSON), optional readme, and one file per platform tag. Needs a bearer token.
POST /packages/<username>/<name>/<version>/deprecate{ "reason": "…" }. Needs a bearer token.

The VOLT server calls the search and tarball endpoints when you browse the marketplace and install a plugin. It reads the registry URL from REGISTRY_URL, https://registry.voltcloud.dev when unset (see Configuration).

On this page