Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Command-Line Reference

crap-cms <COMMAND> [OPTIONS]

Use crap-cms --help to list all commands, or crap-cms <command> --help for details on a specific command.

Global Flags

FlagDescription
-C, --config <PATH>Path to the config directory (overrides auto-detection)
-V, --versionPrint version and exit
-h, --helpPrint help

Config Directory Resolution

Most commands need a config directory (the folder containing crap.toml). The CLI resolves it in this order:

  1. --config / -C flag — explicit path, highest priority
  2. CRAP_CONFIG_DIR environment variable — useful for CI/Docker
  3. Auto-detection — walks up from the current working directory looking for crap.toml

If you cd into your project directory (or any subdirectory), commands just work without any flags:

cd my-project
crap-cms serve
crap-cms status
crap-cms user list

From elsewhere, use -C:

crap-cms -C ./my-project serve
crap-cms -C ./my-project status

Or set the environment variable:

export CRAP_CONFIG_DIR=./my-project
crap-cms serve

Commands

serve — Start the server

crap-cms serve [-d] [--stop] [--restart] [--status] [--json] [--only <admin|api>] [--no-scheduler]
FlagDescription
-d, --detachRun in the background (prints PID and exits)
--stopStop a running detached instance (SIGTERM, then SIGKILL after 10s)
--restartRestart a running detached instance (stop + start)
--statusShow whether a detached instance is running (PID, uptime)
--jsonOutput logs as structured JSON (for log aggregation)
--only <admin|api>Start only the specified server. Omit to start both.
--no-schedulerDisable the background job scheduler

--detach, --stop, --restart, and --status are mutually exclusive.

crap-cms serve                    # foreground
crap-cms serve -d                 # detached (background)
crap-cms serve --status           # is it running?
crap-cms serve --stop             # stop detached instance
crap-cms serve --restart          # stop + start detached
crap-cms serve --json
crap-cms serve --only admin       # admin UI only
crap-cms serve --only api         # gRPC API only
crap-cms serve --no-scheduler     # both servers, no scheduler
crap-cms serve --only admin --no-scheduler
crap-cms serve -d --only api      # detached, API only

status — Show project status

crap-cms status

Prints collections (with row counts), globals, DB size, and migration status.

user — User management

user create

crap-cms user create [-c <COLLECTION>] [-e <EMAIL>] [-p <PASSWORD>] [-f <KEY=VALUE>]...
FlagShortDefaultDescription
--collection-cusersAuth collection slug
--email-eUser email (prompted if omitted)
--password-pUser password (prompted if omitted)
--field-fExtra fields as key=value (repeatable)
# Interactive (prompts for password)
crap-cms user create -e admin@example.com

# Non-interactive
crap-cms user create \
    -e admin@example.com \
    -p secret123 \
    -f role=admin \
    -f name="Admin User"

user list

crap-cms user list [-c <COLLECTION>]

Lists all users with ID, email, locked status, and verified status (if email verification is enabled).

crap-cms user list
crap-cms user list -c admins

user info

crap-cms user info [-c <COLLECTION>] [-e <EMAIL>] [--id <ID>]

Shows detailed info for a single user: ID, email, locked/verified status, password status, timestamps, and all field values.

crap-cms user info -e admin@example.com
crap-cms user info --id abc123

user delete

crap-cms user delete [-c <COLLECTION>] [-e <EMAIL>] [--id <ID>] [-y]
FlagShortDescription
--collection-cAuth collection slug (default: users)
--email-eUser email
--idUser ID
--confirm-ySkip confirmation prompt

user lock / user unlock

crap-cms user lock [-c <COLLECTION>] [-e <EMAIL>] [--id <ID>]
crap-cms user unlock [-c <COLLECTION>] [-e <EMAIL>] [--id <ID>]

user verify / user unverify

crap-cms user verify [-c <COLLECTION>] [-e <EMAIL>] [--id <ID>]
crap-cms user unverify [-c <COLLECTION>] [-e <EMAIL>] [--id <ID>]

Manually mark a user’s email as verified or unverified. Only works on collections with verify_email = true. Useful when email is not configured.

user change-password

Change a user’s password. Prompts for the new password if -p is omitted.

crap-cms user change-password [-c <COLLECTION>] [-e <EMAIL>] [--id <ID>] [-p <PASSWORD>]

init — Scaffold a new config directory

crap-cms init [DIR] [--no-input]

Runs an interactive wizard that scaffolds a complete config directory. Defaults to ./crap-cms if no directory is given.

The wizard prompts for:

