CLI

voxx init [blog|docs|changelog] [--dir <content>] [--base <path>] [--app <dir>] [--force]
voxx init --add [blog|docs|changelog] [--name <name>] [--dir <dir>] [--base <path>] [--app <dir>]
voxx new "Title" [--collection <name>] [--dir <content>] [--date <YYYY-MM-DD>] [--slug <slug>] [--flat] [--section <path>] [--order <n>]
voxx build [--out <dir>] [--drafts]
voxx dev [--port <n>]
voxx telemetry [status|enable|disable]

The CLI is a convenience layer — everything it does, you could do by hand with files and @prudentbird/voxx-core.

voxx init [preset]

Scaffolds a surface. The preset (default blog) picks the sample content and routes; the flags place them:

FlagDefaultWhat it does
--base /notes/<preset>Mount path — scaffolded routes follow it
--dir contentcontentContent folder written into voxx.json
--app src/appauto-detectedThe Next.js app directory
--cache-componentsauto-detectedForce the Cache Components data layer
--no-cache-componentsauto-detectedForce the static data layer
--forceoffOverwrite existing files (default: skip them)

With a Next.js app detected, init writes the routes for the preset, the _voxx/ data layer and components, llms.txt and llms-full.txt routes, plus a sitemap and robots.ts (blog, docs) and an RSS route at <base>/rss.xml (blog, changelog) where the type calls for them. On Next 16+ it also wraps your next.config with withVoxx (from @prudentbird/voxx-core/next) when the config's shape is unambiguous — otherwise it tells you what to add.

init scaffolds the static data layer by default, which needs no rendering-mode changes. When your next.config already enables cacheComponents: true, it scaffolds the Cache Components data layer instead. Pass --cache-components or --no-cache-components to pick the variant directly.

If your app already defines design tokens (--background and friends in a globals.css), Voxx inherits them; if not, init adds a starter voxx-globals.css.

Without Next.js, init asks: static site (just voxx.json + content, rendered by voxx build) or a new app via create-next-app. In a non-interactive shell it defaults to static.

init is idempotent — existing files are skipped and reported, never overwritten, unless you pass --force.

voxx init --add <preset>

Adds a second (or third…) collection to a site that already has a voxx.jsonvoxx init --add docs on a blog gives you a multi-collection site:

FlagDefaultWhat it does
--name notesthe preset nameThe collection's name — what voxx new --collection and getPosts({ collection }) use
--dir content/notescontent/<name>The new collection's content folder
--base /notes/<name>Mount path for the new collection's routes
--app src/appauto-detectedThe Next.js app directory

It rewrites voxx.json (migrating a single-collection content config to a collections array — resolved behavior is preserved exactly), then scaffolds only the new collection's content samples and routes. Site-wide files (sitemap.ts, robots.ts, the llms.txt routes) are left alone if present and created only when missing.

--add never overwrites: it requires an existing voxx.json, refuses --force, and fails — writing nothing — if the new collection's name, dir, or basePath collides with an existing one. Pass --name, --dir, or --base to resolve a collision.

Note that feature defaults (rss, toc, …) follow the first collection's type — review features in voxx.json after adding a collection of a different type.

voxx new "Title"

Creates a content file, shaped by the collection type in voxx.json:

Typevoxx new "X" createsUseful flags
blog2026-06-11-x.md--date, --slug, --flat (no date prefix)
docsx.md--section guides, --order 3guides/03-x.md
changelogX.md with version: set— (the title is the version)

On a multi-collection site, --collection <name> picks which collection the file lands in — voxx new "Install" --collection docs writes a docs page even when the blog is listed first. Without the flag, the first collection in voxx.json wins. An unknown name fails and lists the defined collections.

If the slug is taken, voxx new proposes a free one (x-2) — interactively when it can, automatically when it can't. It never overwrites.

voxx build

Renders every collection to static HTML in ./dist — pages, styles, images and other content assets, and the outputs your feature flags ask for (rss.xml, sitemap.xml, robots.txt, llms.txt, llms-full.txt).

FlagDefaultWhat it does
--out publicdistOutput directory
--draftsoffInclude draft: true pages (a collection's drafts: true in voxx.json also works)

See Static sites for what each content type produces.

voxx dev

A local preview server for static sites: builds to a temp directory, watches voxx.json and your content folders, rebuilds on change, and serves the result. Drafts are included by default — voxx dev is the draft-preview story.

FlagDefaultWhat it does
--port 80804321Port to listen on

voxx telemetry [status|enable|disable]

Manages anonymous usage telemetry. Voxx reports a single anonymous event per command — the command name, whether it succeeded, its duration, and the package, Node, and OS versions. It never collects arguments, file paths, names, or content, and the CLI prints a one-time notice on first run.

SubcommandWhat it does
statusPrints the resolved state and any env override
disableOpts out (persisted)
enableOpts back in (persisted)

Per-invocation opt-out is also honored via the VOXX_TELEMETRY_DISABLED=1, DO_NOT_TRACK=1, or CI=1 environment variables — telemetry is off automatically in CI. The persistent setting lives in ${XDG_STATE_HOME:-~/.local/state}/voxx/telemetry.json.

The same engine powers @prudentbird/voxx-core, which reports one anonymous core_used event per process plus anonymous per-call core API events when used directly without the CLI; the opt-out variables above apply there too.