Brackets in a glob mean brackets
Brackets in a glob mean brackets
In a vx glob, [jt] matches one character, as in Turbo, Nx and your shell. A Next.js route folder like app/[id] needs escaping.
A vx.config.ts is TypeScript, so you share settings with an import. That removes globalDependencies and namedInputs from the schema.
A vx.config.ts is TypeScript. Share settings with an import, not a
special config key. Here is what bunx @vzn/vx-migrate writes from two
package.json scripts:
$ cat packages/ui/package.json{"name":"ui","scripts":{"build":"tsc -b","test":"vitest run"}}
$ bunx @vzn/vx-migrate from package.json scripts tasks 1 clean · 1 todo files packages/ui/vx.config.ts…$ cat packages/ui/vx.config.tsimport type { ProjectConfig } from '@vzn/vx/config'
export default { tasks: { // TODO(vx-migrate): cache: add `inputs: { files: ['src/**'] }, outputs: { files: ['dist/**', 'tsconfig.tsbuildinfo'] }, cache: true` with this package's real inputs and outputs — … build: { // inputs: { files: ['src/**'] }, outputs: { files: ['dist/**', 'tsconfig.tsbuildinfo'] }, cache: true, exec: { command: 'tsc -b', }, dependsOn: ['^build'], }, test: { exec: { command: 'vitest run', }, dependsOn: ['build'], }, },} satisfies ProjectConfigEach script became a task with the same command. The tool suggests inputs and outputs in a comment, and doesn’t guess them.
vx-migrate 69617eb · 2026-10-23
satisfies ProjectConfig gives autocomplete and type checks with no
runtime import. defineProject works too.
A shared preset is a file:
// vx-preset.ts (workspace root)export const lib = (entry: string) => ({ build: { exec: { command: `tsup ${entry}` }, inputs: { files: ['src/**', 'tsup.config.ts'] }, outputs: { files: ['dist/**'] }, cache: true, },})import type { ProjectConfig } from '@vzn/vx/config'import { lib } from '../../vx-preset.ts'export default { tasks: { ...lib('src/index.ts') } } satisfies ProjectConfigThe key hashes the config after it runs.
Edit vx-preset.ts, run vx lock, and every task that uses it gets a
new key.
No list of global dependencies to keep up to date: the import is the dependency.
| JSON configs need | In a TypeScript module |
|---|---|
globalDependencies |
the import |
namedInputs |
a constant |
targetDefaults |
a function returning a task |
extends |
...spread |
Your compiler checks it, your editor refactors it.
A config can’t read another project. Globs stay inside the project
folder, and ../shared/** is an error. inputs.workspaceFiles is the
one exception, for files at the workspace root.
A config may read process.env, the clock or the network, but only
once, when vx lock runs it. No run runs the
config again.
bunx @vzn/vx-migrate also reads turbo.json or an Nx graph. A
globalDependencies list becomes a preset file and its import. Schema:
Configuration schema.
More at vznjs.github.io/vx.