PromptDefaultDescription
Admin port3000Port for the admin UI
gRPC port50051Port for the gRPC API
Enable localization?NoIf yes, prompts for default locale and additional locales
Default localeenDefault locale code (only if localization enabled)
Additional localesComma-separated (e.g., de,fr)
Create auth collection?YesCreates a users collection with email/password login
Create first admin user?YesPrompts for email and password immediately
Create upload collection?YesCreates a media collection for file/image uploads
Create another collection?NoRepeat to add more collections interactively

A 64-character auth secret is auto-generated and written to crap.toml.

crap-cms init ./my-project

After scaffolding:

cd my-project
crap-cms serve

make — Generate scaffolding files

make collection

crap-cms make collection [SLUG] [-F <FIELDS>] [-T] [--auth] [--upload] [--versions] [--no-input] [-f]
FlagShortDescription
--fields-FInline field shorthand (see below)
--no-timestamps-TSet timestamps = false
--authEnable auth (email/password login)
--uploadEnable uploads (file upload collection)
--versionsEnable versioning (draft/publish workflow)
--no-inputNon-interactive mode — skip all prompts, use flags and defaults only
--force-fOverwrite existing file

Without --no-input, missing arguments (slug, fields) are collected via interactive prompts. The field survey asks for name, type, required, and localized (if localization is enabled).

Field shorthand syntax:

name:type[:modifier][:modifier]...

Modifiers are order-independent:

ModifierDescription
requiredField is required
localizedField has per-locale values (see Localization)
# Basic
crap-cms make collection posts

# With fields
crap-cms make collection articles \
    -F "title:text:required,body:richtext"

# With localized fields
crap-cms make collection pages \
    -F "title:text:required:localized,body:textarea:localized,slug:text:required"

# Auth collection
crap-cms make collection users --auth

# Upload collection
crap-cms make collection media --upload

# Non-interactive with versions
crap-cms make collection posts \
    -F "title:text:required,body:richtext" --versions --no-input

make global

crap-cms make global [SLUG] [-F <FIELDS>] [-f]
FlagShortDescription
--fields-FInline field shorthand (same syntax as make collection)
--force-fOverwrite existing file
crap-cms make global site_settings
crap-cms make global nav -F "links:array(label:text:required,url:text)"

make hook

crap-cms make hook [NAME] [-t <TYPE>] [-c <COLLECTION>] [-l <POSITION>] [-F <FIELD>] [--force]
FlagShortDescription
--type-tHook type: collection, field, access, or condition
--collection-cTarget collection or global slug
--position-lLifecycle position (e.g., before_change, after_read)
--field-FTarget field name (field hooks only; watched field for condition hooks)
--forceOverwrite existing file

Missing flags are resolved via interactive prompts. The wizard lists collections and globals from the registry (globals are tagged). For non-interactive mode, the slug is auto-detected as a global if it exists in the globals registry.

Valid positions by type:

TypePositions
collectionbefore_validate, before_change, after_change, before_read, after_read, before_delete, after_delete, before_broadcast
fieldbefore_validate, before_change, after_change, after_read
accessread, create, update, delete
conditiontable, boolean

Generated hooks use per-collection typed annotations for IDE support:

  • Collection hooks: crap.hook.Posts, crap.hook.global_site_settings
  • Field hooks: crap.field_hook.Posts, crap.field_hook.global_site_settings
  • Condition hooks: crap.data.Posts, crap.global_data.SiteSettings
  • Delete hooks: generic crap.HookContext (data only contains the document ID)
  • Access hooks: generic crap.AccessContext
# Interactive (prompts for everything)
crap-cms make hook

# Fully specified
crap-cms make hook auto_slug \
    -t collection -c posts -l before_change

# Field hook
crap-cms make hook normalize_email \
    -t field -c users -l before_validate -F email

# Access hook
crap-cms make hook owner_only \
    -t access -c posts -l read

# Condition hook (client-side table)
crap-cms make hook show_external_url \
    -t condition -c posts -l table -F post_type

make job

crap-cms make job [SLUG] [-s <SCHEDULE>] [-q <QUEUE>] [-r <RETRIES>] [-t <TIMEOUT>] [-f]
FlagShortDefaultDescription
--schedule-sCron expression (e.g., "0 3 * * *")
--queue-qdefaultQueue name
--retries-r0Max retry attempts
--timeout-t60Timeout in seconds
--force-fOverwrite existing file
# Interactive (prompts for slug)
crap-cms make job

