Skip to content

The manablox command

manablox is the command line tool that creates, updates and starts your CMS. This page lists every command and every option. For a guided first run, start with Create your CMS instead.

There are two ways, depending on whether you already have a project:

  • To create something new, run it straight from npm without installing it: pnpm dlx @manablox/cli create my-cms or pnpm dlx @manablox/cli frontend my-site (npx @manablox/cli ... works the same).
  • Inside a project made by manablox create, the command is already installed. Use the scripts in package.json (pnpm dev, pnpm migrate) or pnpm exec manablox <command> for everything else.

Run the commands in your project folder: that is where manablox looks for the config file and .env.

CommandWhat it does
manablox create [dir]Creates a new CMS project in a folder
manablox frontend [dir]Creates a starter website for a space
manablox startStarts the CMS
manablox migrateBrings the database up to date
manablox backup <file>Copies a SQLite database into a file while the CMS runs
manablox syncWrites the workflows, webhooks, credentials and templates declared in code into the database
manablox push-keysPrints a key pair for push notifications
  • An option with a value can be written as --port 3000 or --port=3000.
  • A yes or no option has two forms: --install and --no-install.
  • An option the command does not know stops it with manablox: unknown option '--xyz'; see manablox --help. A typo never goes unnoticed.
  • -h or --help prints the built-in help text for all commands.
  • manablox without a command also prints the help text, but ends with an error code.

start, migrate, backup and sync read your configuration. They look for it like this:

  1. First they load the file .env from the folder you run the command in, if it exists. A variable that is already set in your terminal wins over the value in .env.
  2. Then they load the config file: the one given with --config <file> (relative to the current folder), or else the first of manablox.config.ts, manablox.config.mts, manablox.config.js or manablox.config.mjs in the current folder.

The config file must export its configuration as the default export (export default defineConfig({ ... })); a named export called config works too.

If no config file is found, you see no manablox.config.ts in <folder>; create one or pass --config <file>, or config file not found: <path> when the file given with --config does not exist. Both usually mean you are not in your project folder.

create, frontend and push-keys read neither file.

Starts the CMS and keeps running until you stop it with Ctrl+C.

Terminal window
pnpm exec manablox start
pnpm exec manablox start --watch
pnpm exec manablox start --config manablox.public.config.ts

In a project made by manablox create, the scripts do this for you: pnpm dev runs manablox start --watch, pnpm start runs manablox start, and pnpm dev:public and pnpm start:public do the same with --config manablox.public.config.ts for the public API.

OptionDefaultMeaning
--config <file>manablox.config.tsThe config file to load
--watchoffRestart whenever the config file or any file it imports changes (for example content-model.ts or your plugins)
--mode <mode>from the config, else managementmanagement runs the admin and the management API, public runs the read-only public API. Anything else stops with an error
--port <port>from the configThe port to listen on
--host <host>from the configThe network address to listen on, for example 0.0.0.0 for all

When the CMS is ready, the log shows manablox listening (or manablox public api listening) with its address. If the config is not valid, it prints manablox: the configuration is invalid followed by one line per problem, and stops.

Creates the database tables, or brings them up to date after an update of Manablox. Run it once for a new database and after every update. It is safe to run it again: it only does what is missing.

Terminal window
pnpm migrate
OptionDefaultMeaning
--config <file>manablox.config.tsThe config file whose database address is used

When it is done, it prints manablox: migrations applied. If the config has no database address, it stops with manablox: database.url is not set in the config.

In a docker project, the migrate service does this automatically before the CMS starts. To run it by hand there: docker compose run --rm migrate.

Writes a consistent copy of the database into a new file, while the CMS keeps running. It works for SQLite (a database that is a single file, see The database) only; for Postgres it stops with an error, use pg_dump there. It never overwrites a file: if the file exists, it stops. Missing folders are created.

Terminal window
pnpm exec manablox backup backups/2026-01-31.db
OptionDefaultMeaning
--config <file>manablox.config.tsThe config file that holds the database address

When it is done, it prints manablox: database copied to <file>. The messages it can stop with:

MessageCause
backup needs a file to write, e.g. manablox backup backups/cms.dbNo file name was given
<file> exists; backup never overwritesThe file is already there. Pick a new name
backup copies SQLite databases; back Postgres up with pg_dumpThe project uses Postgres

To restore, stop the CMS, replace the database file with the copy (and delete the -wal and -shm files next to it), then start the CMS again. In a docker project, ./scripts/backup.sh and ./scripts/restore.sh do this for you; see Backups.

Your config and plugins can declare workflows, webhook endpoints, credential slots and content templates in code (see Workflows and webhooks in code). sync writes them into every space they target, so they appear in the admin.

Terminal window
pnpm exec manablox sync --dry-run
pnpm exec manablox sync
pnpm exec manablox sync --space blog
OptionDefaultMeaning
--config <file>manablox.config.tsThe config file to load
--space <name>all spacesOnly this space, by its technical name. An unknown name stops with no space with the machine name '<name>'
--dry-runoffOnly show what would change, write nothing
--pruneoffDelete what is no longer declared. Without it, such things are only switched off

It prints one line per change, and a count of the unchanged ones at the end. The sign at the start of each line says what happened:

SignMeaning
+created
~updated
-deleted (only with --prune)
oswitched off, or handed back to the editors
!skipped, with the reason after it

If there is nothing to do, it says nothing to do.

Prints a new key pair for web push notifications (the kind a browser shows even when the admin is closed).

Terminal window
pnpm push-keys

It prints four lines, ready to paste into .env: PUSH_VAPID_PUBLIC_KEY, PUSH_VAPID_PRIVATE_KEY and an example PUSH_VAPID_SUBJECT (change the address to yours). Create the keys once and keep them: new keys break the subscriptions browsers already have. It has no options. In a docker project, run it as docker compose run --rm --no-deps api push-keys.

Writes a complete, runnable CMS project into a new folder: config files, a .env with freshly generated secrets, and a Docker Compose file. See Create your CMS for a walk-through and A tour of your project for the files it writes.

Terminal window
pnpm dlx @manablox/cli create my-cms
pnpm dlx @manablox/cli create my-cms --yes
pnpm dlx @manablox/cli create my-cms --preset docker --proxy caddy --admin-domain cms.example.com --public-domain content.example.com --acme-email you@example.com

Every option you do not give is asked in the terminal. With --yes, or when there is no terminal (for example in a script), nothing is asked and the defaults are used.

They come in this order. Questions that do not apply to your earlier answers are left out.

QuestionAsked whenDefault
Where should the instance be created?No folder was givenmy-cms
Project nameAlwaysThe folder name
Which database?No --database givenPostgres
How will this instance run?No --preset or --proxy given, or --preset docker without --proxyLocal development (Docker behind Caddy with --preset docker)
Add a public delivery instance?AlwaysYes
Domain of the admin and management APIDocker with Caddy or nginxcms.example.com
Domain of the public delivery APIDocker with Caddy or nginx, with the public APIcontent.example.com
Email for TLS certificate noticesDocker with Caddyops@example.com
Port of the admin and management APILocal, or Docker with ports published3000
Port of the public delivery APISame, with the public API3100
Port to publish Postgres onLocal, with Postgres5432
Port to publish Valkey onLocal6379
Where do uploads live?AlwaysOn disk
How does this instance send mail?AlwaysMailpit for local, No mail for Docker
Install dependencies now with pnpm?AlwaysYes
Initialise a git repository?AlwaysYes
Start Postgres and Valkey, migrate and run pnpm dev once everything is installed? (local; with SQLite it names only Valkey) or Build and start the Docker stack once everything is installed? (docker)When installingNo

The answers to “Which database?” are Postgres and SQLite. The answers to “How will this instance run?” are Local development, Docker behind Caddy, Docker behind nginx, and Docker, ports published.

OptionDefaultMeaning
[dir] or --dir <dir>asked, else my-cmsThe folder to create. It must be empty or not exist yet
--name <name>the folder nameThe name in package.json and of the Docker Compose project. Lowercase letters, digits, -, _ and .
--preset <preset>locallocal: Docker runs only Postgres and Valkey (with SQLite only Valkey), the CMS runs on your computer. docker: every part in containers, for a server
--proxy <proxy>caddyDocker only; giving it without --preset picks docker. caddy: a web server with automatic HTTPS certificates. nginx: a web server with certificates you provide. none: no web server, the ports are published for one you run yourself
--database <database>postgrespostgres: a Postgres server, run by Docker in both presets; the public API connects with its own read-only database user. sqlite: the whole database is one file (data/manablox.db, or the database volume in the docker preset), so no database server runs at all. SQLite allows one writer, so run only one management instance. The backup scripts use manablox backup
--public / --no-public--publicAdd the separate, read-only public API for your websites, or leave it out
--admin-domain <host>cms.example.comCaddy and nginx: the domain of the admin. A prefix http:// means no HTTPS, for a trial
--public-domain <host>content.example.comCaddy and nginx: the domain of the public API, same rules
--acme-email <email>ops@example.comCaddy: where certificate notices are sent
--admin-port <port>3000Without a web server: the port of the admin and the management API
--public-port <port>3100Without a web server: the port of the public API
--postgres-port <port>5432Local with Postgres: the port Postgres is reachable on from your computer
--valkey-port <port>6379Local: the port Valkey is reachable on
--storage <driver>locallocal: uploads are saved on disk. s3: in an S3-compatible bucket, whose keys go into .env
--mail <driver>mailpit (local), none (docker)smtp, mailpit, gmail, microsoft, resend, sendgrid, postmark, mailgun or none. See Sending email
--manablox-version <range>the version of this commandThe version range of the @manablox/* packages. Never asked
--install / --no-install--installRun pnpm install after writing the files
--git / --no-git--gitRun git init after writing the files
--start / --no-start--no-startStart right away. Local: starts Postgres (not with SQLite) and Valkey, migrates and runs pnpm dev. Docker: builds the image and starts every container
--forceoffWrite into a folder that is not empty
--yesoffAsk nothing and use the defaults for everything not given

Values are checked before anything is written. In the questions, a wrong answer shows the problem and asks again; on the command line it stops the command.

MessageCause
--name '...' is not a valid package nameUppercase letters, spaces or other characters in the name
--preset must be one of local, docker, not '...'A value that is not in the list (the same for --proxy, --database, --storage and --mail)
--admin-port '...' is not a portA port must be a whole number from 1 to 65535
--admin-domain '...' is not a host nameA domain like cms.example.com, optionally with http:// in front
--acme-email '...' is not an email addressNot an email address
--start needs the dependencies installed; drop --no-install--start and --no-install together
... is not empty; pass --force to write into it anywayThe folder already has files in it

If pnpm install, git init or a start step fails, the files stay written and the command tells you what to run yourself. At the end it prints “Next steps” with the commands for your setup. With --start on a local project, it hands over to pnpm dev in the same terminal.

Writes a starter website that reads your content from the public API: it finds pages by their web address, draws blocks with one component each, and has a /preview page for the admin’s visual editor. See The starter website for what you get.

Terminal window
pnpm dlx @manablox/cli frontend my-site
pnpm dlx @manablox/cli frontend my-site --framework astro --yes
pnpm dlx @manablox/cli frontend my-site --url https://content.example.com --editor-origin https://cms.example.com

As with create, missing options are asked, and --yes or a missing terminal uses the defaults.

QuestionAsked whenDefault
What should the frontend be built with?No --framework givenAstro
Where should the frontend be created?No folder givenmy-site
Project nameAlwaysThe folder name
URL of the delivery APIAlwayshttp://localhost:3100
The admin’s origin, for the visual editor’s preview channelAlwayshttp://localhost:3000
Write components for a space’s content and block types?No --model or related option givenYes, from the management API
URL of the management API, API keyComponents from the management APIhttp://localhost:3000
Which space should the components be written for?The key can read several spacesthe first
Which types should get a component?Components are writtenAll types
Space idAlwaysempty, or the space picked above
Port of the dev serverAlwaysdepends on the framework
Install dependencies now with pnpm?AlwaysYes
Initialise a git repository?AlwaysYes

If the content model cannot be read (wrong address, wrong key), you can try again or go on without it; you then get an example “teaser” block instead. For the “delivery API” answer, the public API must be running; for the management API you need an API key from Settings > API keys in the admin (see API keys).

OptionDefaultMeaning
[dir] or --dir <dir>asked, else my-siteThe folder to create
--framework <name>astroplain (Vite and TypeScript, rendered in the browser), astro (Astro, rendered on the server), react-ssr (React, rendered on the server), vue-ssr (Vue, rendered on the server)
--name <name>the folder nameThe name in package.json
--url <url>http://localhost:3100The public API the website reads from
--editor-origin <url>http://localhost:3000The address of the admin. The preview page only accepts messages from there
--space-id <id>emptyLeave empty for the public API, which serves exactly one space
--port <port>3003 plain, 3005 astro, 3006 vue-ssr, 3007 react-ssrThe port of the website’s dev server
--model <source>asked; none with --yes or without a terminalWhere to read your content types from: management (with an API key), delivery (the public API at --url, no key) or none (just the example block)
--api-url <url>http://localhost:3000The management API, for --model management
--api-key <key>noneAn API key that may read the space. Implies --model management; required for it with --yes or without a terminal
--space <name>the only oneThe space by technical name or id. Needed when the key can read several spaces
--types <list>allThe content and block types to write components for, as all or a comma-separated list like page,teaser
--manablox-version <range>the version of this commandThe version range of the @manablox/* packages
--install / --no-install--installRun pnpm install afterwards
--git / --no-git--gitRun git init afterwards
--forceoffWrite into a folder that is not empty
--yesoffAsk nothing and use the defaults

URLs must start with http:// or https://; a slash at the end is removed. Giving --api-key, --api-url or --space without --model means management; giving only --types means delivery.

The addresses end up in the website’s .env (MANABLOX_URL, MANABLOX_ADMIN_ORIGIN, MANABLOX_SPACE_ID, with a VITE_ prefix for plain), where you can change them later.

When a command ends, it reports a number to the terminal or script that ran it. 0 means success.

CodeMeaning
0Success, or the help text was asked for
1Something went wrong: an unknown command or option, a wrong value, an invalid config, or an error while running. The message starts with manablox:
2Only sync --dry-run: there is something to change. A deploy script can stop on this
130create or frontend was cancelled with Ctrl+C during the questions. It prints manablox: cancelled, nothing was written

create --start on a local project ends with the exit code of pnpm dev, which it runs at the end.