Skip to content

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 --help

Help 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 version

Default 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-project

What 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 --verbose

How 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 ./schemas are treated as directories and expanded to ./schemas/**/*.vdl automatically.
  • Standard glob patterns use double-star syntax (**) for recursive matching.
  • Files without a .vdl extension are skipped.
  • Duplicate matches are deduplicated, so the same file is never formatted twice.

Examples

Format every VDL file in the current project:

vdl format

Format a specific set of files with feedback:

vdl format ./api/*.vdl ./shared/*.vdl --verbose

Format everything inside a directory:

vdl format ./schemas

vdl generate

Run code generation from a vdl.config.vdl project.

vdl generate
vdl generate ./my-project
vdl generate --check

What It Does

The generation pipeline works like this:

  1. VDL finds and reads vdl.config.vdl.
  2. Pre-generation hooks run (if configured). The first failure stops the pipeline.
  3. Each configured plugin source is resolved:
  4. Local .js files are loaded directly.
  5. HTTPS URLs are fetched and cached.
  6. GitHub shorthands like owner/[email protected] resolve to a remote dist/index.js artifact, which is fetched and cached.
  7. Each plugin's configured .vdl schema is analyzed and converted into the Intermediate Representation (IR).
  8. All plugins execute concurrently in an embedded JavaScript runtime.
  9. Output file paths are validated to stay inside their configured outDir.
  10. Conflicting writes between plugins are detected and fail the run.
  11. Output directories are cleaned (default) or merged, and generated files are written.
  12. Post-generation hooks run (failures print warnings but do not roll back files).
  13. The vdl.lock file 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 --check

In 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.vdl

What 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-path

How 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.log

vdl version

Show VDL version information.

vdl version
vdl --version
vdl -v

The 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/.vdl

If 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 generate

Format In CI

vdl format --verbose
git diff --exit-code || echo "Unformatted VDL files detected"

Check Generation In CI

vdl generate --check

Explore 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 --check

Repeated Generation Workflow

# Format first, then generate
vdl format
vdl generate

Troubleshooting

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.vdl

vdl 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/cache

vdl 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/**/*.vdl

The language server is not responding

Check the LSP logs:

vdl lsp --log-path    # find the log file
cat <log-file-path>   # inspect it

Make sure your editor extension is configured to launch vdl lsp and not a different binary.