Nova CLI

nova is the single entry point to the Nova language toolchain. It replaces run_tests.ps1 / run_tests.sh / regen_runtime.ps1 (see Plan 28).

Version: 0.1.0 (bootstrap). The binary ships as nova (Cargo package nova, crate nova-cli).


Quickstart

# Inside a Nova project (sibling nova.toml present). Modules live at the
# package root — there is no `src/` directory (D78).
nova check                       # type-check whole workspace
nova check encoding/             # walk a directory recursively
nova check lib.nv                # single file

nova build app.nv -o app         # compile to a native binary (the way to run code)
./app                            # then execute it
nova add mathlib --path ../mathlib   # add a dependency, update nova.lock
nova info mathlib                # a dependency's effect-surface
nova test nova_tests             # compile + run all nova_tests/
nova test nova_tests/plan118     # a single subdirectory
nova test std nova_tests         # multiple paths: std/ + nova_tests/
nova test --filter basics        # substring subset

nova doc lib.nv                  # markdown to stdout
nova doc . --format json         # D107 JSON schema
nova doc . --check --strict      # CI doc validation

nova bench run bench.nv          # run benchmarks
nova contracts verify foo.nv     # SMT-verify contracts

No interpreter. Nova compiles to C — there is no nova run. To run a program, nova build it and execute the binary; to run tests, use nova test. See nova run below.


Installation and build

nova-cli lives in nova-cli/ next to compiler-codegen/. No workspace is used (see Plan 28 — both crates are standalone).

# Debug build (default, opt-level=0)
cargo build --manifest-path nova-cli/Cargo.toml

# Release (opt-level=2, LTO thin)
cargo build --release --manifest-path nova-cli/Cargo.toml

# With the Z3 backend for contracts (Plan 33.1)
cargo build --release --manifest-path nova-cli/Cargo.toml --features z3-backend

You get:

  • nova-cli/target/{debug,release}/nova[.exe]
  • nova-cli/target/{debug,release}/migrate_plan60[.exe]
  • nova-cli/target/{debug,release}/migrate_plan65[.exe]

nova has a path dependency on nova_codegen (../compiler-codegen) — rebuilding the compiler automatically recompiles the CLI.


Global flags

Apply to every subcommand:

FlagValuesDescription
--colorauto (default), always, neverANSI color control. See Plan 36 R10.

Color auto-detection (priority high → low):

  1. CLI --color always|never — overrides everything
  2. CLICOLOR_FORCE=1 → always
  3. NO_COLOR (any value) → never (no-color.org)
  4. CLICOLOR=0 → never
  5. CI=true → never
  6. TERM=dumb → never
  7. Default — on

Field-cache tuning (advanced)

Every subcommand also accepts the Plan 123 field-caching knobs. These are forensic / escape-hatch flags — the defaults are correct for normal use; you only touch them when investigating a codegen-cache regression.

FlagEffect
--no-field-cacheDisable field caching entirely (== NOVA_FIELD_CACHE=0)
--no-field-cache-licmDisable the LICM phase (D218)
--no-field-cache-pureDisable the pure-call cache phase (D219)
--no-field-cache-chainDisable the chain cache phase (D217 V4)
--no-field-cache-ipaDisable IPA refinements (D223 V7.1)
--field-cache-threshold NMin @field reads to cache (default 2)
--field-cache-licm-threshold NMin reads inside a loop (default 2)
--field-cache-pure-threshold NMin @method() calls (default 2)
--field-cache-chain-threshold NMin chain occurrences (default 2)
--field-cache-max NPer-fn cap across all layers (default 8)
--field-cache-licm-max NPer-loop LICM cap (default 4)
--field-cache-chain-depth NChain max depth (default 4, min 2)
--field-cache-ipa-iter NIPA iterative-closure cap (default 10)

nova check additionally exposes --explain-cache, --telemetry-cache, --telemetry-json, --telemetry-baseline FILE, --telemetry-gate-affected-drop F, and --telemetry-gate-caches-drop F for cache-analysis reporting and CI regression gating.

The field-cache flags are omitted from the per-command tables below to keep them readable; assume every command accepts the whole family.


Exit codes

Cargo convention (Plan 36 R7):

CodeMeaning
0Success
1Diagnostic failure (typecheck fail, test fail, contract violation, etc.)
2Usage error (bad flag, file not found, wrong extension, missing nova.toml)
101Internal panic (forced via std::panic::set_hook for cross-platform consistency)

nova doc --diff additionally uses 3 for patch-level breaking change (see nova doc).


Project root discovery

