- Published on
Query Powered vlt Commands
- Authors
- Name
- Luke Karrys
- Bluesky@lukekarrys.com
--scope
support for commands like vlr
, vlx
, and vlt pkg
Target your full graph with Running scripts across a large project just got a lot more precise. vlr
(vlt run
), vlx
(vlt exec
) and vlt pkg
now support the full Dependency Selector Syntax via the --scope
flag. You can now target exactly the dependencies you want to take actions against: specific workspaces, prod or dev-only deps, git deps with a prepare
script, and more.
If you're familiar with CSS selectors, you'll feel right at home. The --scope
flag accepts the complete Dependency Selector Syntax.
tl;dr
vlr --scope="<selector>" <script>
runs<script>
in every package matched by<selector>
.vlx --scope="<selector>" <command>
executes<command>
in every package matched by<selector>
.vlt pkg get [name] --scope="<selector>"
will get package information for all packages matched by<selector>
.- Works great with workspaces as well as any and all other dependencies in your project (including transitives).
Why this is useful
As your projects grow, and especially as monorepos become more and more popular, developers need smarter tools to control the execution of tasks across their dependency graphs. Making our commands configurable using the Dependency Selector Syntax allows developers and teams to:
- Run scripts only where there's compatibility: e.g., test workspaces whose
engines.node
support is for a specific version. - Target non-workspace dependencies: e.g. running
postinstall
scripts for select transitive deps who you may have been previously blocked and need to rehydrate or diagnose environment-specific behavior. - Target by metadata: e.g. limit the execution of a tool against just
git
,:prod
,:dev
, specifically named, pathed, or security-related dependencies.
How it works
vlt
evaluates the selector passed with --scope
against your project's dependency graph. Any matching dependency will be returned and the corresponding command/action will be taken (ex. script execution for vlr
, binary execution for vlx
, package.json
value fetching for vlt pkg get
etc.). Selectors work to match configured workspaces, direct dependencies and even transitive dependencies.
The Dependency Selector Syntax supports:
- Attribute selectors like
[name]
,[name=react]
,[license^=MIT]
- Property selectors like
:attr(engines,[node^=20])
or:attr(deeply,nested,prop,[name=value])
- Combinators like
>
(direct deps) and the descendant combinator (all transitive deps) - Pseudo Classes like
:has(...)
,:is(...)
,:attr(...)
,:semver(...)
,:path("...")
,:type(git|file|workspace|...)
- Pseudo States like
:workspace
,:project
,:prod
,:dev
,:peer
,:private
For the full reference, check the docs: Dependency Selector Syntax.
Examples
Run tests for workspaces that support a specific Node version
$ vlr --scope=":workspace:semver($(node -v), satisfies, :attr(engines, [node]))" test
> app-web ok
vitest run
> api-server test
node --test
postinstall
script for all production dependencies that declare one
Run the $ vlr --scope=":prod:attr(scripts, [postinstall])" postinstall
> esbuild postinstall
node install.js
> sharp postinstall
node install/libvips
prepare
script for any git dependencies
Run the $ vlr --scope=":type(git):attr(scripts, [prepare])" prepare
> my-git-dep prepare
tshy build
> another-git-dep prepare
tsc -b
app-
Lint workspaces whose names start with $ vlr --scope=":workspace[name^=app-]" lint
> app-shell lint
eslint .
> app-admin lint
eslint .
test
scripts of workspaces which defined them in the packages/**
directory
Run the $ vlr --scope=':path("packages/**"):attr(scripts, [test])' test
> packages/foo test
vitest run
> packages/bar test
vitest run
Run the build script for specifically named workspaces
$ vlr --scope=":workspace:is([name=web],[name=docs],[name=api])" build
> web build
next build
> docs build
static-site build
> api build
tsc -b && node scripts/build.js
tsc
for workspaces that have typescript
as a dev dependency
Execute $ vlx --scope ":workspace:attr(devDependencies, [typescript])" tsc --noEmit
> app-web
tsc --noEmit
> app-server
tsc --noEmit
vercel
for any projects found in the ./apps
directory
Execute $ vlx --scope=':path("apps/*")' vercel
> apps/web
vercel
> apps/api
vercel
package.json
fields with vlt pkg
Inspect Use vlt pkg get
to fetch a single value and vlt pkg pick
to fetch multiple values (supports dot-prop paths). These commands work with --scope
, so you can query fields across workspaces or any part of your dependency graph. See docs: vlt pkg.
$ vlt pkg get name --scope=":workspace"
app-web
app-server
$ vlt pkg get engines.node --scope=":workspace:attr(engines, [node])"
^22 || ^24
^18 || ^20
$ vlt pkg pick name version repository.url --scope=":is([name=web],[name=api])"
[
{
"name": "web",
"version": "1.0.0",
"repository": {
"url": "https://github.com/vltpkg/web"
}
},
{
"name": "api",
"version": "2.0.0",
"repository": {
"url": "https://github.com/vltpkg/api"
}
}
]
$ vlt pkg pick name scripts.test --scope=':path("packages/**"):attr(scripts, [test])'
[
{
"name": "app-web",
"scripts": {
"test": "vitest run"
}
},
{
"name": "app-server",
"scripts": {
"test": "node --test"
}
}
]
Learn more
The Dependency Selector Syntax is powerful, expressive and improving all the time. You can read the complete reference documentation here.
If you have any questions, comments or feedback about the selector syntax, command support for --scope
, or anything vlt
-related, come join us on Discord or open an issue on GitHub.