The kovo & vp CLIs
Kovo projects use two distinct binaries, and keeping them straight saves confusion:
vpis the project / toolchain runner — Vite+ (vite-plus). It is how you run the dev server, build, test, typecheck, and run named project tasks. Day-to-day,vpis the command you type most.kovois the framework CLI. It answers questions about your app's graph — coverage, invalidation, guards, audits — and emits compiler-backed artifacts. It is the legibility surface:kovo explainprints the same stable, diffable text humans and agents both read.
The two compose: vp orchestrates, and kovo is often invoked through a vp task. For example,
vp run kovo-check is a project task that runs kovo check under the hood (the repo wires this as
the check:kovo npm script).
vp — the toolchain runner#
vp is the Vite+ runner. Its everyday commands:
| Command | What it does |
|---|---|
vp dev |
Start the dev server. Regenerates Kovo registries before typechecking (so a stale registry is unrepresentable), serves pages, and reports compiler diagnostics through Vite's overlay and terminal. |
vp build |
Build the app and component packages for production. |
vp test |
Run the project's test suites. |
vp check |
Typecheck + lint. Regenerates registries first, then runs TypeScript static checking over all wiring (handlers, routes & links, forms, targets, bindings, IDREFs, guards). |
vp run <task> |
Run a named task from the Vite+ config — the general escape hatch for project-defined scripts. |
vp pack |
Package the project / component library for publishing. |
vp check is where the framework's type-level guarantees land: it regenerates the registry .d.ts
files and runs tsc, so route renames, missing form fields, and dead links all surface as type
errors (this is the propagation property from routing).
In practice, a repo wires these into npm scripts that combine vp with extra gates:
{
"scripts": {
"check": "vp check && vp run typecheck-examples",
"check:kovo": "vp run kovo-check", // a vp task that runs `kovo check`
"test:integration": "vp run integration",
"test:browser": "vp run browser",
},
}So npm run check:kovo → vp run kovo-check → kovo check. The npm script is the convenience name;
vp is the runner; kovo does the graph work.
kovo — the framework CLI#
kovo with no arguments lists its subcommands:
$ kovo
kovo: add, audit, build, check, compile, explain, export, mcpEvery command emits stable, versioned, diffable output (kovo-check/v1, kovo-explain/v1, …) — the
same artifact a reviewer reads and an agent consumes.
kovo check — the graph/coverage check#
Runs the framework's consistency and exhaustiveness verifier over the app graph: touch-graph consistency, optimistic exhaustiveness (KV310), update coverage (KV311), and the fixpoint / render-equivalence invariants. The two sub-checks are positional, not dash-flags:
kovo check # full consistency check
kovo check optimistic # optimistic exhaustiveness only
kovo check coverage # update-coverage (every query/state position has a status)
kovo check coverage graph.json # against a pre-emitted graph artifactkovo explain — print the decision tree#
kovo explain is the compiler's decision tree on demand. It has two shapes: explain a single subject,
or run a stable machine-ingress/auth audit.
Explain a subject — kovo explain <kind> <target> [graph.json], where <kind> is one of
component, mutation, query, page, context:
kovo explain component cart # extracted handlers, derives, capture channels, platform substitutions, attribute merges, triggers
kovo explain query cart # read set, consumers, every mutation that invalidates it
kovo explain mutation cart/add # writes → domains → invalidated queries → consumers; guard chain
kovo explain page /products/:id # modulepreloads, prefetch config, param/search schemas, query payloadsTwo target-specific flags:
kovo explain mutation cart/add --optimistic # transform coverage per query; derivation traces + punts
kovo explain page /products/:id --layouts # the page's resolved layout chainRun an audit — these are mutually-exclusive modes that scan the whole app, each accepting an
optional --fail-on-findings to make CI block on results:
kovo explain --unguarded [--fail-on-findings] [graph.json] # everything reachable without authentication
kovo explain --unscoped [--fail-on-findings] [graph.json] # rows not tied to a principal via the owner: annotation
kovo explain --endpoints [graph.json] # the machine-ingress audit (see below)--unguardedlists every mutation, route, and query reachable without auth — the audit guards enroll pages in (see routing) and mutations enroll in (see mutations).--unscopeduses the schema'sowner:annotation to flag data not tied to a principal.--endpointsis the stable security-review surface: a diffable table of every declaredendpoint()andwebhook(), plus every route returningrespond.file()/respond.stream(), with name, method, path, mount mode, auth scheme, and CSRF posture (checkedorexempt:<justification>).
kovo add — vendor a UI component#
Copies a vendored @kovojs/ui component into your app source (shadcn-style — it becomes your code,
not a dependency):
kovo add button card dialog # copy into the default src/components/ui
kovo add tabs --out src/components/ui # choose the destinationThe catalog covers the headless-UI family (accordion, alert-dialog, autocomplete, button, checkbox, combobox, dialog, dropdown-menu, popover, select, tabs, toast, toggle, tooltip, and more — see components).
kovo build — production build of an app module#
Builds a Kovo app module into a preset production output:
kovo build ./src/app.ts # → dist/
kovo build ./src/app.ts --out build --preset vercel--preset selects the deployment target (node, vercel, cloudflare); --out overrides the
output directory (default dist). See deployment.
kovo compile — emit compiler-backed artifacts#
Emits lowered IR and graph facts without importing @kovojs/compiler directly — the same lowering the
dev server and build use, exposed as a command (useful for tooling, fixtures, and the fixpoint gate).
It takes a target subcommand:
kovo compile component src/cart-badge.tsx --out cart-badge.kovo.tsx [--check] [--fixpoint] [--render-equivalence]
kovo compile route src/app.tsx --out app.route.tsx [--check]
kovo compile graph input.json --out graph.json [--check]
kovo compile mutation-inputs src/cart.mutations.ts --out facts.json
kovo compile drizzle-static input.json --out facts.json
kovo compile drizzle-optimistic input.json --out optimistic.ts
kovo compile package-css @acme/primitives --out primitives.cssThe component target's --fixpoint and --render-equivalence flags exercise the compiler's hard
invariants — that the lowered IR is valid input (compile(compile(src)) === compile(src)) and renders
byte-identically to source.
kovo audit — security/access audits#
Runs the security and access audits over the app graph as one command:
kovo audit [--fail-on-findings] [graph.json]This rolls up the same auth/ingress posture the explain --unguarded/--unscoped/--endpoints
modes surface, in a form CI can block on with --fail-on-findings.
kovo export — static export#
Statically exports an app module to disk — replaying synthetic GET requests through the same handler, so there is no second render path:
kovo export ./src/app.ts --out dist [--origin https://example.com] [--skip-non-exportable]
kovo export ./src/app.ts --vite --root . --out dist # load the module via Vite SSRExport is L0/L1 only: a route with a guard, unproven session dependence, mutation-only interaction,
or a param path without enumerated staticPaths fails or skips loudly with KV229, according to
the export policy (--skip-non-exportable chooses skip). See deployment.
kovo mcp — Model Context Protocol server#
Runs an MCP server over stdio (newline-delimited JSON-RPC), exposing the same structured diagnostics
and compile/check/explain results to agents:
kovo mcpMCP is a rendering/query surface over the existing diagnostics, not a second diagnostic channel — an agent gets the identical codes, severities, and help text a human sees.
How they compose#
npm script → vp → kovo
─────────────────────────────────────────────
npm run check → vp check (typecheck + lint, regenerates registries)
npm run check:kovo → vp run kovo-check → kovo check (graph consistency + coverage)
npm run test:* → vp run <task> (project test suites)Use vp to run things; use kovo to ask the graph questions and emit artifacts. In CI a typical
gate is vp check (TypeScript proves all wiring) followed by kovo check (the framework proves
touch-graph consistency, optimistic exhaustiveness, and update coverage) — together they make an app's
wiring proof-carrying without executing a browser.
Next#
- Reading kovo check & kovo explain — interpreting the output in depth.
- Deployment —
kovo buildpresets andkovo export. - Testing — what
vp testruns and the browser-free verification surface.
Spec & diagnostics
The compiler pipeline, hard rules (1:1 mapping, fixpoint, registry atomicity that vp dev/vp check
rely on), and kovo explain sub-commands: SPEC §5.1–5.3. The verification surface — TypeScript
checking, kovo check, graph queries over kovo explain, and the --endpoints machine-ingress
audit: SPEC §11.4. Diagnostic severities and blocking policy: SPEC §11.3. Static export (kovo export, KV229) and the request shell: SPEC §9.5. The CLI command surface (subcommands, flags,
positional sub-checks) is verified against packages/cli/src/commands-manifest.ts and the
index.kovo-*.test.ts suites.