CLI reference
mvmforge canonicalize <manifest.json>mvmforge validate <manifest.json>mvmforge emit <entry.py | entry.ts>mvmforge compile <manifest.json> --out <dir>mvmforge up <entry> [-- <mvmctl args...>]mvmforge --helpAll subcommands print canonical JSON (RFC 8785) when they print structured output. Exit codes are stable.
Exit codes
| Code | Meaning |
|---|---|
0 | Success |
1 | Validation or SDK failure (the operation produced a structured error) |
2 | I/O, CLI usage, or environment error |
Subcommands
canonicalize
mvmforge canonicalize <manifest.json>Reads any JSON document and prints its RFC 8785 canonical form on stdout. Useful for normalizing IR fixtures, computing stable hashes, or comparing two documents for semantic equality.
mvmforge canonicalize my-manifest.json | sha256sumvalidate
mvmforge validate <manifest.json>Strict-parses the document as a Workload IR, runs all v0 host validation rules, and prints a canonical JSON result:
{"errors":[],"ok":true}or
{"errors":[{"code":"E_SECRETS_NOT_IMPLEMENTED","path":".apps[0].env.TOKEN","detail":"..."}],"ok":false}Exit codes:
0ifok: true1if validation failed (exit envelope on stdout still parseable)2if the file couldn’t be read or wasn’t valid JSON
Error codes come from the error-code registry. They are stable strings; SDK tests can pattern-match on them.
emit
mvmforge emit <entry>Runs the SDK emitter for <entry>, validates the output, and prints the
canonical IR on stdout. v0 supports .py and .ts extensions.
The host invokes the SDK as a subprocess per ADR-0002 with the
environment variable MVMFORGE_IR_OUT set to a temp file path. The SDK
loads <entry> (which runs its decorator registrations as a side effect),
serializes to canonical JSON, and writes to the named path.
Environment:
| Variable | Default | Purpose |
|---|---|---|
MVMFORGE_PYTHON_BIN | python | Python interpreter for .py entries |
MVMFORGE_NODE_BIN | node | Node interpreter for .ts entries |
MVMFORGE_TS_MAIN | sdks/typescript/src/main.ts | TypeScript SDK entrypoint |
mvmforge emit app.pymvmforge emit app.tscompile
mvmforge compile <manifest.json> --out <dir>Reads a Workload IR manifest, validates it, copies the user’s source tree
into a staging directory, renders flake.nix and launch.json, and
atomically publishes the artifact directory at <dir>.
The output directory contains:
<dir>/ flake.nix # generated Nix template launch.json # canonical-JSON launch plan with ir_hash, tree_hash, etc. src/ # user's source tree (per app.source.path + globs)compile does not invoke nix. The flake is rendered from templates;
inputs are pinned by URL but locked by Nix at build time. Source paths in
the IR are resolved relative to the manifest file’s directory.
Environment:
| Variable | Default | Purpose |
|---|---|---|
MVMFORGE_MVM_FLAKE_URL | (build-time pin) | Override the mvm flake input — useful for local-checkout development |
mvmforge emit app.py > /tmp/m.jsonmvmforge compile /tmp/m.json --out /tmp/artifactup
mvmforge up <entry> [-- <mvmctl args...>]The end-to-end pipeline. <entry> may be:
- a
.pyor.tsSDK entry (host runsemitfirst to produce IR), or - a
.jsonIR manifest (compiled directly).
Compile lands in a temp directory; the host then invokes
mvmctl up --flake <artifact-dir> with any args after -- appended verbatim.
mvmforge up app.pymvmforge up app.ts -- --hypervisor apple-container --name myvmmvmforge up manifest.json -- -p 8080:80Environment:
| Variable | Default | Purpose |
|---|---|---|
MVMFORGE_MVM_BIN | (search PATH for mvm) | The mvmctl binary (the project name is mvm; the binary is named mvmctl) |
Plus the same env vars as emit (for .py/.ts entries) and compile.
mvmctl’s stdout, stderr, and exit status pass through unmodified per
ADR-0005 §5.
Output canonicalization
All structured output (validate results, emit IR, up’s post-validation
forwarded IR) is canonical JSON per RFC 8785:
- Object keys sorted lexicographically.
- No whitespace.
- Standard string escaping.
- Integer-only numerics (the v0 IR has no floats).
Two compiles or emits over the same input produce byte-identical output.