Most commands search for nova.toml walking up from CWD. The logic lives in nova_codegen::test_runner::find_repo_root_from:

  1. Walk from CWD up to the filesystem root
  2. At each level read nova.toml if present
  3. If it contains [workspace] — that is the root (workspace root), stop
  4. Otherwise remember the last nova.toml seen and keep going
  5. Return the [workspace]-marked root if found, else the topmost nova.toml directory

This is workspace-aware behavior (D78 AD6, Plan 35) — prevents a nested nova_tests/nova.toml from shadowing the real root.

If no nova.toml is found — exit 2:

error: nova.toml not found — are you inside a Nova project?

Paths resolved under the workspace root:

  • <root>/nova_tests/ — test corpus
  • <root>/std/ — standard library
  • <root>/compiler-codegen/ — C-runtime include paths
  • <root>/compiler-codegen/nova_rt/ — runtime sources (libuv, GC)
  • <root>/target/last-test-results.json--rerun-failed cache

Commands

nova check

Type-check one or more .nv files or directories. Plan 36 MVP — replaces nova-codegen check.

nova check [PATHS...] [--jobs N] [-q|-v] [--list] [--format human|short]
           [--include-runtime] [--skip PATTERN]...

Positional arguments:

  • PATHS — list of files or directories. Empty → workspace root (recursive walk). Files must have a .nv extension, otherwise exit 2.

Flags:

FlagDefaultDescription
--jobs N0 (= num_cpus)Parallel workers
-q, --quietoffOnly FAIL lines and summary
-v, --verboseoffExtra info (timing)
--listoffList collected files without checking
--formathumanhuman (colored) or short (file:line:col: msg for grep)
--include-runtimeoffInclude std/runtime/ (auto-gen, skipped by default)
--skip PATTERN[]Skip files matching substring (repeatable)

Hard-coded skip (always excluded):

  • target/, node_modules/, vendor/
  • .git/, .hg/, .svn/
  • directories starting with _ or .
  • std/runtime/ (override via --include-runtime)

Behavior:

  • Dedup via canonicalize
  • Sorted for determinism
  • Parallel walk via thread::scope + mpsc channel
  • Per-file warnings (yellow: warning:) after the ok: line
  • Summary: pass=N fail=N warnings=N (X.YYs)
  • Exit 1 on any FAIL, 2 on usage error

--format short:

lib.nv: ok
parser.nv:42:5: error: type mismatch

--format human (default):

ok: lib.nv
FAIL: parser.nv
  parser.nv:42:5: type mismatch

JSON / SARIF / JUnit formats are reserved for sub-plan 36.A and not yet implemented.


nova run

Currently NOT supported. The tree-walking interpreter is disabled.

nova run is still a visible subcommand, but invoking it errors out and points you at the C-codegen path:

nova run FILE
error: the Nova interpreter (`nova run`) is currently NOT supported.
Use `nova build <file>` to compile to an executable, or `nova test` to
compile and run tests (both via C codegen).

(exit 1).

Nova compiles to C; there is no supported interpreter. To run a program, nova build it and execute the resulting binary; to compile and run tests, use nova test / nova test-build.


nova add

Add a dependency to [dependencies] of the current package’s nova.toml and update nova.lock (Plan 03.1).

nova add NAME (--path DIR | --git URL [--tag T | --branch B | --rev R | --version REQ])
FlagDescription
NAMEDependency name — must equal the [package].name of the depended-on package
--path DIRLocal path dependency (another package on disk)
--git URLGit dependency (repository URL)
--tag TGit pin: tag (only with --git)
--branch BGit pin: branch (only with --git)
--rev RGit pin: commit / rev (only with --git)
--version REQGit pin: semver range, e.g. ^1.2 (only with --git, Plan 03.2)
  • --path and --git are mutually exclusive; exactly one is required.
  • --tag / --branch / --rev / --version are mutually exclusive; optional (no pin → default branch, still recorded as an exact commit in the lock).
  • --version selects the highest matching semver tag of the repository and records both the resolved version and commit in nova.lock.
  • Edits the [dependencies] section (creates it if absent). A duplicate name → exit 2.
  • After editing, runs lock sync: materializes a git dependency in the cache and writes the resolved commit to nova.lock.
  • Must run inside a package (a nova.toml with [package]), not on a bare [workspace] manifest.
nova add mathlib --path ../mathlib
nova add gitlib  --git https://example.org/gitlib.nv --tag v1.0.0
nova add libfoo  --git https://example.org/libfoo.nv --version "^1.2"

nova update

Re-resolve git dependencies and refresh nova.lock (Plan 03.1 / 03.2).

