CLI reference
Root.js ships a few command-line tools. Run them with pnpm exec (or through a package.json script) from your project directory:
-
create-root: scaffolds a new project (pnpm create @blinkk/root). -
root: runs, builds and deploys the site. -
root-cms: sets up the CMS, generates types, and reads and writes content. -
root-password-protect: tools for password-protected pages.
This reference is generated from the source code.
create-root
create-root
create-root [dir] [options]| Argument | Description |
|---|---|
[dir] |
Output dir |
| Option | Description |
|---|---|
--template [template] |
Template to use Default: "starter" |
--repo [repo] |
Github repo to pull from Default: "blinkk/rootjs/examples" |
root
| Global options | Description |
|---|---|
-q, --quiet |
Quiet |
root build
Generates a static build
root build [path] [options]
| Argument | Description |
|---|---|
[path] |
Optional. |
| Option | Description |
|---|---|
--ssr-only |
Produce a ssr-only build |
--mode <mode> |
See: https://vitejs.dev/guide/env-and-mode.html#modes Default: "production" |
-c, --concurrency <num> |
Number of files to build concurrently Default: "10" |
--threads [num] |
Renders pages using worker threads; pass a number for exactly N workers, or omit the value (or pass "auto") to pick based on cpu cores and page count |
--filter <urlPathRegex> |
Builds the url paths that match the given regex, e.g. "/products/.*" Default: "" |
--log <mode> |
Build log output: "progress" (default) shows a progress indicator and a final summary, "verbose" prints one line per output file, "quiet" prints only the final summary One of: progress, verbose, quiet. |
root codegen
Generates boilerplate code
root codegen [type] [name] [options]
| Argument | Description |
|---|---|
[type] |
Optional. |
[name] |
Optional. |
| Option | Description |
|---|---|
--out <outdir> |
Output dir |
root create-packagealias: package
Creates a standalone npm package for deployment to various hosting services
root create-package [path] [options]
| Argument | Description |
|---|---|
[path] |
Optional. |
| Option | Description |
|---|---|
--target <target> |
Hosting target, i.e. appengine or firebase |
--out <outdir> |
Output dir |
--mode <mode> |
Deployment mode, i.e. production or preview |
--app-yaml <path> |
For appengine targets, path to app.yaml (defaults to "app.yaml") |
root dev
Starts the server in development mode
root dev [path] [options]
| Argument | Description |
|---|---|
[path] |
Optional. |
| Option | Description |
|---|---|
--host <host> |
Network address the server should listen on, e.g. 127.0.0.1 |
root gae-deploy
Appengine deploy utility that can optionally run healthchecks before diverting traffic to the new version and clean up old versions
root gae-deploy <appdir> [options]
| Argument | Description |
|---|---|
<appdir> |
Required. |
| Option | Description |
|---|---|
--project <project> |
GCP project id |
--prefix <prefix> |
Prefix to append the version |
--promote |
Whether to promote the version (if healthchecks pass) |
--healthcheck-url <url> |
Healthcheck url path (e.g. "/healthcheck") which should return a 200 status with the text "OK" |
--max-versions <num> |
The max number of versions to keep |
root preview
Starts the server in preview mode
root preview [path] [options]
| Argument | Description |
|---|---|
[path] |
Optional. |
| Option | Description |
|---|---|
--host <host> |
Network address the server should listen on, e.g. 127.0.0.1 |
root start
Starts the server in production mode
root start [path] [options]
| Argument | Description |
|---|---|
[path] |
Optional. |
| Option | Description |
|---|---|
--host <host> |
Network address the server should listen on, e.g. 127.0.0.1 |
root secrets
Manage shared secrets backed by Google Cloud Secret Manager (requires the gcloud CLI)
root secrets
root secrets init
Create a secrets manifest
root secrets init [options]
| Option | Description |
|---|---|
--gcp-project <id> |
GCP project id |
--gsm-key <key> |
Secret Manager key for this manifest |
--manifest <path> |
Manifest path (defaults to ./.root.secrets.json) |
--import <path> |
Path to a shared manifest to import keys from |
--import-keys <names> |
Comma-separated subset of shared keys to import |
root secrets set
Store a secret value, read from a prompt (TTY) or piped stdin
root secrets set <name> [options]
| Argument | Description |
|---|---|
<name> |
Required. |
| Option | Description |
|---|---|
--manifest <path> |
Target manifest (defaults to ./.root.secrets.json) |
root secrets rm
Remove a secret
root secrets rm <name> [options]
| Argument | Description |
|---|---|
<name> |
Required. |
| Option | Description |
|---|---|
--manifest <path> |
Target manifest (defaults to ./.root.secrets.json) |
root secrets sync
Three-way merge managed secrets into .env
root secrets sync
root secrets pull
Force-download managed secrets into .env (overwrites local edits)
root secrets pull
root secrets push
Push .env values up to Secret Manager and record them in the manifest
root secrets push [options]
| Option | Description |
|---|---|
--manifest <path> |
Target manifest (defaults to ./.root.secrets.json) |
--keys <names> |
Comma-separated subset of .env keys (default: all) |
--yes |
Skip the confirmation prompt |
root secrets status
Show managed secrets and their sync status (no network)
root secrets status
root-cms
| Global options | Description |
|---|---|
-q, --quiet |
Quiet |
root-cms init-firebasealias: init
Inits the firebase project proper security rules
root-cms init-firebase [options]
| Option | Description |
|---|---|
--project <project> |
Gcp project id |
--admin <email> |
Adds an admin to the project |
root-cms generate-typesalias: types
Generates root-cms.d.ts from *.schema.ts files in the project
root-cms generate-types
root-cms export
Exports firestore data to a local directory
By default, all content in the Firestore database associated with the CMS will be exported.
A unique new directory will be created for each export.
File naming conventions: - Documents that act as containers for subcollections are exported as directories containing a __data.json file for the document's own data. - Standalone documents are exported as JSON files named after their document ID (e.g. page.json). - For collections like ActionLogs and Translations, the document ID (often a hash) is used as the filename.
Example output: <output>/Collections/Pages/Draft/... <output>/Collections/Pages/Published/... <output>/ActionLogs/...
root-cms export [options]
| Option | Description |
|---|---|
--filter <pattern> |
Comma-separated list of glob patterns to filter content (e.g. Collections/Pages/**, !ActionLogs/**) |
--site <siteId> |
Site id to export (overrides root config) |
--database <databaseId> |
Firestore database id (overrides root config, default: "(default)") |
--project <projectId> |
Gcp project id (overrides root config) |
$ root-cms export
$ root-cms export --filter "Collections/Pages/**"
$ root-cms export --filter "Collections/Pages/**,!Collections/Pages/Draft/**"
root-cms import
Imports firestore data from a local directory
root-cms import [options]
| Option | Description |
|---|---|
--dir <directory> |
Directory to import from (required) |
--filter <pattern> |
Comma-separated list of glob patterns to filter content (e.g. Collections/Pages/**, !ActionLogs/**) |
--site <siteId> |
Site id to import to (overrides root config) |
--database <databaseId> |
Firestore database id (overrides root config, default: "(default)") |
--project <projectId> |
Gcp project id (overrides root config) |
$ root-cms import --dir export_project_site_20251209t1305
$ root-cms import --dir export_project_site_20251209t1305 --filter "Collections/Pages/**"
root-cms docs.get
Fetches a single doc and outputs it as JSON
If an output path is provided, writes to a file. Otherwise, writes to stdout.
root-cms docs.get <docId> [outputPath] [options]
| Argument | Description |
|---|---|
<docId> |
Required. |
[outputPath] |
Optional. |
| Option | Description |
|---|---|
--mode <mode> |
Doc mode: "draft" or "published" (default: "draft") |
--raw |
Output raw firestore data without unmarshaling |
$ root-cms docs.get Pages/home
$ root-cms docs.get Pages/home ./out/home.json
$ root-cms docs.get Pages/home --mode published
$ root-cms docs.get Pages/home | jq .fields
root-cms docs.set
Updates a single doc from a JSON file or stdin
If a filepath is provided, reads from the file. Otherwise, reads from stdin.
root-cms docs.set <docId> [filepath] [options]
| Argument | Description |
|---|---|
<docId> |
Required. |
[filepath] |
Optional. |
| Option | Description |
|---|---|
--mode <mode> |
Doc mode: "draft" or "published" (default: "draft") |
$ root-cms docs.set Pages/home home.json
$ root-cms docs.set Pages/home home.json --mode published
$ cat data.json | root-cms docs.set Pages/home
root-cms docs.download
Downloads all docs in a collection to a local directory
root-cms docs.download <collection> [outputDir] [options]
| Argument | Description |
|---|---|
<collection> |
Required. |
[outputDir] |
Optional. |
| Option | Description |
|---|---|
--mode <mode> |
Doc mode: "draft" or "published" (default: "draft") |
$ root-cms docs.download Pages
$ root-cms docs.download Pages ./my-pages
$ root-cms docs.download Pages --mode published
root-cms docs.upload
Uploads docs from a local directory to a collection
root-cms docs.upload <collection> <dir> [options]
| Argument | Description |
|---|---|
<collection> |
Required. |
<dir> |
Required. |
| Option | Description |
|---|---|
--mode <mode> |
Doc mode: "draft" or "published" (default: "draft") |
$ root-cms docs.upload Pages ./Pages
$ root-cms docs.upload Pages ./my-pages --mode published
root-cms client.call
Calls a method on the RootCMSClient with JSON-encoded arguments
Designed for AI agents. Arguments are a JSON array of positional args passed on the command line. When jsonArgs is omitted the method is called with no arguments; pass - to read the JSON args from stdin. The result is printed to stdout as a JSON envelope: {"ok": true, "result": <value>} {"ok": false, "error": "<message>"}
Run root-cms client.methods to discover available methods and their argument signatures.
root-cms client.call <method> [jsonArgs]
| Argument | Description |
|---|---|
<method> |
Required. |
[jsonArgs] |
Optional. |
$ root-cms client.call getDoc '["Pages", "home", {"mode": "draft"}]'
$ root-cms client.call listDocs '["Pages", {"mode": "published"}]'
$ root-cms client.call publishScheduledDocs
$ echo '["Pages", "home", {"mode": "draft"}]' | root-cms client.call getDoc -
root-cms client.methods
Lists the methods available on the RootCMSClient
Designed for AI discovery of available functionality. Prints each method's signature and description.
root-cms client.methods [options]
| Option | Description |
|---|---|
--json |
Output machine-readable JSON |
--types |
Include referenced type/interface definitions |
$ root-cms client.methods
$ root-cms client.methods --json
$ root-cms client.methods --json --types
root-cms proposal.check
Checks a CMS change proposal without touching the database
Parses the YAML, checks it against the proposal format, and prints a summary of the changes it describes. Collection schemas are not checked here (that needs db access — use proposal.diff). Exits non-zero on any error, so it works as a CI gate on a pull request.
root-cms proposal.check <file>
| Argument | Description |
|---|---|
<file> |
Required. |
$ root-cms proposal.check cms-proposals/hero-refresh.yaml
root-cms proposal.diff
Resolves a proposal against the live database and reports what it would write, without writing anything
root-cms proposal.diff <file> [options]
| Argument | Description |
|---|---|
<file> |
Required. |
| Option | Description |
|---|---|
--skip-validation |
Skip collection schema validation |
$ root-cms proposal.diff cms-proposals/hero-refresh.yaml
root-cms proposal.apply
Applies a CMS change proposal to the database
Writes drafts, release contents, and draft translations only — never publishes, schedules, or deletes. Nothing is written unless every change in the proposal resolves cleanly.
By default a proposal's recorded before values are treated as documentation for the human reviewer and are not checked against the database. Pass --verify-before to fail on drift instead.
root-cms proposal.apply <file> [options]
| Argument | Description |
|---|---|
<file> |
Required. |
| Option | Description |
|---|---|
--dry-run |
Resolve and validate everything, but write nothing |
--verify-before |
Fail if a recorded `before` value no longer matches the database |
--skip-validation |
Skip collection schema validation |
--modified-by <email> |
Email attributed as the author |
$ root-cms proposal.apply cms-proposals/hero-refresh.yaml
$ root-cms proposal.apply cms-proposals/hero-refresh.yaml --dry-run
$ root-cms proposal.apply cms-proposals/hero-refresh.yaml --verify-before
root-cms skill.install
Installs the bundled agent skills
Copies the skills (which teach AI coding agents how to use the root-cms client.* commands, and how to propose and apply CMS change proposals) into a local skills directory.
When no directory is given, existing agent skills directories are auto-detected (e.g. .claude/skills, .agent/skills, or any .*/skills dir already in the project) so Root does not assume a specific AI provider. If none is found, it installs to .agent/skills.
root-cms skill.install [dir] [options]
| Argument | Description |
|---|---|
[dir] |
Optional. |
| Option | Description |
|---|---|
--force |
Overwrite the skill if it is already installed |
--skill <name> |
Install only the named skill |
$ root-cms skill.install
$ root-cms skill.install ./my-agent/skills
$ root-cms skill.install --skill root-cms-propose
$ root-cms skill.install --force
root-password-protect
| Global options | Description |
|---|---|
-q, --quiet |
Quiet |
root-password-protect generate-hash
Generates a hash/salt pair from a plain-text password
root-password-protect generate-hash <password>
| Argument | Description |
|---|---|
<password> |
Required. |