# With schedule
crap-cms make job cleanup_expired -s "0 3 * * *" -r 3 -t 300

# Simple job (triggered from hooks)
crap-cms make job send_welcome_email

blueprint — Manage saved blueprints

blueprint save

crap-cms blueprint save <NAME> [-f]

Saves the current config directory as a reusable blueprint (excluding data/, uploads/, types/). A .crap-blueprint.toml manifest is written with the CMS version and timestamp.

blueprint use

crap-cms blueprint use <NAME> [DIR]

Creates a new project from a saved blueprint. If the blueprint was saved with a different CMS version, a warning is printed (but the operation proceeds).

blueprint list

crap-cms blueprint list

Lists saved blueprints with collection/global counts and the CMS version they were saved with.

blueprint remove

crap-cms blueprint remove <NAME>

db — Database tools

db console

crap-cms db console

Opens an interactive sqlite3 session on the project database.

db cleanup

crap-cms db cleanup [--confirm]
FlagDescription
--confirmActually drop orphan columns (default: dry-run report only)

Detects columns in collection tables that don’t correspond to any field in the current Lua definitions. System columns (_-prefixed like _password_hash, _locked) are always kept. Plugin columns are safe because plugins run during schema loading — their fields are part of the live definitions.

# Dry run — show orphans without removing them
crap-cms db cleanup

# Actually drop orphan columns
crap-cms db cleanup --confirm

export — Export collection data

crap-cms export [-c <COLLECTION>] [-o <FILE>]
FlagShortDescription
--collection-cExport only this collection (default: all)
--output-oOutput file (default: stdout)

Export includes crap_version and exported_at metadata in the JSON envelope. On import, a version mismatch produces a warning (but does not abort).

crap-cms export
crap-cms export -c posts -o posts.json

import — Import collection data

crap-cms import <FILE> [-c <COLLECTION>]
FlagShortDescription
--collection-cImport only this collection (default: all in file)
crap-cms import backup.json
crap-cms import backup.json -c posts

typegen — Generate typed definitions

crap-cms typegen [-l <LANG>] [-o <DIR>]
FlagShortDefaultDescription
--lang-lluaOutput language: lua, ts, go, py, rs, all
--output-o<config>/types/Output directory for generated files
crap-cms typegen
crap-cms typegen -l all
crap-cms typegen -l ts -o ./client/src/types

proto — Export proto file

crap-cms proto [-o <PATH>]

Writes content.proto to stdout or the given path. No config directory needed.

crap-cms proto
crap-cms proto -o ./proto/

migrate — Run database migrations

crap-cms migrate <create|up|down|list|fresh>
SubcommandDescription
create <NAME>Generate a new migration file (e.g., backfill_slugs)
upSync schema + run pending migrations
down [-s|--steps N]Roll back last N migrations (default: 1)
listShow all migration files with status
fresh [-y|--confirm]Drop all tables and recreate (destructive, requires confirmation)
crap-cms migrate create backfill_slugs
crap-cms migrate up
crap-cms migrate list
crap-cms migrate down -s 2
crap-cms migrate fresh -y

backup — Backup database

crap-cms backup [-o <DIR>] [-i]
FlagShortDescription
--output-oOutput directory (default: <config>/backups/)
--include-uploads-iAlso compress the uploads directory
crap-cms backup
crap-cms backup -o /tmp/backups -i

restore — Restore from backup

crap-cms restore <BACKUP> [-i] [-y]
FlagShortDescription
--include-uploads-iAlso restore uploads from uploads.tar.gz if present
--confirm-yRequired — confirms the destructive operation

Replaces the current database with a backup snapshot. Cleans up stale WAL/SHM files.

crap-cms restore ./backups/backup-2026-03-07T10-00-00 -y
crap-cms restore /tmp/backups/backup-2026-03-07T10-00-00 -i -y

templates — List and extract default admin templates

Extract the compiled-in admin templates and static files into your config directory for customization.

templates list

crap-cms templates list [-t <TYPE>] [-v]
FlagShortDescription
--type-tFilter: templates or static (default: both)
--verbose-vShow full file tree with individual sizes (default: compact summary)
crap-cms templates list
crap-cms templates list -t templates
crap-cms templates list -v

templates extract

crap-cms templates extract [PATHS...] [-a] [-t <TYPE>] [-f]
FlagShortDescription
--all-aExtract all files
--type-tFilter: templates or static (only with --all)
--force-fOverwrite existing files
# Extract specific files
crap-cms templates extract layout/base.hbs styles.css

# Extract all templates
crap-cms templates extract --all --type templates