nova update [NAME] [--precise NAME@VERSION]
  • NAME — a single git dependency to update. Omitted → all git dependencies.
  • Drops the targeted git entries from nova.lock, then re-resolves them: branch/tag pins pick up the current commit, version-range pins pick the highest matching tag. Untargeted dependencies stay pinned (reproducibility).
  • --precise NAME@VERSION — pin a version-range git dependency to an exact version (e.g. nova update --precise libfoo@1.2.0). The resolver must satisfy it with the rest of the tree, or fails with a conflict.
  • path dependencies have no pin — passing one is rejected with an explanation.

nova info

Show the effect-surface of a package — the aggregated effects of its public API (Plan 03.4 / D140). Nova-unique: in Cargo/npm you cannot tell that a dependency reaches the network without auditing its code.

nova info TARGET [--format human|json] [--diff BASE [--fail-on-new]]
FlagDescription
TARGETA package path (.nv file / directory) or a dependency name from the current package’s [dependencies]
--formathuman (default) or json
--diff BASECompare TARGET’s effect-surface against BASE (path or dependency) — shows added/removed effects
--fail-on-newWith --diff: exit non-zero if new effects appeared (CI gate against supply-chain drift)
  • Effect-surface = union of effects declared on all export functions (D28 — public functions declare effects explicitly, so the surface is exact without inter-procedural analysis). Private functions are excluded.
  • --diff is a supply-chain signal: a Net/Fs effect appearing in a patch/minor release of a previously pure API is a red flag.
nova info ./mylib                    # effect-surface of a local package
nova info somedep                    # of a declared dependency
nova info somedep --format json
nova info ./v2 --diff ./v1 --fail-on-new   # CI: fail if v2 added effects

Capability-confined dependencies. A dependency can be constrained with forbid in nova.toml:

[dependencies]
parser = { git = "https://example.org/parser.nv", forbid = ["Net", "Fs"] }

nova build computes the dependency’s effect-surface and fails the build if it uses a forbidden effect — a type-level sandbox (stronger than runtime permission models). See D63 / D140.


nova build

Compile one .nv file to a native binary (via the C backend).

nova build FILE [-o OUTPUT] [--mode dev|release] [--toolchain auto|clang|msvc|gcc]
           [--vcvars PATH] [--clang PATH] [--timeout SECS] [--keep-artifacts]
           [--mono-depth N]

Single file only-o takes one path. For multi-file projects use import from the entry point.

Arguments:

FlagDefaultDescription
FILEEntry-point .nv with fn main
-o OUTPUT<name>[.exe] in CWDOutput binary path
--modedevdev (unoptimized) or release (-O2 + LTO)
--toolchainautoauto (Clang → MSVC → GCC), clang, msvc, gcc
--vcvarsauto via vswherePath to vcvars64.bat (Windows)
--clangauto detectPath to clang.exe
--timeout120Compile timeout (seconds)
--keep-artifactsoffKeep .c/.exe/.obj in tmp
--mono-depth N500 (or NOVA_MONO_DEPTH)Monomorphization-instantiation depth limit (Plan 48 Ф.7.6)

Tmp directory: $TEMP/nova_tests/build/<path-hash>/ on Windows or $TMPDIR/nova_tests/build/<path-hash>/ on Unix. The hash uses DefaultHasher over the absolute file path — unique without crypto dependency.

Pipeline:

  1. parse + typecheck + infer_effects
  2. CEmitter::emit_module → C source
  3. detect_toolchain() (auto-detects vcvars)
  4. detect_or_build_libuv() — runtime may depend on libuv
  5. compile_c_to_exe(&tc, &build_opts, timeout)
  6. Copy exe → -o or CWD
  7. Remove tmp (unless --keep-artifacts)

nova test

Run tests from a directory or a file. Plan 28 (together with Plan 26, Plan 27, Plan 34).

nova test [PATH]... [--filter SUBSTR] [--jobs N] [--format text|json|tap|junit]
          [--mode dev|release] [--toolchain auto|clang|msvc|gcc]
          [--vcvars PATH] [--clang PATH] [--timeout SECS] [-v|-q]
          [--results-file PATH] [--rerun-failed] [--retries N]
          [--keep-artifacts] [--gc boehm|malloc]
          [--list] [--filter-from PATH] [--shuffle [SEED]]
          [--skip PATTERN]... [--mono-depth N]
          [--positive] [--compile-error] [--panic] [--timeout-type]
          [--exit] [--slow] [--full]

Arguments:

