Tools
Varyk owns the front end, the Rust emitter, and diagnostics. Everything else comes from Cargo and rustc: the manifest, dependency resolution, the registry, lockfiles, features, workspaces, caching, cross-compilation, code generation, optimization, and the full borrow check. There is no separate package registry, package manifest, or build system: a Varyk package is a Cargo package, and varyk builds it with cargo.
The varyk command
varyk check [file.vr] check for errors
varyk build [file.vr] [--release] [--emit-rust] generate and build; print the executable's path
varyk run [file.vr] [--release] [-- args...] build, then run with the given arguments
varyk test [file.vr] build the tests and run them
varyk init [dir] [--lib] write a new package
varyk add [cargo add args] run cargo add in the package
varyk add http sql mongo add the official packages as `http`, `sql`, and `mongo`
varyk add sql [cargo add args] add one official package under its short name (`http`, `sql`, `mongo`)
varyk publish [--assemble-only] [-- cargo args] check, assemble a plain Rust crate, and run
cargo publish there
varyk lsp the language server your editor runs (see Editors)
Without a file, each command works on the package found by looking for Cargo.toml in the current directory and then upward. --release builds with optimizations. --emit-rust prints every generated file, Cargo.toml and the Rust files, each after a line naming it, and then builds. Every command accepts --message-format=json, which prints errors, and the warnings rustc gives about your .rs modules, as JSON on standard output, one object per line, with file, line, and byte column for the error, each label, and the fix-it; under varyk run and varyk test, whose standard output is the program's or the test runner's own, they go to standard error instead. check is the fast loop and must stay fast; it runs cargo only to learn which packages the build uses, when a package lists a dependency besides varyk-std. varyk test builds the program with its #[test] functions and runs them, showing the Rust test runner's report; varyk build and varyk run leave the tests out. Generated Rust goes under target/varyk/, never next to your .vr files. An error or warning rustc reports in a .rs module you wrote is shown at your file and line, unchanged; a rustc error in the code Varyk generated, which should not happen, is reported as V0900 at the Varyk line responsible. Another exception is a started task that holds a value from a .rs module that cannot move to another thread: that is your Rust code's choice, reported as V0901 naming the Rust type.
Packages
A package is a directory with a Cargo.toml and a src/main.vr (a program) or src/lib.vr (a library). Cargo.toml is the manifest, as in any Rust project, and needs edition = "2024"; [package.metadata.varyk] is reserved for Varyk and has no keys yet. [dependencies] names the Varyk packages the package uses and the Rust crates its .rs modules call, and a Cargo.lock beside Cargo.toml is used when building, so Varyk builds the same crate versions cargo would. Cargo.toml names the package's root as cargo's target, [[bin]] with path = "src/main.vr" or [lib] with path = "src/lib.vr", so cargo's tools, such as cargo add, cargo update, and cargo tree, read the package; without it, varyk check reports V0406 with the lines to add.
Since milestone 5b2, Varyk code uses a Varyk package by its key in [dependencies], with each - read as _: with units = { path = "../units" }, units::length::add(a, b) calls into the package units, and packages may use packages, to any depth. A dependency is a Varyk package when its folder has src/lib.vr, whether it comes from a path, a registry, or git. Varyk code never names a Rust crate: a .rs file in the package, a facade, wraps what the program needs, and Varyk imports that. Since milestone 5b3, a facade function can read its result into whatever type the caller names, take any number of values after its other arguments, take text written in the program and nothing else (V0217), and return Varyk's own Error, so a package such as varyk-sql keeps its Rust in a facade and a program that uses it writes no Rust; since milestone 5b4, it can also take any value JSON can write (&T: Serialize) and return an Error it makes itself. The reference shows the shapes. One package is known to the compiler by name: in a build that holds varyk-http, the route and hook calls on its App are the compiler's own, and varyk check checks each route against its handler (see HTTP). A library's root can give its items shorter names with pub use, so its users write shelf::item(3) for shelf::store::item(3). The reference has the rules: what a package gives you, why each package sees only the packages its own Cargo.toml lists (V0115), and why a Varyk package reached any other way, through [dev-dependencies], as an optional dependency, or through a Rust crate, is refused (V0401).
A Varyk package is built by varyk and only by varyk. varyk asks cargo for the package graph (cargo metadata; V0405 when cargo cannot work it out), checks every Varyk package of the build from its .vr sources, and builds each as a crate of its own under target/varyk/packages/, from the Rust generated from its .vr files and its own .rs modules only. Under varyk build, varyk run, and varyk test, a package's build.rs and the generated Rust its publisher shipped are never compiled or run. varyk publish is the exception: cargo publish verifies the crate as a plain cargo user would build it, which compiles a Varyk dependency's shipped Rust and any build.rs it was published with; --no-verify after -- skips that.
varyk init [dir] writes a new package named after the directory, four files: Cargo.toml, which names src/main.vr as the [[bin]] target and lists varyk-std at the compiler's own version under [dependencies], .gitignore, which leaves out /target and .env, .dockerignore, which keeps target and .env out of a container build, and src/main.vr, a hello-world program (--lib writes src/lib.vr and a [lib] target instead). It refuses to overwrite any of them. There is no build.rs and no stub: the package builds with varyk build and varyk run, not with plain cargo build, since its root is Varyk, not Rust. A build.rs or src/main.rs left by an earlier varyk init is never read.
varyk add runs cargo add in the package with exactly the arguments you give, and passes cargo's output and exit code through. varyk add http, varyk add sql, and varyk add mongo add the official packages: each runs cargo add varyk-http --rename http, cargo add varyk-sql --rename sql, or cargo add varyk-mongo --rename mongo, so code writes http::App, sql::connect, or mongo::connect, and the full crate name (varyk add varyk-http) does the same. Since milestone 5b4, varyk add http sql adds both, each with its own cargo add, in order, and takes no other argument; with one official name, any later arguments go to cargo as written (varyk add sql --features postgres). A short name with --rename is refused, since http, sql, and mongo are also names of unrelated crates: write the full name, varyk add varyk-http --rename web. varyk-http, varyk-sql, and varyk-mongo, the MongoDB package, which came after milestone 5, each live in their own repository and are released on their own. varyk-std is the one Rust crate Varyk code reaches without a facade: it is behind Error, json, env, log, and, since milestone 5c, Time, Uuid, and Bytes, and since milestone 5b1 the async runtime: an async main or test, a started call, Task::all or Task::all_settled, and time::sleep. A program that uses it needs a varyk-std line in [dependencies], and since milestone 6 that line names the oldest varyk the package was written for: a varyk of that version and every later one accept it, and build the program and every Varyk package it uses with the compiler's own varyk-std, whatever version each line names, so a new varyk release does not stop a published package from building. A compiler older than the line refuses it (V0404); from milestone 6 on, that error says which varyk the package needs and to run cargo install varyk. Until the program's line is on the compiler's minor and cargo update -p varyk-std has run, each build asks the crates.io index for the compiler's varyk-std again, so it needs the network; the reference has the commands. varyk publish asks more, since plain cargo builds the crate it ships from its Cargo.toml and lock as written: the line on the compiler's minor, and a varyk-std resolved for the build no older than the compiler's; varyk publish says which fails (V0404) and the fix: the line to write, cargo update -p varyk-std, or a release of a Varyk package of the build written for this varyk.
varyk publish runs the full check, assembles a plain Rust crate at target/varyk/package/<name>/ with the generated .rs files and every .vr source beside the file it produced, and no build.rs, then runs cargo publish there, passing on every argument after --. The crate needs no varyk: a Rust project adds it to [dependencies] like any crate and builds it with plain cargo build, and cargo install of a published Varyk binary works the same way. A Varyk package that depends on a published Varyk library names it directly, and varyk builds it from its .vr sources. varyk publish --assemble-only stops after the assembly, prints the crate's directory, and publishes nothing.
Diagnostics
Diagnostics have codes and fix-its; the reference lists every code. A code, once assigned, is never reused for a different meaning, though it may be retired. Rust habits are recognized: &user at a call site, user: &User in a signature, String or str, and lifetime annotations each get a diagnostic that says exactly what to change.
Editors
varyk lsp, since milestone 6, is the language server: an editor starts it and talks to it over its standard input and output, in the Language Server Protocol. Each time you open or save a .vr file, it checks the program the file belongs to, exactly as varyk check would, and the editor underlines every error at its place, with its message, notes, and code; an error with a suggested fix offers it as a quick fix. The Varyk extensions for VS Code and Zed, in varyk-editors and installed from the Visual Studio Marketplace or Open VSX (the Zed extension is submitted to Zed's registry and appears in its extensions panel once the Zed team merges it), colour .vr files and start varyk lsp for you; JetBrains IDEs get the colours through their TextMate Bundles setting, pointed at the vscode/ folder of a checkout of varyk-editors, whose README has the steps; and any other editor that speaks the protocol can run varyk lsp itself. The reference says which program a file belongs to.
Planned
- Milestone 6, in progress and not scheduled:
varyk fmt, a deterministic formatter on thevaryk-syntaxcrate, and the rest of the language server: hover, go-to-definition, and completion, which need error recovery in the parser.
Milestone 3 added Cargo.toml; there is no formatter yet. The roadmap has the full list.