Skip to main content
Reference

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

From @blinkk/create-root v4.0.0

create-root

create-root [dir] [options]
Argument Description
[dir] Output dir
Option Description
--template [template] Template to use: "starter" (Root CMS) or "minimal" (hello world) Default: "starter"
--repo [repo] Github repo to pull from Default: "blinkk/rootjs/examples"
--skip-gcp-setup Don't offer to set up Google Cloud for Root CMS templates

root

From @blinkk/root v4.0.0

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

From @blinkk/root-cms v4.0.0

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 setup

Sets up a google cloud project for root cms: checks gcloud sign-in, then configures firebase, firestore, storage, iam and secrets

root-cms setup [options]
Option Description
--project <project> Gcp project id (skips the new/existing question)
--site-id <siteId> Site id, used to keep sites on one gcp project apart
--location <location> Region for a new firestore database and storage bucket
--dry-run Print what would change without changing anything
--yes Accept the default answer to every question

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)
Examples
$ 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)
Examples
$ 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
Examples
$ 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")
Examples
$ 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")
Examples
$ 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")
Examples
$ root-cms docs.upload Pages ./Pages
$ root-cms docs.upload Pages ./my-pages --mode published

root-cms assets.upload

Uploads files to the asset library

Files are uploaded to the GCS bucket (and registered with the Google Cloud Image service for images when gci is enabled). If the folder already has a file with the same name, the asset is replaced and the new file is synced to every draft doc that uses it. Directories are uploaded recursively, mirroring their structure as subfolders.

root-cms assets.upload <paths...> [options]
Argument Description
<paths> Required.
Option Description
--folder <folder> Asset library folder to upload into, e.g. "marketing/q1" (default: root)
--name <name> Asset name (single file only)
--asset-id <assetId> Id of an existing asset whose file should be replaced (single file only)
--alt <text> Alt text for the uploaded file(s)
--naming-mode <mode> Gcs object naming: "hash", "hash-path" or "clean" (default: folder setting)
--cache-control <value> Cache-control header for the file(s)
--no-gci Skip registering images with the gci service
--no-sync Skip updating docs that use a replaced asset
--modified-by <email> Email attributed as the author
Examples
$ root-cms assets.upload ./hero.png
$ root-cms assets.upload ./hero.png --folder marketing --alt "Hero image"
$ root-cms assets.upload ./new-hero.png --asset-id AbC123dEf456
$ root-cms assets.upload ./icons --folder brand

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.
Examples
$ 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
Examples
$ 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.
Examples
$ 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
Examples
$ 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
Examples
$ 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
Examples
$ 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-cms translations.migrate

Migrates v1 translations to the v2 translations manager

Requires experiments: {v2TranslationsManager: true}. The CMS runs this automatically on the first root dev or root build. Run it on demand to migrate as a deliberate step, e.g. when opting in. The v1 translations are left in place as a backup, and the migrated translations are published.

root-cms translations.migrate [options]
Option Description
--status Print the migration status without migrating
--force Re-run a completed migration (overwrites v2 edits to migrated strings)
Examples
$ root-cms translations.migrate --status
$ root-cms translations.migrate
$ root-cms translations.migrate --force

root-password-protect

From @blinkk/root-password-protect v4.0.0

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.
1
2
3
4
5
6
7
8
9
10
11
12
Breakpoint: