---
title: The hollware CLI
description: Every command of the hollware CLI, which works on the project in the current directory through its wrangler.
section: reference
order: 1
---

# The hollware CLI

The CLI comes with every project as a dev dependency. Run it with `npx hollware` or `pnpm exec hollware`, from inside the project: it reads the project's `wrangler.jsonc` and runs its own wrangler. Every command answers `--help`.

Commands that touch the database take `--local` (the default) or `--remote`, and `--database` for another D1 database than the binding `DB`. Commands about a site take `--site` when the database has several.

## init

```sh
hollware init --site my-site [--preset blog | docs | empty] [--locales en,es] [--owner-name "Ada"]
              [--ip-addresses off | hashed] [--audit-retention-days 365]
              [--token-file owner.token] [--json]
```

Creates the site, its owner and a first personal token, and prints a link to set up the owner's passkey. The site starts from a preset, a blog in English unless you say otherwise, which you then shape in the admin. On a database that has an owner already, it adds the site to that owner. A project that still has a `hollware.config.ts` keeps it: its Worker moves it into the database. `--ip-addresses` and `--audit-retention-days` choose what the site's activity log keeps: no addresses and every line unless you say otherwise ([Tokens, OAuth and passkeys](/docs/security/#activity-log)).

For an agent, two flags help on every command that makes a token or an answer: `--token-file <path>` writes the token to a file only you can read (mode 0600) and prints the path instead, and `--json` prints one JSON object and nothing else (`init`, `token create`, `invite`, `doctor`, and `npm create hollware`).

## dev

```sh
hollware dev                 # in the foreground, until Ctrl+C
hollware dev --detach        # in the background; it prints the URL and returns
hollware dev --stop          # stops the one --detach started
```

Starts the project's local server and says `Hollware is ready at http://localhost:5199` once it answers. Ctrl+C, or `--stop`, ends it and every process it started. `--json` prints the URL as JSON, for an agent.

## mcp-config

```sh
hollware mcp-config [--client claude-code | cursor | vscode | json] [--url https://cms.example.com]
```

Prints what connects an MCP client to this Hollware: the `claude mcp add` line for Claude Code, or the JSON block of `.mcp.json` for Cursor, VS Code and the others. The header names the environment variable `HOLLWARE_TOKEN`, never the token: set it from your token file with `export HOLLWARE_TOKEN="$(cat owner.token)"`.

## migrate

```sh
hollware migrate [--check]
```

Applies the migrations the database lacks. With `--remote` it first exports a backup to `.wrangler/hollware-backups`, unless the database is new. D1 cannot export a database with a full-text index, which every Hollware has from 0.5 on: then it takes a Time Travel bookmark instead, and prints the command that restores the database to it. `--check` only lists what is pending.

## deploy

```sh
hollware deploy [--url https://cms.example.com]
```

Deploys with wrangler, which creates the missing resources the first time (the database, the namespace, the queues and the bucket of images), sets the public URL, makes `HOLLWARE_SECRET` when the Worker has none (it seals the secrets Hollware makes, such as those of webhooks), and migrates the remote database. A project deployed before is migrated first, while its Worker still serves, so the new Worker never serves a database without its tables. `--url` on a domain of your own also writes its route into `wrangler.jsonc` as a custom domain.

## doctor

```sh
hollware doctor [--remote] [--json]
```

Checks the flags, the public URL, the bindings (the bucket and the Images binding of [images](/docs/images/) among them), the cron, the events queue, the rate limit, the built admin, the migrations and the owner of the local database, or the remote one with `--remote`, and says what to fix. A healthy project ends with "Everything Hollware needs is in place.

## token

```sh
hollware token create --label ci [--scopes content:read,content:write] [--expires-in-days 30] [--token-file ci.token] [--json]
hollware token create --label my-site --read
hollware token list
hollware token revoke tok_...
```

A token expires after `--expires-in-days`, 1 to 365, and never without it; `hollware token revoke` ends it at once. The first token of `hollware init` expires in 90 days.

## invite

```sh
hollware invite --role editor
hollware invite --owner
```

## import

```sh
hollware import ./content --url https://cms.example.com --token-file ./token.txt [--publish] [--dry-run]
```

Imports a directory laid out as `<collection>/<locale>/<slug>.md`, over MCP, with the images of its `_assets/` when it has them. It validates every file first and writes nothing if one would be refused; running it again changes nothing.

To move a Nuxt Content site, `--from nuxt-content` reads its `content/` as the files Hollware imports:

```sh
hollware import ./content --from nuxt-content --collection docs --locale-dirs --url https://cms.example.com --token-file ./token.txt
```

A page keeps its Markdown, with its slug as Nuxt Content routes it and a `title` from its first heading when it has none. With `--locale-dirs`, the first folder is the locale, and the pages at one path are translations of each other.

## export

```sh
hollware export ./backup --url https://cms.example.com --token-file ./token.txt [--published] [--collection blog] [--locale en]
                [--assets public/images/cms --assets-url /images/cms/] [--dry-run]
```

Writes every entry as `<collection>/<locale>/<slug>.md`, exactly as Hollware keeps it, into an empty directory: drafts included, or only what is published with `--published`. `hollware import` takes it back unchanged, so an export is also a backup of your content in plain files.

The images the entries show go to `_assets/`, as they were uploaded, with an `assets.json` that `hollware import` uploads again before the entries. With `--assets <dir> --assets-url <path>`, they go to `<dir>` as they are served instead, and every `asset:` reference points at `<path>`: for a site that builds from the export and serves its images itself. See [Images](/docs/images/#your-images-on-your-site).

With `--published`, the entries that moved to another slug are in `redirects.json` too, each with its old and its new path: a static site turns them into 301s.

## backup

```sh
hollware backup list --url https://cms.example.com --token-file ./owner.token
hollware backup get 2026-10-18 ./restore --url https://cms.example.com --token-file ./owner.token [--published]
```

The daily backups that your Hollware keeps in its R2 bucket ([Deploy](/docs/deploy/#restore)). `list` says which there are, with their size. `get` writes the one of a date into an empty directory as `<collection>/<locale>/<slug>.md`, the layout `hollware import` reads, with `site.json`, the definition of the site: the latest revision of every entry out of the trash, or only what was published with `--published`. Both take a personal token of an owner (`schema:admin`).
