CLI
Madori source checkout includes command-line tools for scaffolding, content migration, code generation, and administration. Generated create-madori-app projects do not bundle this CLI; manage those projects through control panel instead. @madori/cli is currently source-checkout tooling rather than a published registry package.
Configuration Reference
Running CLI Commands
From Madori source checkout, run commands with:
pnpm madori <command>
Available Commands
| Command | Description |
|---|---|
make:user |
Create a new user account interactively |
make:blueprint <handle> |
Generate a blueprint from content, schema, or interactively |
make:collection <handle> |
Scaffold a complete collection with blueprint and example entry |
migrate:definitions |
Migrate legacy entity definitions from config to flat files |
migrate:wordpress <export-file> |
Migrate content from a WordPress WXR export file |
migrate:markdown <source-directory> |
Migrate Markdown files from a directory into a collection |
export <path> |
Export blueprints, collections, fieldsets, and content as an archive |
import <archive-path> |
Import resources and content from an archive |
init:preset <preset-name> |
Initialise project with an opinionated preset structure |
registry:pull <repository-url> |
Pull resources from a shared Git registry |
registry:push <repository-url> |
Push local resources to a shared Git registry |
git:status |
Show Git sync status for configured repositories |
git:sync |
Commit and optionally push pending tracked changes |
git:retry --repository <id> |
Retry a pending Git push for repository ID from git:status |
seo:migrate |
Migrate legacy SEO frontmatter fields into nested seo values |
seo:rollback --plan <path> |
Roll back an SEO migration plan |
backup <path> |
Create a checksummed operational backup |
backup:verify <archive-path> |
Verify backup structure and checksums |
restore <archive-path> --yes |
Restore a verified backup and retain rollback copies |
generate |
Generate TypeScript types, schemas, and SDK from blueprints |
check |
Check manifest schema-version compatibility |
Scaffolding Commands
Git sync commands and setup are documented in Git Content Sync.
make:blueprint
Generate a blueprint from existing content, a JSON Schema file, or interactively.
pnpm madori make:blueprint <handle> [options]
| Flag | Type | Description |
|---|---|---|
--from-content <path> |
string |
Infer blueprint from a Markdown file's frontmatter |
--from-schema <path> |
string |
Generate blueprint from a JSON Schema file |
When run without flags, the command runs interactively. Fields inferred with low confidence default to text and are flagged in the output.
Example — infer from content:
pnpm madori make:blueprint blog --from-content content/collections/blog/hello.md
✓ Blueprint "blog" created successfully!
Output: resources/blueprints/collections/blog.yaml
Fields: 6
⚠ 1 field(s) defaulted to "text" (low confidence):
- custom_meta
Example — from JSON Schema:
pnpm madori make:blueprint products --from-schema schemas/product.json
make:collection
Scaffold a complete collection in one step — creates the collection definition, blueprint, and an example entry.
pnpm madori make:collection <handle> [options]
| Flag | Type | Description |
|---|---|---|
--fields <fields> |
string |
Comma-separated field definitions: handle:type[:required] |
--route <route> |
string |
Route pattern for the collection |
Example:
pnpm madori make:collection products --fields "name:text:required,price:number:required,description:tiptap,image:asset" --route "/products/{slug}"
✓ Collection "products" created successfully!
Files created:
- resources/collections/products.yaml
- resources/blueprints/collections/products.yaml
- content/collections/products/example.md
init:preset
Initialise a project with an opinionated preset structure for common use cases.
pnpm madori init:preset <preset-name> [options]
| Flag | Description |
|---|---|
--force |
Skip conflict prompts and overwrite existing resources |
Available presets:
| Preset | Description |
|---|---|
marketing-site |
Pages, sections, and team members |
blog |
Blog posts with categories and tags |
documentation |
Documentation pages with navigation |
saas-landing |
SaaS marketing with features and pricing |
agency-portfolio |
Portfolio with case studies and team |
Example:
pnpm madori init:preset blog
✓ Preset "blog" applied successfully!
Files created:
- resources/collections/posts.yaml
- resources/blueprints/collections/posts.yaml
- resources/taxonomies/categories.yaml
- resources/taxonomies/tags.yaml
- content/navigation/main.yaml
Next steps:
Run `pnpm madori check` to check manifest schema compatibility.
Migration Commands
migrate:wordpress
Migrate content from a WordPress WXR export file into Madori entries. Converts HTML to Markdown, preserves categories and tags as taxonomy terms, and maps WordPress statuses.
pnpm madori migrate:wordpress <export-file> [options]
| Flag | Type | Description |
|---|---|---|
--collection <handle> |
string |
Target collection handle (default: posts for posts, pages for pages) |
Example:
pnpm madori migrate:wordpress wordpress-export.xml --collection blog
Migrating WordPress content from: /path/to/wordpress-export.xml
Migration complete!
Total processed: 142
Entries created: 138
Skipped: 4
Taxonomies:
Categories: 8 terms → resources/taxonomies/categories.yaml
Tags: 23 terms → resources/taxonomies/tags.yaml
Summary: 142 processed, 138 created, 4 skipped, 0 warnings
The migration:
- Converts HTML content to Markdown
- Maps
publish→published,draft/private→draft - Preserves author, categories, and tags
- Auto-creates taxonomy definition files
migrate:markdown
Migrate a directory of Markdown files into a Madori collection. Extra frontmatter fields are preserved, but migration sets title, slug, status, createdAt, and updatedAt; imported entries become drafts. Review generated entries before publishing.
pnpm madori migrate:markdown <source-directory> [options]
| Flag | Type | Description |
|---|---|---|
--collection <handle> |
string |
Target collection handle (prompted if not provided) |
Example:
pnpm madori migrate:markdown ./old-blog-posts --collection blog
Migrating Markdown files from: /path/to/old-blog-posts
Target collection: blog
Migration complete!
Files processed: 47
Entries created: 47
Skipped: 0
Summary: 47 processed, 47 created, 0 skipped, 0 warnings
migrate:definitions
Migrates taxonomies, globals, and navigations arrays from the config file into individual YAML files under resources/.
pnpm madori migrate:definitions [options]
| Flag | Type | Default | Description |
|---|---|---|---|
--config <path> |
string |
./madori.config.ts |
Path to the config file to migrate from |
--resources <path> |
string |
./resources |
Output directory for generated definition files |
Portability Commands
export
Export project resources and content as a portable archive.
pnpm madori export <output-path> [options]
| Flag | Type | Default | Description |
|---|---|---|---|
--format <format> |
string |
zip |
Archive format: zip or tar |
--resources <types> |
string |
all | Comma-separated resource types to include |
Resource types: blueprints, collections, fieldsets, content
Example:
pnpm madori export ./backup.zip --format zip --resources "blueprints,fieldsets"
✓ Export completed successfully!
Archive: ./backup.zip
Size: 24.3 KB
Files: 18
import
Import resources and content from a previously exported archive.
pnpm madori import <archive-path>
Example:
pnpm madori import ./backup.zip
✓ Import completed successfully!
Total files: 18
Imported: 16
Skipped: 2
Conflicts: 0
Existing files are skipped by default to prevent accidental overwrites.
Operational backup and restore
Back up configured content, resources, assets, users, configuration, SEO state,
sessions, and the schema manifest. Restore requires an explicit --yes and
keeps pre-restore rollback copies.
pnpm madori backup ./storage/madori-backup.tar.gz
pnpm madori backup:verify ./storage/madori-backup.tar.gz
pnpm madori restore ./storage/madori-backup.tar.gz --yes
Use --rollback-dir <path> with restore to choose the rollback directory.
registry:pull
Pull shared resources from a Git repository into your local project.
pnpm madori registry:pull <repository-url> [options]
| Flag | Type | Default | Description |
|---|---|---|---|
--resources <types> |
string |
all | Comma-separated resource types to pull |
--branch <branch> |
string |
main |
Git branch to pull from |
Example:
pnpm madori registry:pull https://github.com/my-agency/shared-blueprints.git --resources "blueprints,fieldsets"
registry:push
Push local resources to a shared Git registry.
pnpm madori registry:push <repository-url> [options]
| Flag | Type | Default | Description |
|---|---|---|---|
--resources <types> |
string |
all | Comma-separated resource types to push |
--branch <branch> |
string |
main |
Git branch to push to |
Code Generation
generate
Generate TypeScript types, Zod schemas, and a typed GraphQL SDK from your blueprints. Output goes to .madori/generated/ by default.
pnpm madori generate [options]
| Flag | Type | Default | Description |
|---|---|---|---|
-o, --output <path> |
string |
.madori/generated |
Output directory for generated files |
-w, --watch |
boolean |
false |
Watch blueprint files and regenerate on change |
Example:
pnpm madori generate
✓ Generate complete: 3 blueprint(s) processed in 42ms
Watch mode:
pnpm madori generate --watch
Watches YAML files under resources/blueprints/**/*.yaml and regenerates with
a 300ms debounce. It does not watch collection definitions or fieldsets, so run
pnpm madori generate explicitly after changing those resources.
The generator reads resources/blueprints/**/*.yaml from the project root and
does not derive this input directory from a custom resourcesPath. The generated
output includes:
- TypeScript interfaces for each collection's entries
- Zod schemas for runtime validation
- A typed GraphQL SDK with operations for each collection
- A barrel
index.tsfor convenient imports - A
tsconfig.paths.jsonfor path alias configuration
Generated consumers import @madori/sdk, which is currently a source workspace package. Build and link the SDK before using those imports; see SDK and content access for setup. Path aliases alone do not install the package.
Administration Commands
make:user
Create a new user account interactively.
pnpm madori make:user
| Prompt | Type | Validation |
|---|---|---|
| Email address | string |
Must be valid email, must not already exist |
| Display name | string |
Required, non-empty |
| Password | string |
Required, minimum 8 characters |
| Roles | string[] |
Comma-separated list of role handles |
Output: Creates a YAML file at users/{id}.yaml with a scrypt password hash.
check
Check whether the manifest's schema version matches the version expected by the running code. This command does not validate all blueprints, content, or application configuration.
pnpm madori check
Use --manifest <path> to override the default .madori/manifest.json location.
Usage Examples
Creating a User
pnpm madori make:user
Interactive prompts:
? Email address: [email protected]
? Display name: Jane Editor
? Password: ********
? Roles (comma-separated): editor
✓ User created: users/<generated-id>.yaml
Full Agency Workflow
Set up a new client project from a preset, then customise:
# Start from a preset
pnpm madori init:preset marketing-site
# Add a blog collection
pnpm madori make:collection blog --fields "title:text:required,slug:slug:required,body:tiptap,image:asset"
# Validate everything
pnpm madori check
# Generate typed SDK
pnpm madori generate
Migrating from WordPress
# Export from WordPress (WXR format)
# Then import into Madori:
pnpm madori migrate:wordpress wordpress-export.xml
# Generate blueprint from migrated content
pnpm madori make:blueprint posts --from-content content/collections/posts/first-post.md
Sharing Resources Between Projects
# Push blueprints and fieldsets to a shared registry
pnpm madori registry:push https://github.com/my-agency/shared-resources.git --resources "blueprints,fieldsets"
# Pull into another project
pnpm madori registry:pull https://github.com/my-agency/shared-resources.git
Resource Portability
# Export supported resources and content
pnpm madori export ./project-backup.zip
# Import on another machine; existing files are skipped
pnpm madori import ./project-backup.zip
This portable export is not an operational backup of users, sessions, assets, or all configured storage roots. Use backup, backup:verify, and restore for disaster recovery.
Common Patterns
Scripting User Creation
For CI/CD or staging setup, prefer make:user or your configured auth provider.
If you write provider files directly, use the provider's documented hash format;
Madori's built-in file provider uses scrypt:<salt>:<hash> values.
# users/staging-admin.yaml
id: staging-admin
email: [email protected]
name: Staging Admin
password_hash: scrypt:<salt hex>:<hash hex>
roles:
- admin
created_at: 2026-01-01T00:00:00.000Z
Code Generation in CI
Add generation to your build pipeline to ensure types stay fresh:
{
"scripts": {
"prebuild": "pnpm madori generate",
"build": "next build"
}
}
SEO Frontmatter Migration
Move legacy meta_title, meta_description, and og_image fields into a nested seo object. The command is idempotent, preserves unknown fields, writes per-file backups, and refuses rollback if a target changed after migration. Records do not carry the standalone SEO document's version wrapper.
# Preview changes
pnpm madori seo:migrate --root ./content --dry-run
# Apply migration
pnpm madori seo:migrate --root ./content
For a reversible apply, write a private rollback plan and keep it out of Git:
pnpm madori seo:migrate --root ./content --plan ./storage/seo-migration-plan.json
pnpm madori seo:rollback --plan ./storage/seo-migration-plan.json
Review the JSON output and rollbackPlan before committing. Commit migrated content and SEO defaults through the repository that owns those paths; operational SEO state under storage/seo is not part of this migration and should remain outside content Git.
Legacy Definitions Migration
When upgrading from an older Madori version that stored definitions inline:
- Run
pnpm madori migrate:definitionsto extract definitions to files - Review the generated files in
resources/ - Remove the migrated arrays from
madori.config.ts - Commit the new files and updated config
The migration is non-destructive — existing files are never overwritten.