FlagDefaultDescription
PATH...— (required)Files and/or directories to test (at least one required)
--filter SUBSTRFilter by display-name substring
--jobs N0 (= num_cpus)Parallel workers
--formattexttext, json, tap, junit
--modedevdev or release
--toolchainautoauto, clang, msvc, gcc
--vcvarsautoPath to vcvars64.bat
--clangautoPath to clang.exe
--timeout60Per-test timeout (seconds)
-v, --verboseoffOutput for passing tests too
-q, --quietoffFAIL + summary only
--results-file PATH<root>/target/last-test-results.jsonWhere to write results
--rerun-failedoffRe-run only failed/timed-out from last run
--retries N0Retries for transient failures (AV races, etc.)
--keep-artifactsoffKeep .c/.exe/.obj
--gcboehmboehm (default) or malloc (internal only)
--listoffList tests without running
--filter-from PATHFile with test names (one per line, exact match)
--shuffle [SEED]offRandom order; optional seed for reproducibility
--skip PATTERN[]Skip tests by name or path substring (repeatable)
--mono-depth N500 (or env)Monomorphization-instantiation depth limit
--positiveon (default)Select positive tests (no EXPECT_* marker). Default when no category flag is given.
--compile-erroroffSelect EXPECT_COMPILE_ERROR tests.
--panicoffSelect EXPECT_RUNTIME_PANIC tests.
--timeout-typeoffSelect EXPECT_TIMEOUT tests.
--exitoffSelect EXPECT_EXIT_CODE tests.
--slowoffAlso include *_slow.nv tests (any type). Alias: --include-slow.
--fulloffAll types + slow (--positive --compile-error --panic --timeout-type --exit --slow).

Category flags (Plan 169.1.1, D304) are additive — multiple flags union their test sets (OR). With no category flag the default is positive tests only, fast (non-slow). The test type is detected from the first EXPECT_* marker in the file header (first 30 lines), not from the folder — so negative tests are found even outside neg/.

Multi-path (Plan 36.D.1): pass any number of paths — directories and/or files. At least one path is required (Plan 172.6). To also test std/:

nova test nova_tests             # nova_tests/ only
nova test std nova_tests         # std/ + nova_tests/ together
nova test nova_tests/plan118     # specific subdirectory

Display name is relative to the current working directory (cwd): nova_tests/plan118/t1_parse_ok instead of an absolute path.

Output formats:

  • text — human-readable, colored, on stdout
  • json — array with name, status, duration_ms, stderr
  • tap — Test Anything Protocol v13
  • junit — JUnit XML (for CI aggregators)

--rerun-failed: reads --results-file, selects entries with status != "pass", filters the suite, runs only those.

EXPECT markers in test files (see docs/test-conventions.md):

  • // EXPECT: <stdout-line> — exact line match
  • // EXPECT_STDERR: <line> — for stderr
  • // EXPECT_COMPILE_ERROR: <substring> — must fail to compile
  • // EXPECT_RUNTIME_ERROR: <substring> — panic with substring
  • // REQUIRES_SMT_BACKEND — skip if SMT not available

nova test-build

Build + run one test file. Used by IDE / CI for targeted debug.

nova test-build FILE [--mode dev|release] [--toolchain auto|clang|msvc|gcc]
                [--vcvars PATH] [--clang PATH] [--timeout SECS]
                [--keep-artifacts] [--gc boehm|malloc] [--mono-depth N]
FlagDefaultDescription
FILEPath to a .nv test
--modedevSee nova test
--toolchainauto
--vcvarsauto
--clangauto
--timeout60
--keep-artifactsoff
--gcboehm
--mono-depth N500

Equivalent to nova test <FILE> but without bulk-runner machinery (single exe, single test-block per file).


nova regen-runtime

