CLI Commands
Overview
The vdl CLI is the primary way to interact with VDL projects. It covers the full lifecycle: creating a project, writing and formatting schemas, generating code through plugins, compiling to inspect the intermediate representation, and running the language server for editor integration.
If you have not installed VDL yet, start with the installation guide.
Quick Reference
| Command | Purpose |
|---|---|
vdl init | Create a new VDL project with schema and config |
vdl format | Format .vdl files in place |
vdl generate | Run code generation from vdl.config.vdl |
vdl compile | Compile a .vdl file and print its IR as JSON |
vdl lsp | Start the VDL language server |
vdl version | Show VDL version information |
Global Behavior
A few things work everywhere, no matter which subcommand you use.
Help
Every command supports --help and -h:
vdl --help
vdl init --help
vdl generate --helpHelp output includes the VDL logo plus a description of the command and its flags.
Version
Use --version, -v, or the version subcommand to see the installed VDL version:
vdl --version
vdl versionDefault Output
Running vdl with no subcommand shows the VDL logo and version.
vdl init
Initialize a new VDL project in a directory.
vdl init
vdl init ./my-projectWhat It Creates
Two files are written into the target directory:
| File | Purpose |
|---|---|
schema.vdl | A sample schema with types, constants, and RPCs |
vdl.config.vdl | A commented config file ready for code generation |
The sample config includes commented-out plugin examples so you can uncomment the ones you need or add more as needed.
Arguments
| Argument | Required | Description |
|---|---|---|
path | no | Target directory. Defaults to the current directory (.). |
vdl format
Format .vdl files in place.
vdl format
vdl format ./schemas/**/*.vdl
vdl format ./schemas ./other
vdl format --verboseHow It Works
The formatter uses VDL's own lexer and parser to normalize whitespace, indentation, inline spacing, and blank lines so every file follows a consistent style. Files are overwritten in place.
Arguments
| Argument | Required | Description |
|---|---|---|
patterns | no | Glob patterns or directory paths. Defaults to ./**/*.vdl. |
--verbose | no | Print each file path as it is formatted. |
Pattern Behavior
- Plain paths like
./schemasare treated as directories and expanded to./schemas/**/*.vdlautomatically. - Standard glob patterns use double-star syntax (
**) for recursive matching. - Files without a
.vdlextension are skipped. - Duplicate matches are deduplicated, so the same file is never formatted twice.
Examples
Format every VDL file in the current project:
vdl formatFormat a specific set of files with feedback:
vdl format ./api/*.vdl ./shared/*.vdl --verboseFormat everything inside a directory:
vdl format ./schemasvdl generate
Run code generation from a vdl.config.vdl project.
vdl generate
vdl generate ./my-project
vdl generate --checkWhat It Does
The generation pipeline works like this:
- VDL finds and reads
vdl.config.vdl. - Pre-generation hooks run (if configured). The first failure stops the pipeline.
- Each configured plugin source is resolved:
- Local
.jsfiles are loaded directly. - HTTPS URLs are fetched and cached.
- GitHub shorthands like
owner/[email protected]resolve to a remotedist/index.jsartifact, which is fetched and cached.
- Local
- Each plugin's configured
.vdlschema is analyzed and converted into the Intermediate Representation (IR). - All plugins execute concurrently in an embedded JavaScript runtime.
- Output file paths are validated to stay inside their configured
outDir. - Conflicting writes between plugins are detected and fail the run.
- Output directories are cleaned (default) or merged, and generated files are written.
- Post-generation hooks run (failures print warnings but do not roll back files).
- The
vdl.lockfile is updated with remote plugin hashes.
Arguments
| Argument | Required | Description |
|---|---|---|
path | no | Directory or path to vdl.config.vdl. Defaults to . (cwd). |
--check | no | Run the full pipeline but skip writing output files. Useful for CI. |
Config File Discovery
When path points to a directory, VDL looks for a file named exactly vdl.config.vdl inside it. When path points directly to a file, that file is used. The config file must declare a const config with the generation settings.
For all configuration options, see the project configuration guide.
--check Mode
Use --check in CI to verify that generation would succeed without producing side effects:
vdl generate --checkIn check mode, VDL runs the full pipeline—hooks, plugin resolution, schema analysis, plugin execution, and output validation—but skips writing files, updating vdl.lock and executing post generation hooks. If the pipeline fails, the command exits with a non-zero code, making it suitable for linting and CI workflows.
Lock File
Remote plugin artifacts are cached and their content hashes are recorded in vdl.lock. Commit this file when your project depends on remote plugins. VDL uses it to detect unexpected changes in cached plugins.
vdl compile
Compile a .vdl file and print its Intermediate Representation (IR) as formatted JSON to stdout.
vdl compile ./schema.vdlWhat It Produces
The IR is a machine-readable description of everything VDL understands about your schema: types, enums, constants, annotations, documentation, and relationships. It is the same IR that plugins receive as input.ir.
Arguments
| Argument | Required | Description |
|---|---|---|
file | yes | Path to the .vdl file to compile. |
Use Cases
Inspect what your schema looks like after analysis, before generation.
Debug why a plugin produces unexpected output.
Pipe the IR into custom tooling:
vdl compile ./schema.vdl | jq '.types | length' vdl compile ./schema.vdl > schema-ir.json
Error Handling
If the schema has errors, diagnostics are printed to stderr and the command exits with code 1. No partial JSON is emitted.
vdl lsp
Start the VDL language server.
vdl lsp
vdl lsp --log-pathHow It Works
The language server speaks the Language Server Protocol over stdin and stdout. It provides editor features for .vdl files:
- Go-to-definition
- Hover information
- Find references
- Rename
- Completions
- Document symbols
- Document links
You typically do not run vdl lsp directly. Your editor plugin starts it and communicates with it over stdio. See the VS Code extension or Neovim setup for editor-specific instructions.
Arguments
| Argument | Required | Description |
|---|---|---|
--log-path | no | Print the path to the LSP log file instead of starting the server. |
Log Files
The LSP writes detailed diagnostic logs to a file under the VDL logs directory (~/.vdl/logs/ by default). Use --log-path to find the log file location, then inspect it when debugging editor behavior.
vdl lsp --log-path
# /home/you/.vdl/logs/vdl-lsp.log
cat /home/you/.vdl/logs/vdl-lsp.logvdl version
Show VDL version information.
vdl version
vdl --version
vdl -vThe output includes the VDL logo, version number, and links to the repository.
The VDL Home Directory
VDL stores caches and logs under a home directory outside your project.
Location
By default, the VDL home directory is ~/.vdl. You can override it with the VDL_HOME environment variable:
export VDL_HOME=/custom/path/.vdlIf no user home directory is available, VDL falls back to your system temp directory.
Contents
| Directory | Purpose |
|---|---|
cache/ | Cached remote plugin artifacts for reproducibility |
logs/ | Log files written by the language server |
Environment Variables
| Variable | Purpose |
|---|---|
VDL_HOME | Override the VDL home directory (default: ~/.vdl). |
VDL_INSECURE_ALLOW_HTTP | Allow http:// URLs for local plugin development. Set to true. |
VDL_SKIP_HOST_HOOKS | Skip pre-generation and post-generation hooks. Set to true. |
VDL_CLOUD | Skip host hooks (for cloud CI environments where shell hooks are not supported). |
Common Workflows
Start A New Project
vdl init ./my-service
cd ./my-service
# Edit schema.vdl and vdl.config.vdl
vdl generateFormat In CI
vdl format --verbose
git diff --exit-code || echo "Unformatted VDL files detected"Check Generation In CI
vdl generate --checkExplore A Schema
# See how many types a schema has
vdl compile ./schema.vdl | jq '.types | length'
# List type names
vdl compile ./schema.vdl | jq '.types[].name'
# Inspect enum values
vdl compile ./schema.vdl | jq '.enums[] | {name, values: [.members[].name]}'Debug Plugin Behavior
# Compare the IR a plugin will receive
vdl compile ./schema.vdl > debug-ir.json
# Run generation in check mode
vdl generate --checkRepeated Generation Workflow
# Format first, then generate
vdl format
vdl generateTroubleshooting
vdl generate cannot find the config file
Make sure the file is named exactly vdl.config.vdl and that you are running the command from the correct directory. Pass an explicit path if needed:
vdl generate ./path/to/vdl.config.vdlvdl generate fails on a remote plugin
Check that the plugin version exists and that the repository is public (or configured with the correct remotes block). Remote plugins are cached under the VDL cache directory—clear it with:
rm -rf ~/.vdl/cachevdl format does not find any files
By default, vdl format looks for ./**/*.vdl. If your VDL files use a different extension or are in an unexpected location, pass explicit patterns:
vdl format ./my-schemas/**/*.vdlThe language server is not responding
Check the LSP logs:
vdl lsp --log-path # find the log file
cat <log-file-path> # inspect itMake sure your editor extension is configured to launch vdl lsp and not a different binary.