Vex package manager
Manifest-based Wave projects, Git and path dependencies, lockfiles, offline builds, and the wavec boundary.
Wave Foundation
Role
Vex is the package manager and build tool for Wave. It sits above wavec: Vex owns project structure and dependency resolution, while wavec owns compiler flags and the compilation pipeline.
Vex commands are manifest-based. Raw wavec flags are intentionally not accepted by vex build, vex check, or vex run.
Create a package
vex init
vex init --lib
An application uses src/main.wave; a library uses src/lib.wave. The package root contains:
my_project/
├── src/
│ └── main.wave
├── vex.ws
├── vex.lock
└── .vex/
└── deps/
vex.ws is the manifest. Vex does not use a .wson manifest extension.
{
name = "my_project",
version = 0.1.0,
lib = false,
description = "my_project Project",
author = "unknown",
license = "Unknown",
dependencies = []
}
Build commands
vex build [--target <triple>] [--release] [--dry-run] [--locked] [--offline]
vex check [--target <triple>] [--release] [--dry-run] [--locked] [--offline]
vex run [--target <triple>] [--release] [--dry-run] [--locked] [--offline] [-- <args...>]
Vex keeps this surface small. Use wavec directly when you need compiler-specific emit, linker, CPU, ABI, or debug controls. Set VEX_WAVEC=/path/to/wavec when Vex must use a specific compiler binary.
Progress stages such as Resolving, Fetching, Compiling, Checking, Running, and Finished are written to stderr. Program output remains on stdout.
Git-first dependencies
Vex resolves dependencies from local paths or Git URLs. Each dependency uses exactly one source form.
{
name = "app",
version = 0.1.0,
dependencies = [
{ name = "local_math", path = "../local_math" },
{ name = "remote_math", git = "https://github.com/example/math.git", tag = "v0.1.0" }
]
}
A Git dependency may select at most one of branch, tag, or rev. Every dependency root must contain its own vex.ws. Vex resolves dependency manifests recursively, rejects conflicting package identities, and stores managed Git checkouts under .vex/deps/<name>.
Lockfile contract
The schema-v2 vex.lock records the complete transitive graph and exact Git commits. Commit it with the manifest. Given the same manifest and valid lockfile, Vex selects the same dependency graph rather than following a branch or tag again.
Commands that need dependencies resolve them automatically, or you can prepare the graph explicitly:
vex fetch
vex update
vex update math shared_core
vex update refreshes all Git packages, or only the named packages and their affected transitive graph. Unrelated locked packages retain their selected commits.
Locked and offline workflows
--locked forbids creating or changing vex.lock. It fails when the file is missing, uses an unrecognized schema, or no longer matches the manifest graph. It may still fetch a commit already pinned by the lockfile.
--offline prohibits Git network operations. Required checkouts and commits must already exist locally.
vex fetch --locked
vex build --locked --offline
This pair is the strict CI workflow: fetch the exact locked commits while network access is allowed, then compile without network access or lockfile changes. A dry run never fetches dependencies or rewrites the lockfile.
Compiler setup and inspection
vex info
vex setup wavec
vex setup wavec --version <version>
vex --version
Vex validates the JSON build plan returned by wavec --dry-run before compiling. If their schema versions do not match, Vex reports a compatibility error without starting the build.