Regenerate std/runtime/*.nv stubs from the compiler runtime registry. Replaces regen_runtime.ps1.

nova regen-runtime [--check]
FlagDefaultDescription
--checkoffCompare only — exit 1 if stubs diverge from the registry (CI guard)

Backed by nova_codegen::codegen::runtime_registry::all() + module render. See Plan 13.


nova doc

Production-grade documentation (Plan 45 / D107). Markdown / JSON / HTML

  • doc-tests + coverage + mutation testing + watch + workspace mode.
nova doc [FILE] [--format markdown|json|html] [--json-schema]
         [--include-private] [--test] [--check] [--watch]
         [--coverage [--coverage-threshold PERCENT]] [--jobs N]
         [--diff OLD NEW] [--scrape-examples WORKSPACE]
         [--strict] [--mutate-contracts [--real-exec]]
         [--output-dir DIR]

Arguments:

FlagDefaultDescription
FILE— (required unless --json-schema).nv file or directory
--formatmarkdownmarkdown, json (D107 schema), html
--json-schemaoffPrint the embedded JSON Schema 2020-12 and exit
--include-privateoffInclude non-exported items
--testoffRun doc-tests (Plan 45 Ф.7)
--checkoffValidate without rendering (broken links, missing summaries)
--watchoffRe-render on mtime poll (500ms); Ctrl-C to exit
--coverageoffCoverage metrics (% items with summary)
--coverage-threshold NCI gate: exit 1 if coverage% < N
--jobs N0 (= num_cpus)Parallel parse jobs for workspace
--diff OLD NEWCompare two JSON outputs (semver detection)
--scrape-examples WORKSPACEAttach top-3 usage examples per fn
--strictoffWarnings → errors (CI)
--mutate-contractsoffMutation testing for contracts (Nova-unique)
--real-execoffActually execute mutants (requires --mutate-contracts)
--output-dir DIRMulti-page HTML; only with --format html

Exit codes for --diff OLD NEW:

CodeMeaning
0No breaking changes
1Major change (breaking)
2Minor change (additive)
3Patch change (cosmetic)

Mutation testing (--mutate-contracts):

Generates mutants per function with contracts:

  • >>=, <<=
  • ==!=
  • Drop requires/ensures

Default — text-based heuristic (~1ms/mutant). With --real-exec — runs mutated doc-tests through test_runner (~100ms/mutant, true positive guarantee).

Supported /// doc formats — see Plan 45 (D107).


nova doc-query

DSL queries against the nova doc --format json output (Plan 45 Ф.32.1). Foundation for the MCP server (nova doc-mcp).

nova doc-query JSON_FILE [QUERY]

Query syntax: key=value,key=value,...

KeyValues
kindfn, type, effect, protocol, module, …
namesubstring
moduleexact module path
module-prefixpath prefix
capabilitycapability name
effecteffect name
has-contractstrue, false
verifiedtrue, false
stabilitystable, unstable, experimental
deprecatedtrue, false

Examples:

nova doc . --format json > out.json
nova doc-query out.json "kind=fn,capability=pure"
nova doc-query out.json "name=add,has-contracts=true"
nova doc-query out.json "module-prefix=std,effect=Fs"

Empty query → returns the whole file as-is.


nova doc-mcp

MCP server (Model Context Protocol) — JSON-RPC over stdio or HTTP (Plan 45 Ф.32.3 / Ф.34.1). Compatible with MCP clients (Claude Code, MCP Inspector).

nova doc-mcp FILE [--port PORT]
FlagDefaultDescription
FILE.nv source or pre-generated .json
--port PORT— (stdio)HTTP mode on 127.0.0.1:PORT, POST /mcp

Tools (exposed via tools/list):

  • query_items(query) — search via DSL (nova doc-query)
  • list_modules() — list module paths
  • get_item(item_id) — fetch full item JSON

Protocol: the MCP client sends initializetools/listtools/call.


nova contracts

Contract inspection and verification (Plan 33 / D24). Output is JSON (AI-friendly schema, see docs/contracts-diag-schema.json).

nova contracts <SUBCOMMAND>

nova contracts list

List all contracts in a file.

nova contracts list FILE

nova contracts verify

SMT-verify contracts. JSON output.

nova contracts verify FILE [--backend BACKEND]
FlagDefaultDescription
FILE.nv file
--backend BACKENDenv NOVA_SMT_BACKENDOverride SMT backend (trivial, z3)

Z3 backend: requires a build with --features z3-backend. See Plan 33.1.

nova contracts suggest

AI-assisted contract suggestions (stubs).

nova contracts suggest FILE FN_NAME

nova contracts counterexample

Counterexample for a failing contract.

nova contracts counterexample FILE FN_NAME [--contract-id N]
FlagDefaultDescription
FN_NAMEFunction name
--contract-id N0Contract index (0-based)

nova bench

Benchmark infrastructure (Plan 57 — MVP+A+B+C+D+E+F+G+H shipped). Outperforms Criterion (Rust) / testing.B+benchstat (Go) / tinybench (TS) on several axes. See docs/bench-conventions.md.

nova bench <SUBCOMMAND>

Subcommands: run, diff, gate, calibrate, cpu-instr-check, membw-check, hyperfine, callgrind, callgrind-check, runner-branch, history-anomalies, remote, corpus, history-add, history-list, history-squash, dashboard.

nova bench run

Run bench "..." { measure { ... } } declarations.

nova bench run FILE [--filter PATTERN] [--samples N] [--warmup-ms MS]
                    [--time-budget SECS] [--gc boehm|malloc]
                    [--mode release|dev] [--toolchain auto|clang|msvc|gcc]
                    [--vcvars PATH] [--clang PATH]
                    [--compile-timeout SECS] [--run-timeout SECS]
                    [--keep-artifacts] [--mono-depth N]
                    [--out PATH] [--out-csv PATH] [--out-md PATH]
                    [--out-criterion DIR] [--profile MODE OUT]
                    [--histogram]
FlagDefaultDescription
FILE.nv file with bench "..." blocks
--filter PATTERNComma-separated bench-name fragments
--samples N100Override sample count
--warmup-ms500Warmup duration in ms
--time-budget10Per-bench budget in seconds
--gcboehmSee nova test
--modereleaserelease (recommended) or dev
--toolchainautoSee nova build
--compile-timeout120Compile timeout
--run-timeout600Bench process run timeout
--out PATHWrite JSON v1
--out-csv PATHWrite CSV
--out-md PATHMarkdown (for PR comment)
--out-criterion DIRCriterion-compatible JSON layout
--profile MODE OUTcpu/heap/gc profile; cpu requires samply
--histogramoffASCII histogram per bench

Output formats:

  • --out (JSON v1): full schema with metadata (git SHA, toolchain, CPU model)
  • --out-criterion: <dir>/<safe-name>/new/{estimates,sample,benchmark}.json, compatible with cargo-criterion --message-format=criterion
  • --out-md: markdown table for PRs
  • --histogram: 40 buckets, Unicode block chars, median and Tukey fences

Profile modes:

  • cpu — wraps samply (install via cargo install samply)
  • heapNOVA_BENCH_HEAP_SAMPLE_MS=10
  • gcNOVA_BENCH_GC_TRACE=1

nova bench diff

Compare two bench results. Welch’s t-test, geomean delta, reproducibility check.

nova bench diff BASELINE NEW [--format terminal|markdown|json]
                              [--explain [--ai-config PATH] [--ai-max-tokens N]
                                         [--ai-dry-run]]
                              [--baseline-sha SHA] [--new-sha SHA]
FlagDefaultDescription
BASELINE, NEWJSON files (nova bench run --out)
--formatterminalterminal, markdown, json
--explainoffAI regression interpretation (Plan 57.F.2, opt-in)
--ai-config PATH~/.nova-ai.tomlAI config path
--ai-max-tokens4000Override max tokens
--ai-dry-runoffPrint request body without API call
--baseline-sha, --new-shaauto from JSONGit SHA for context

--explain uses system curl (no RustCrypto stack) and requires NOVA_AI_API_KEY or a config file.

nova bench gate

CI gate — apply thresholds from bench.toml. Exit 0 = pass, 1 = regress.

nova bench gate BASELINE NEW [--config PATH] [--noise PATH]
FlagDefaultDescription
--config./bench.tomlPath to bench.toml
--noise./.nova-bench-noise.json if presentAuto-calibrated noise floor (see calibrate)

nova bench calibrate

Auto-calibrate noise floor from ≥2 repeated runs of the same baseline (Plan 57.A.3).

nova bench calibrate RUNS... [--out PATH]
FlagDefaultDescription
RUNS...≥2 JSON results of the same source
--out.nova-bench-noise.jsonWhere to write the noise floor

The file is machine-specific; do not commit to git.

nova bench cpu-instr-check

Diagnose CPU-instruction-counter availability (Plan 57.B.4).

nova bench cpu-instr-check

Linux: tries perf_event_open + measures a known loop. Other OS: prints a stub message.

nova bench membw-check

Diagnose memory-bandwidth measurement availability (Plan 57.F.3).

nova bench membw-check

Linux: probes /sys/devices/uncore_imc_* + tries an LLC-miss perf counter. Other OS: stub.

nova bench hyperfine

Hyperfine-style cross-binary timing — wall-clock measurement of arbitrary commands (Plan 57.H.2). Output schema-compatible with nova bench diff.

nova bench hyperfine SPECS... [--warmup N] [--samples N]
                              [--timeout SECS] [--workdir PATH] [--out PATH]
FlagDefaultDescription
SPECS...≥1"name=binary args..." or just "binary args..."
--warmup3Warmup runs (discarded)
--samples10Sample runs
--timeout300Per-command timeout
--workdir PATHCWD for commands
--out PATHstdoutJSON output

Example:

nova bench hyperfine \
  "old=./nova-old build large.nv" \
  "new=./nova-new build large.nv" \
  --samples 10 --warmup 2 --out result.json

nova bench callgrind

Run under Valgrind Callgrind — deterministic CPU-instruction count (Plan 57.H.3). Cross-platform fallback to perf_event_open (Linux-only). Works on macOS + Linux with valgrind installed.

nova bench callgrind BINARY [ARGS...] [--cache-sim] [--workdir PATH] [--out PATH]
FlagDefaultDescription
BINARYPath to executable
ARGS...Arguments for the executable
--cache-simoffI1/D1/LL miss counts (slower)
--workdir PATHCWD for the command
--out PATHJSON CallgrindResult

nova bench callgrind-check

Check valgrind availability + version.

nova bench callgrind-check

nova bench runner-branch

Print the recommended history-branch name based on the NOVA_BENCH_RUNNER_ID env (Plan 57.D.4 — multi-runner CI matrix).

nova bench runner-branch

Returns bench-history if env is unset, else bench-history-<id>.

nova bench history-anomalies

Detect changepoints in the historical median time-series via PELT (Plan 57.E.5). Identifies regimes with ≥5% delta.

nova bench history-anomalies [--branch BRANCH] [--format text|json]
FlagDefaultDescription
--branchauto (NOVA_BENCH_RUNNER_ID-aware)History branch
--formattexttext or json

nova bench remote

SSH-distributed bench coordination (Plan 57.F.1).

nova bench remote <SUBCOMMAND>
nova bench remote list

List configured remotes from ~/.nova-bench-remotes.toml.

nova bench remote list [--config PATH]

--config overridable via NOVA_BENCH_REMOTES env.

nova bench remote ping

SSH health check for one remote.

nova bench remote ping NAME [--config PATH]
nova bench remote run

Parallel bench across N remotes; gathers results.

nova bench remote run BENCH [--remotes LIST] [--gather-into DIR] [--sha SHA] [--config PATH]
FlagDefaultDescription
BENCH.nv file path (relative to remote repo root)
--remotesallComma-separated names or all
--gather-intoremote-resultsWhere to place per-remote JSON
--sha SHAOptional git SHA to checkout before bench

nova bench corpus

Measure per-pass compile time for corpus file(s) (Plan 57.C.8). Wraps nova build with NOVA_PERF_TIMER=1, parses __PERF__ markers.

nova bench corpus PATH [--json] [--html PATH] [--echarts-url URL]
                       [--mode release|dev] [--toolchain auto|clang|msvc]
                       [--gc boehm|malloc]
FlagDefaultDescription
PATH.nv file or directory
--jsonoffJSON output (instead of table)
--html PATHHTML compiler-perf dashboard (Plan 57.D.5)
--echarts-urlhttps://cdn.jsdelivr.net/...Custom echarts URL (offline)
--moderelease
--toolchainauto
--gcboehm

nova bench history-add

Append a result JSON to the orphan history branch (Plan 57.A.1).

nova bench history-add RESULT [--branch BRANCH] [--push] [--remote NAME] [--dry-run]
FlagDefaultDescription
RESULTJSON from nova bench run --out
--branchautoOrphan branch (defaults to bench-history)
--pushoffPush after commit
--remoteoriginRemote name when --push
--dry-runoffPrint what would happen without committing

nova bench history-list

List entries in the history branch (newest first).

nova bench history-list [--branch BRANCH]

nova bench history-squash

Squash older entries per retention policy (Plan 57.C.6 — yearly squash recommended).

nova bench history-squash --before-date YYYY-MM-DD [--branch BRANCH]
                          [--push] [--remote NAME] [--dry-run]
FlagDefaultDescription
--before-date— (required)Squash everything older than this UTC date
--branchauto
--pushoff
--remoteorigin
--dry-runoffPrint what would be removed

nova bench dashboard

Static HTML dashboard from history (Plan 57.A.2).

nova bench dashboard [--history-branch BRANCH] [--out DIR] [--max-entries N] [--echarts-url URL]
FlagDefaultDescription
--history-branchautoHistory branch
--outdashboardOutput directory
--max-entries200Max entries (newest first)
--echarts-urljsdelivr URLCustom echarts URL (offline = local)

Generates index.html + bench-<safe>.html per bench + data.json.

The nova bench family also exposes the diagnostic subcommands field-cache (real wall-clock measurement of the Plan 123 field-cache impact), cpu-instr-check, membw-check, and callgrind-check. Run nova bench <sub> --help for their flags.


nova consume-analyze

Consume-type coverage analyzer (Plan 100.8 / D7). Scans a file or directory, collects all consume-typed bindings, and reports how many are covered via consume-methods (Cleanup.@cleanup, D188) or defer. Useful as a CI hygiene check.

nova consume-analyze PATH [--format human|json] [--fail-on-uncovered]
FlagDefaultDescription
PATH.nv file or directory to analyze
--formathumanhuman or json
--fail-on-uncoveredoffExit non-zero if any uncovered consume binding is found (CI gate)

Exit codes:

CodeMeaning
0All consume bindings covered
1Uncovered bindings found
2Usage error

Environment variables

VarUsed byEffect
NOVA_CODEGEN(reserved)Override path to nova-codegen binary
NOVA_MONO_DEPTHbuild, test, test-build, benchMonomorphization-instantiation depth limit (default 500)
NOVA_REACH_DCEbuild, test, test-buildReachability-codegen DCE (Plan 159, D283). Unset / ≠0ON (default): emit to C only declarations reachable from main. =0OFF: byte-identical pre-159 behavior (emit everything) — escape hatch for over-prune diagnosis
NOVA_HOMEadd, build (git deps)Root for the git dependency cache; default ~/.nova (cache under <NOVA_HOME>/git)
NOVA_OFFLINEadd, build (git deps)=1 → forbid network (clone/fetch); build only from the existing cache
NOVA_SMT_BACKENDcontractsSMT backend (trivial, z3)
NOVA_PERF_TIMERbench corpus (auto-set)Enables __PERF__ markers in the compiler
NOVA_PERF_TIMER_AGGREGATEbench corpusAggregate __PERF__ across passes
NOVA_BENCH_RUNNER_IDbench history-*, runner-branchMulti-runner CI matrix; used in branch name
NOVA_BENCH_REMOTESbench remoteOverride path to .nova-bench-remotes.toml
NOVA_BENCH_FILTERbench run (auto-set)Forwarded to bench process
NOVA_BENCH_SAMPLESbench run (auto-set)Override sample count
NOVA_BENCH_WARMUP_NSbench run (auto-set)Warmup in nanoseconds
NOVA_BENCH_TIME_BUDGET_NSbench run (auto-set)Time budget in nanoseconds
NOVA_BENCH_HEAP_SAMPLE_MSbench run --profile heapSample interval in ms
NOVA_BENCH_GC_TRACEbench run --profile gcEnables GC tracing
NOVA_AI_PROVIDERbench diff --explainAI provider (anthropic, openai, …)
NOVA_AI_MODELbench diff --explainModel override
NOVA_AI_API_KEYbench diff --explainAPI key (or via ~/.nova-ai.toml)
NOVA_C_COMPILERbench reproReal path to the C compiler (captured in metadata)
NOVA_SHAbench repro (compile-time option_env!)Git SHA of the nova binary
NO_COLORglobalDisable ANSI colors
CLICOLORglobal=0 → disable
CLICOLOR_FORCEglobal=1 → force enable
CIglobal=true → disable colors
TERMglobal=dumb → disable colors
TEMPWindowsTmp directory for build/test artifacts
TMPDIRUnixSame

Migration binaries

Separate one-shot tools in nova-cli/src/bin/. Kept in the repository as a reference for future atomic API-rename plans.

migrate_plan60

Lexer-based migration of field-style size-accessors to method-form (D117 / Plan 60):

expr.len      → expr.len()
expr.is_empty → expr.is_empty()
expr.byte_len → expr.byte_len()
expr.cap      → expr.capacity()
expr.capacity → expr.capacity()

Skip conditions: previous significant token == = (method-value assignment: let f = arr.len).

migrate_plan60 [--apply] [--dry-run] [--md] [--paths DIR...]
FlagDefaultDescription
--dry-run(default)Print diff only
--applyoffActually write
--mdoffInclude .md files (rewrite inside ```nova / ```nv blocks)
--paths DIR...std/, nova_tests/, examples/List of directories

Token-level rewrite — comments / whitespace / formatting preserved 1:1.

migrate_plan65

Lexer-based migration of Time.after(<lit>)ChanReader.close_after(Duration.from_*(<lit>)) (Plan 65 AD11):

Time.after(<INT>)    → ChanReader.close_after(Duration.from_millis(<INT>))
Time.after(<FLOAT>)  → ChanReader.close_after(Duration.from_secs_f64(<FLOAT>))
Time.after(<expr>)   → left as-is + // MIGRATE_MANUAL: Plan 65 — non-literal arg
migrate_plan65 [--apply] [--dry-run] [--md] [--paths DIR...]

Exit codes (special set):

CodeMeaning
0No changes needed (idempotent)
1Manual markers emitted — CI gate fails
2Changes applied (or would be applied in dry-run)

Token-aware via nova_codegen::lexer — strings and comments are naturally skipped.