CLI Reference
The EmDash CLI provides commands for managing an EmDash CMS instance — database setup, type generation, content CRUD, schema management, media, and more.
Installation
Section titled “Installation”The CLI is included with the emdash package. Install it with the following command:
npm install emdashRun commands with npx emdash or add scripts to package.json. The binary is also available as em for brevity.
Start your site with its package script, such as pnpm dev. The package script starts Astro; the EmDash integration generates emdash-env.d.ts, while the runtime runs pending migrations on the first request and applies the bundled seed when the database is empty and setup has not been completed.
Authentication
Section titled “Authentication”Commands using the shared remote client resolve authentication in this order:
--tokenflag — explicit token on the command lineEMDASH_TOKENenv var- Stored credentials from
~/.config/emdash/auth.json(saved byemdash login) - Dev bypass — if the URL is localhost and no token is available, automatically authenticates via the dev bypass endpoint
These commands accept --url (from EMDASH_URL, falling back to http://localhost:4321) and --token flags. Authentication commands have their own connection options. When targeting a local dev server, no token is needed.
Common Flags
Section titled “Common Flags”These flags are available on commands using the shared remote client:
| Flag | Alias | Description | Default |
|---|---|---|---|
--url | -u | EmDash instance URL | EMDASH_URL or http://localhost:4321 |
--token | -t | Auth token | From env/stored creds |
--header "Name: Value" | -H | Custom request header; may be repeated | From EMDASH_HEADERS/stored creds |
--json | Output as JSON (for piping) | Auto-detected from TTY |
Output
Section titled “Output”For commands using the shared remote client, stdout is pretty-printed with consola when it is a TTY and becomes raw JSON when piped or when --json is set. emdash migrate emits JSON only with its explicit --json option.
Commands
Section titled “Commands”emdash migrate
Section titled “emdash migrate”Check or apply the core migration set emitted by an Astro build.
npx emdash migrate [options]npx emdash migrate --check [options]npx emdash migrate --status --json [options]By default the command discovers the project root and reads .emdash/migrations.json. It validates the manifest against the project’s installed EmDash package, resolves the adapter’s project-local executor, and prints the immutable target before any SQL.
Options
Section titled “Options”| Option | Description |
|---|---|
--check | Apply nothing; exit non-zero for pending or unknown migration records |
--status | Report exact status without applying; exit zero after a successful report |
--json | Emit the stable migration report as JSON |
--manifest <path> | Read a non-standard manifest path |
--from-config | Explicitly evaluate trusted Astro configuration instead of a manifest |
--config <path> | Astro config path used with --from-config |
--expected-target-fingerprint <sha256> | Required guard for non-interactive apply |
--database <path> | Override a SQLite path |
--database-url-env <name> | Override a PostgreSQL connection-variable name |
--d1 <uuid-or-name> | Select a D1 database explicitly |
--account-id <id> | Select a Cloudflare account explicitly |
--wrangler-config <path> | Read D1 binding metadata from an explicit Wrangler config |
--wrangler-env <name> | Select an environment; requires --wrangler-config |
Interactive human-readable apply asks for confirmation. Non-interactive apply and every apply using --json require the exact fingerprint printed for the target. There is no down or --dry-run; use --check to determine whether work is required.
Exit codes
Section titled “Exit codes”| Code | Meaning |
|---|---|
0 | Success, including a successful --status report |
1 | Validation, configuration, target, migration, or cleanup error |
2 | --check found pending known migrations |
3 | --check found unknown applied records (takes precedence over pending) |
4 | Confirmation missing, declined, or target fingerprint mismatch |
130 | Interrupted after bounded executor cleanup |
See Manage Core Database Migrations for deployment order, target credentials, and D1 serialization.
emdash dev (deprecated)
Section titled “emdash dev (deprecated)”The legacy command initializes and migrates a local SQLite database before starting Astro. That behavior does not use the database adapter configured by the site and is incompatible with Cloudflare D1 development. Existing invocations now print a deprecation warning before doing any database work.
emdash types
Section titled “emdash types”Generate TypeScript types from a running EmDash instance’s schema.
npx emdash types [options]Options
Section titled “Options”| Option | Alias | Description | Default |
|---|---|---|---|
--url | -u | EmDash instance URL | http://localhost:4321 |
--token | -t | Auth token | From env/stored creds |
--output | -o | Output path for types | .emdash/types.ts |
--cwd | Working directory | Current directory |
Examples
Section titled “Examples”# Generate types from local dev servernpx emdash types
# Generate from remote instancenpx emdash types --url https://my-site.pages.dev
# Custom output pathnpx emdash types --output src/types/emdash.tsBehavior
Section titled “Behavior”- Fetches the schema from the instance
- Generates TypeScript type definitions
- Writes types to the output file
- Writes
schema.jsonalongside for reference
emdash login
Section titled “emdash login”Log in to an EmDash instance using OAuth Device Flow.
npx emdash login [options]Options
Section titled “Options”| Option | Alias | Description | Default |
|---|---|---|---|
--url | -u | EmDash instance URL | http://localhost:4321 |
Behavior
Section titled “Behavior”- Discovers auth endpoints from the instance
- If localhost and no auth configured, uses dev bypass automatically
- Otherwise initiates OAuth Device Flow — displays a code and opens your browser
- Polls for authorization, then saves credentials to
~/.config/emdash/auth.json
Saved credentials are used automatically by all subsequent commands targeting the same instance.
emdash logout
Section titled “emdash logout”Log out and remove stored credentials.
npx emdash logout [options]Options
Section titled “Options”| Option | Alias | Description | Default |
|---|---|---|---|
--url | -u | EmDash instance URL | http://localhost:4321 |
emdash whoami
Section titled “emdash whoami”Show the current authenticated user.
npx emdash whoami [options]Options
Section titled “Options”| Option | Alias | Description | Default |
|---|---|---|---|
--url | -u | EmDash instance URL | http://localhost:4321 |
--token | -t | Auth token | From env/stored creds |
--json | Output as JSON |
Displays email, name, role, auth method, and instance URL.
emdash content
Section titled “emdash content”Manage content items. All subcommands use the remote API via EmDashClient.
content list <collection>
Section titled “content list <collection>”npx emdash content list postsnpx emdash content list posts --status published --limit 10| Option | Description |
|---|---|
--status | Filter by status |
--limit | Maximum items |
--cursor | Pagination cursor |
content get <collection> <id>
Section titled “content get <collection> <id>”npx emdash content get posts 01ABC123npx emdash content get posts 01ABC123 --raw| Option | Description |
|---|---|
--raw | Return raw Portable Text (skip markdown conversion) |
The response includes a _rev token. Pass it to content update to confirm you have seen the current state before overwriting it.
content create <collection>
Section titled “content create <collection>”npx emdash content create posts --data '{"title": "Hello"}'npx emdash content create posts --file post.json --slug hello-worldcat post.json | npx emdash content create posts --stdin| Option | Description |
|---|---|
--data | JSON string with content data |
--file | Read data from a JSON file |
--stdin | Read data from stdin |
--slug | Content slug |
--locale | Content locale |
--translation-of | ID of a content item to link this as a translation of |
--draft | Keep as draft instead of auto-publishing |
Provide data via exactly one of --data, --file, or --stdin. New items are auto-published unless --draft is set.
content update <collection> <id>
Section titled “content update <collection> <id>”You must provide the _rev token from a prior get to prove you have seen the current state. This prevents overwriting changes you have not seen. The following steps read an item, then update it with that token:
# 1. Read the item, note the _revnpx emdash content get posts 01ABC123
# 2. Update with the _rev from step 1npx emdash content update posts 01ABC123 \ --rev MToyMDI2LTAyLTE0... \ --data '{"title": "Updated"}'| Option | Description |
|---|---|
--rev | Revision token from get (required) |
--data | JSON string with content data |
--file | Read data from a JSON file |
If the item has changed since your get, the server returns 409 Conflict — re-read and try again.
content delete <collection> <id>
Section titled “content delete <collection> <id>”npx emdash content delete posts 01ABC123Soft-deletes the content item (moves to trash).
content publish <collection> <id>
Section titled “content publish <collection> <id>”npx emdash content publish posts 01ABC123content unpublish <collection> <id>
Section titled “content unpublish <collection> <id>”npx emdash content unpublish posts 01ABC123content schedule <collection> <id>
Section titled “content schedule <collection> <id>”npx emdash content schedule posts 01ABC123 --at 2026-03-01T09:00:00Z| Option | Description |
|---|---|
--at | ISO 8601 datetime (required) |
content restore <collection> <id>
Section titled “content restore <collection> <id>”npx emdash content restore posts 01ABC123Restores a trashed content item.
emdash schema
Section titled “emdash schema”Manage collections and fields.
schema list
Section titled “schema list”npx emdash schema listLists all collections.
schema get <collection>
Section titled “schema get <collection>”npx emdash schema get postsShows a collection with all its fields.
schema create <collection>
Section titled “schema create <collection>”npx emdash schema create articles --label Articlesnpx emdash schema create articles --label Articles --label-singular Article --description "Blog articles"| Option | Description |
|---|---|
--label | Collection label (required) |
--label-singular | Singular label |
--description | Collection description |
schema delete <collection>
Section titled “schema delete <collection>”npx emdash schema delete articlesnpx emdash schema delete articles --force| Option | Description |
|---|---|
--force | Skip confirmation |
Prompts for confirmation unless --force is set.
schema add-field <collection> <field>
Section titled “schema add-field <collection> <field>”npx emdash schema add-field posts body --type portableText --label "Body Content"npx emdash schema add-field posts featured --type boolean --required| Option | Description |
|---|---|
--type | Field type: string, text, number, integer, boolean, datetime, image, reference, portableText, json (required) |
--label | Field label (defaults to field slug) |
--required | Whether the field is required |
schema remove-field <collection> <field>
Section titled “schema remove-field <collection> <field>”npx emdash schema remove-field posts featuredemdash media
Section titled “emdash media”Manage media items.
media list
Section titled “media list”npx emdash media listnpx emdash media list --mime image/png --limit 20| Option | Description |
|---|---|
--mime | Filter by MIME type |
--limit | Number of items |
--cursor | Pagination cursor |
media upload <file>
Section titled “media upload <file>”npx emdash media upload ./photo.jpgnpx emdash media upload ./photo.jpg --alt "A sunset" --caption "Taken in Bristol"| Option | Description |
|---|---|
--alt | Alt text |
--caption | Caption text |
media get <id>
Section titled “media get <id>”npx emdash media get 01MEDIA123media delete <id>
Section titled “media delete <id>”npx emdash media delete 01MEDIA123media repair-usage
Section titled “media repair-usage”Repair content media usage indexes for one collection or for every content collection. Use this after imports or direct database writes when usage coverage is stale or untrusted.
npx emdash media repair-usage --collection postsnpx emdash media repair-usage --allnpx emdash media repair-usage --all --json| Option | Alias | Description |
|---|---|---|
--collection | -c | Repair one content collection |
--all | Repair every content collection |
Pass exactly one of --collection or --all. Remote repair requires an Admin user and an auth token with the admin scope.
All-content repair runs synchronously and can be slow or expensive on large sites. Prefer --collection when you only need to repair one collection.
Structured complete, partial, and stale repair results exit 0; structured failed results exit 1. Automation and cron jobs should use --json and parse status, failedSourceCount, skippedSourceCount, and per-collection summaries instead of treating exit 0 as complete coverage.
emdash search
Section titled “emdash search”Full-text search across content.
npx emdash search "hello world"npx emdash search "hello" --collection posts --limit 5| Option | Alias | Description |
|---|---|---|
--collection | -c | Filter by collection |
--limit | -l | Maximum results |
emdash taxonomy
Section titled “emdash taxonomy”Manage taxonomies and terms.
taxonomy list
Section titled “taxonomy list”npx emdash taxonomy listtaxonomy terms <name>
Section titled “taxonomy terms <name>”npx emdash taxonomy terms categoriesnpx emdash taxonomy terms tags --limit 50| Option | Alias | Description |
|---|---|---|
--limit | -l | Maximum terms |
--cursor | Pagination cursor |
taxonomy add-term <taxonomy>
Section titled “taxonomy add-term <taxonomy>”npx emdash taxonomy add-term categories --name "Tech" --slug technpx emdash taxonomy add-term categories --name "Frontend" --parent 01PARENT123| Option | Description |
|---|---|
--name | Term label (required) |
--slug | Term slug (defaults to slugified name) |
--parent | Parent term ID (for hierarchical taxonomies) |
emdash menu
Section titled “emdash menu”Manage navigation menus.
menu list
Section titled “menu list”npx emdash menu listmenu get <name>
Section titled “menu get <name>”npx emdash menu get primaryReturns the menu with all its items.
emdash export-seed
Section titled “emdash export-seed”Export database schema and content as a seed file. Works directly on a local SQLite file.
npx emdash export-seed [options] > seed.jsonOptions
Section titled “Options”| Option | Alias | Description | Default |
|---|---|---|---|
--database | -d | Database file path | ./data.db |
--cwd | Working directory | Current directory | |
--with-content | Include content (all or comma-separated collections) | ||
--no-pretty | Disable JSON formatting | false |
Output Format
Section titled “Output Format”The exported seed file includes:
- Settings: Site title, tagline, social links
- Collections: All collection definitions with fields
- Taxonomies: Taxonomy definitions and terms
- Menus: Navigation menus with items
- Widget Areas: Widget areas and widgets
- Content (if requested): Entries with
$mediareferences and$ref:syntax for portability
emdash secrets generate
Section titled “emdash secrets generate”Generate an EMDASH_ENCRYPTION_KEY for your deployment. The key is used to
encrypt plugin secrets at rest.
npx emdash secrets generatePrints the new key to stdout. Pipe it into your secret store, or write it
straight to your local .env file with --write. The same .env file is
read by Node and, in local development, by Wrangler and the Cloudflare Vite
plugin:
npx emdash secrets generate --write .env--write refuses to overwrite an existing entry without --force.
Replacing a key in a deployment with existing encrypted data will leave
those secrets unreadable, so the protection is intentional.
emdash secrets fingerprint <key>
Section titled “emdash secrets fingerprint <key>”Print the 8-character fingerprint (kid) of a key without exposing its value. This is useful in CI for verifying the right key was deployed. The following command prints a key’s fingerprint:
npx emdash secrets fingerprint emdash_enc_v1_...Generated Files
Section titled “Generated Files”.emdash/types.ts
Section titled “.emdash/types.ts”The emdash types command generates TypeScript interfaces for each collection:
// Generated by EmDash CLI// Do not edit manually - run `emdash types` to regenerate
import type { PortableTextBlock } from "emdash";
export interface Post { id: string; title: string; content: PortableTextBlock[]; publishedAt: Date | null;}.emdash/schema.json
Section titled “.emdash/schema.json”The command also writes a raw schema export for tooling:
{ "version": "a1b2c3d4", "collections": [ { "slug": "posts", "label": "Posts", "fields": [...] } ]}Environment Variables
Section titled “Environment Variables”| Variable | Description |
|---|---|
EMDASH_DATABASE_URL | Override database URL |
EMDASH_TOKEN | Auth token for remote operations |
EMDASH_URL | Default URL for commands using the shared remote client |
EMDASH_HEADERS | Newline-separated custom request headers for the shared remote client and login |
EMDASH_ENCRYPTION_KEY | Key for encrypting plugin secrets at rest. Operator-provided — never stored in the database. Generate with emdash secrets generate. |
EMDASH_PREVIEW_SECRET | Optional override for preview HMAC secret. When unset, EmDash generates and persists one in the options table. |
EMDASH_IP_SALT | Optional override for the commenter-IP hash salt. When unset, EmDash generates and persists one in the options table. |
EMDASH_AUTH_SECRET | Legacy. Used as the IP-salt source if set, so existing installs keep stable commenter-IP hashes across upgrade. New installs should not set this. |
Package scripts
Section titled “Package scripts”Add common commands as package.json scripts for convenience:
{ "scripts": { "dev": "astro dev", "types": "emdash types", "export-seed": "emdash export-seed", "db:reset": "rm -f data.db" }}Exit Codes
Section titled “Exit Codes”| Code | Description |
|---|---|
0 | Success |
1 | Error (configuration, network, database) |