- Published on
Scoped Releases: New version, pack, and publish commands
- Authors
 - Name
- Luke Karrys
- Bluesky@lukekarrys.com
 
 
Manage releases across workspaces with --scope: version, pack, publish
Releasing changes in a growing project or monorepo shouldn't require bespoke scripts. vlt now supports graph-aware release operations with version, vlt pack, and vlt publish. Each command supports the full Dependency Selector Syntax via --scope. You can bump versions, create tarballs, and publish only the workspaces you intend. We also added --publish-directory to both pack and publish so you can bundle into a directory (e.g. dist/) before packaging or publishing.
tl;dr
- vlt version <inc>with- --scope="<selector>"bumps the version in matched packages.
- vlt pack --scope="<selector>"creates tarballs in each matched package.
- vlt publish --scope="<selector>"publishes matched workspaces.
- vlt packand- vlt publishuse- --publish-directory=<path>to publish from a different output directory.
- --scopeaccepts the full selector syntax and works great with workspaces.
Why this is useful
- Target only what matters: release a subset of workspaces (e.g., apps, services) without touching the rest.
- Bundle first, then ship: build to a different directory during prepack, then pack/publish only the artifacts using--publish-directory.
- Safer, repeatable flows: version, then pack to verify artifacts, then publish. All of this is driven by selectors.
How it works
vlt evaluates the selector passed with --scope against your project's dependency graph. For version, pack, and publish, matched items are typically your configured workspaces. version applies the increment to each matched workspace. pack produces npm-compatible tarballs, and publish sends packages to your registry. Both pack and publish respect --publish-directory to run from a different working directory.
For the complete selector reference, see the docs: Dependency Selector Syntax.
Examples
Version a package by name and all its workspace dependencies
$ vlt version patch --scope="#package-a, #package-a :workspace"
package-a: v1.4.1
package-b: v1.2.1 # dependent on package-a
package-c: v3.2.1 # dependent on package-b
Version a subset of workspaces that start with app-
$ vlt version patch --scope=":workspace[name^=app-]"
app-web: v1.2.4
app-admin: v0.9.1
Version prereleases for apps found in ./apps
$ vlt version prerelease --scope=':path("apps/*")'
apps/web: v1.4.1-pre.0
apps/api: v2.8.4-pre.0
apps/admin: v0.9.1-pre.0
Version and pack workspaces by name
Use this flow to validate artifacts before publishing.
$ vlt version minor --scope=':workspace:is(#web, #api)'
web: v1.4.0
api: v2.9.0
$ vlt pack --scope=':workspace:is(#web, #api)'
๐ฆ Package: [email protected]
๐ File: web-1.4.0.tgz
๐ 52 Files
... (truncated)
๐ Package Size: 1.2 MB
๐ Unpacked Size: 1.1 MB
๐ Shasum: ...
๐ Integrity: ...
๐ฆ Package: [email protected]
๐ File: api-2.9.0.tgz
๐ 108 Files
... (truncated)
๐ Package Size: 2.9 MB
๐ Unpacked Size: 2.8 MB
๐ Shasum: ...
๐ Integrity: ...
Version and publish all public workspaces
$ vlt version patch ":workspace:not(:private)"
app-web: v1.4.1
app-server: v2.9.1
$ vlt publish ":workspace:not(:private)" --tag=latest
๐ฆ Package: [email protected]
๐ท๏ธ Tag: latest
๐ก Registry: https://registry.npmjs.org/
๐ 52 Files
... (truncated)
๐ Package Size: 1.2 MB
๐ Unpacked Size: 1.1 MB
๐ Shasum: ...
๐ Integrity: ...
๐ฆ Package: [email protected]
๐ File: app-server-2.9.1.tgz
๐ 108 Files
... (truncated)
๐ Package Size: 2.9 MB
๐ Unpacked Size: 2.8 MB
๐ Shasum: ...
๐ Integrity: ...
Build to --publish-directory during prepack and then pack and publish
Bundle to dist/ during prepack, then package/publish from that directory. This allows you to publish a set of files that is completely different than what is in the source directory. This is helpful when bundling or compiling your project before publishing.
package.json:
{
  "name": "app-web",
  "version": "1.4.1",
  "private": false,
  "scripts": {
    "prepack": "vite build && cp package.json dist/ && cp README.md dist/"
  }
}
Pack from dist/:
$ vlt pack --scope="#app-web" --publish-directory=dist
Publish from dist/:
$ vlt publish --scope="#app-web" --publish-directory=dist --tag=latest
Publish all packages that have a prepack script
You can combine this with selectors to publish many packages that follow the same build layout.
$ vlt publish --scope=':workspace:path("packages/*"):attr(scripts, [prepack])' --publish-directory=dist --tag=latest
๐ฆ Package: @org/[email protected]
๐ File: @org/foo-0.7.0.tgz
๐ 52 Files
... (truncated)
๐ Package Size: 1.2 MB
๐ Unpacked Size: 1.1 MB
๐ Shasum: ...
๐ Integrity: ...
๐ฆ Package: @org/[email protected]
๐ File: @org/bar-3.2.1.tgz
๐ 108 Files
... (truncated)
๐ Package Size: 2.9 MB
๐ Unpacked Size: 2.8 MB
๐ Shasum: ...
๐ Integrity: ...
Learn more
Have questions or feedback about --scope, --publish-directory, or releasing with vlt? Join us on Discord or open an issue on GitHub.