# Extract everything, overwriting existing
crap-cms templates extract --all --force

jobs — Manage background jobs

jobs list

crap-cms jobs list

Lists all defined jobs with their configuration (handler, schedule, queue, retries, timeout, concurrency).

jobs trigger

crap-cms jobs trigger <SLUG> [-d <DATA>]
FlagShortDefaultDescription
--data-d"{}"JSON data to pass to the job

Manually queue a job for execution. Works even while the server is running (SQLite WAL allows concurrent access). Prints the queued job run ID.

jobs status

crap-cms jobs status [--id <ID>] [-s <SLUG>] [-l <LIMIT>]
FlagShortDefaultDescription
--idShow details for a specific run
--slug-sFilter by job slug
--limit-l20Max results to show

Show recent job runs. If --id is given, shows details for that specific run. Otherwise lists recent runs across all jobs.

jobs cancel

crap-cms jobs cancel [--slug <SLUG>]
FlagDefaultDescription
--slug, -s(all)Only cancel pending jobs with this slug. Without it, cancels all pending jobs.

Deletes pending jobs from the queue. Useful for clearing stuck or unwanted jobs that keep retrying.

jobs purge

crap-cms jobs purge [--older-than <DURATION>]
FlagDefaultDescription
--older-than7dDelete completed/failed/stale runs older than this. Supports Nd, Nh, Nm formats.

jobs healthcheck

crap-cms jobs healthcheck

Checks job system health and prints a summary: defined jobs, stale jobs (running but heartbeat expired), failed jobs in the last 24 hours, pending jobs waiting longer than 5 minutes, and scheduled jobs that have never completed a run.

Exit status: healthy (no issues), warning (failed or long-pending jobs), unhealthy (stale jobs detected).

crap-cms jobs list
crap-cms jobs trigger cleanup_expired
crap-cms jobs status
crap-cms jobs status --id abc123
crap-cms jobs cancel
crap-cms jobs cancel -s process_inquiry
crap-cms jobs purge --older-than 30d
crap-cms jobs healthcheck

images — Manage image processing queue

Inspect and manage the background image format conversion queue. See Image Processing for how to enable queued conversion.

images list

crap-cms images list [-s <STATUS>] [-l <LIMIT>]
FlagShortDefaultDescription
--status-sFilter by status: pending, processing, completed, failed
--limit-l20Max entries to show

images stats

crap-cms images stats

Shows counts by status (pending, processing, completed, failed) and total.

images retry

crap-cms images retry [--id <ID>] [--all] [-y]
FlagShortDescription
--idRetry a specific failed entry by ID
--allRetry all failed entries
--confirm-yRequired with --all

images purge

crap-cms images purge [--older-than <DURATION>]
FlagDefaultDescription
--older-than7dDelete completed/failed entries older than this. Supports Nd, Nh, Nm, Ns formats.
crap-cms images list
crap-cms images list -s failed
crap-cms images stats
crap-cms images retry --id abc123
crap-cms images retry --all -y
crap-cms images purge --older-than 30d

mcp — Start the MCP server (stdio)

Start an MCP (Model Context Protocol) server over stdio for AI assistant integration.

crap-cms mcp

Reads JSON-RPC 2.0 from stdin, writes responses to stdout. Use with Claude Desktop, Cursor, VS Code, or any MCP-compatible client. See MCP Overview for configuration and usage.

logs — View and manage log files

crap-cms logs [-f] [-n <lines>]
crap-cms logs clear

View log output from file-based logging. Requires [logging] file = true in crap.toml (auto-enabled when running with --detach).

FlagDescription
-f, --followFollow log output in real time (like tail -f)
-n, --lines <N>Number of lines to show (default: 100)

Subcommands:

SubcommandDescription
clearRemove old rotated log files, keeping only the current one
crap-cms logs                # show last 100 lines
crap-cms logs -f             # follow in real time
crap-cms logs -n 50          # show last 50 lines
crap-cms logs clear          # remove old rotated files

Log files are stored in data/logs/ (or the path configured in [logging] path). Old files are automatically pruned on startup based on max_files. See Configuration Reference for all logging options.

Environment Variables

VariableDescription
CRAP_CONFIG_DIRPath to the config directory (same as --config flag; flag takes priority)
RUST_LOGControls log verbosity. Default: crap_cms=debug,info for serve, crap_cms=error for all other commands. Example: RUST_LOG=crap_cms=trace
CRAP_LOG_FORMATSet to json for structured JSON log output (same as --json flag)