Skip to content

CLI Reference

The EmDash CLI provides commands for managing an EmDash CMS instance — database setup, type generation, content CRUD, schema management, media, and more.

The CLI is included with the emdash package. Install it with the following command:

Terminal window
npm install emdash

Run 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.

Commands using the shared remote client resolve authentication in this order:

  1. --token flag — explicit token on the command line
  2. EMDASH_TOKEN env var
  3. Stored credentials from ~/.config/emdash/auth.json (saved by emdash login)
  4. 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.

These flags are available on commands using the shared remote client:

FlagAliasDescriptionDefault
--url-uEmDash instance URLEMDASH_URL or http://localhost:4321
--token-tAuth tokenFrom env/stored creds
--header "Name: Value"-HCustom request header; may be repeatedFrom EMDASH_HEADERS/stored creds
--jsonOutput as JSON (for piping)Auto-detected from TTY

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.

Check or apply the core migration set emitted by an Astro build.

Terminal window
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.

OptionDescription
--checkApply nothing; exit non-zero for pending or unknown migration records
--statusReport exact status without applying; exit zero after a successful report
--jsonEmit the stable migration report as JSON
--manifest <path>Read a non-standard manifest path
--from-configExplicitly 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.

CodeMeaning
0Success, including a successful --status report
1Validation, configuration, target, migration, or cleanup error
2--check found pending known migrations
3--check found unknown applied records (takes precedence over pending)
4Confirmation missing, declined, or target fingerprint mismatch
130Interrupted after bounded executor cleanup

See Manage Core Database Migrations for deployment order, target credentials, and D1 serialization.

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.

Generate TypeScript types from a running EmDash instance’s schema.

Terminal window
npx emdash types [options]
OptionAliasDescriptionDefault
--url-uEmDash instance URLhttp://localhost:4321
--token-tAuth tokenFrom env/stored creds
--output-oOutput path for types.emdash/types.ts
--cwdWorking directoryCurrent directory
Terminal window
# Generate types from local dev server
npx emdash types
# Generate from remote instance
npx emdash types --url https://my-site.pages.dev
# Custom output path
npx emdash types --output src/types/emdash.ts
  1. Fetches the schema from the instance
  2. Generates TypeScript type definitions
  3. Writes types to the output file
  4. Writes schema.json alongside for reference

Log in to an EmDash instance using OAuth Device Flow.

Terminal window
npx emdash login [options]
OptionAliasDescriptionDefault
--url-uEmDash instance URLhttp://localhost:4321
  1. Discovers auth endpoints from the instance
  2. If localhost and no auth configured, uses dev bypass automatically
  3. Otherwise initiates OAuth Device Flow — displays a code and opens your browser
  4. Polls for authorization, then saves credentials to ~/.config/emdash/auth.json

Saved credentials are used automatically by all subsequent commands targeting the same instance.

Log out and remove stored credentials.

Terminal window
npx emdash logout [options]
OptionAliasDescriptionDefault
--url-uEmDash instance URLhttp://localhost:4321

Show the current authenticated user.

Terminal window
npx emdash whoami [options]
OptionAliasDescriptionDefault
--url-uEmDash instance URLhttp://localhost:4321
--token-tAuth tokenFrom env/stored creds
--jsonOutput as JSON

Displays email, name, role, auth method, and instance URL.

Manage content items. All subcommands use the remote API via EmDashClient.

Terminal window
npx emdash content list posts
npx emdash content list posts --status published --limit 10
OptionDescription
--statusFilter by status
--limitMaximum items
--cursorPagination cursor
Terminal window
npx emdash content get posts 01ABC123
npx emdash content get posts 01ABC123 --raw
OptionDescription
--rawReturn 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.

Terminal window
npx emdash content create posts --data '{"title": "Hello"}'
npx emdash content create posts --file post.json --slug hello-world
cat post.json | npx emdash content create posts --stdin
OptionDescription
--dataJSON string with content data
--fileRead data from a JSON file
--stdinRead data from stdin
--slugContent slug
--localeContent locale
--translation-ofID of a content item to link this as a translation of
--draftKeep 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.

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:

Terminal window
# 1. Read the item, note the _rev
npx emdash content get posts 01ABC123
# 2. Update with the _rev from step 1
npx emdash content update posts 01ABC123 \
--rev MToyMDI2LTAyLTE0... \
--data '{"title": "Updated"}'
OptionDescription
--revRevision token from get (required)
--dataJSON string with content data
--fileRead data from a JSON file

If the item has changed since your get, the server returns 409 Conflict — re-read and try again.

Terminal window
npx emdash content delete posts 01ABC123

Soft-deletes the content item (moves to trash).

Terminal window
npx emdash content publish posts 01ABC123
Terminal window
npx emdash content unpublish posts 01ABC123
Terminal window
npx emdash content schedule posts 01ABC123 --at 2026-03-01T09:00:00Z
OptionDescription
--atISO 8601 datetime (required)
Terminal window
npx emdash content restore posts 01ABC123

Restores a trashed content item.

Manage collections and fields.

Terminal window
npx emdash schema list

Lists all collections.

Terminal window
npx emdash schema get posts

Shows a collection with all its fields.

Terminal window
npx emdash schema create articles --label Articles
npx emdash schema create articles --label Articles --label-singular Article --description "Blog articles"
OptionDescription
--labelCollection label (required)
--label-singularSingular label
--descriptionCollection description
Terminal window
npx emdash schema delete articles
npx emdash schema delete articles --force
OptionDescription
--forceSkip confirmation

Prompts for confirmation unless --force is set.

Terminal window
npx emdash schema add-field posts body --type portableText --label "Body Content"
npx emdash schema add-field posts featured --type boolean --required
OptionDescription
--typeField type: string, text, number, integer, boolean, datetime, image, reference, portableText, json (required)
--labelField label (defaults to field slug)
--requiredWhether the field is required
Terminal window
npx emdash schema remove-field posts featured

Manage media items.

Terminal window
npx emdash media list
npx emdash media list --mime image/png --limit 20
OptionDescription
--mimeFilter by MIME type
--limitNumber of items
--cursorPagination cursor
Terminal window
npx emdash media upload ./photo.jpg
npx emdash media upload ./photo.jpg --alt "A sunset" --caption "Taken in Bristol"
OptionDescription
--altAlt text
--captionCaption text
Terminal window
npx emdash media get 01MEDIA123
Terminal window
npx emdash media delete 01MEDIA123

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.

Terminal window
npx emdash media repair-usage --collection posts
npx emdash media repair-usage --all
npx emdash media repair-usage --all --json
OptionAliasDescription
--collection-cRepair one content collection
--allRepair 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.

Full-text search across content.

Terminal window
npx emdash search "hello world"
npx emdash search "hello" --collection posts --limit 5
OptionAliasDescription
--collection-cFilter by collection
--limit-lMaximum results

Manage taxonomies and terms.

Terminal window
npx emdash taxonomy list
Terminal window
npx emdash taxonomy terms categories
npx emdash taxonomy terms tags --limit 50
OptionAliasDescription
--limit-lMaximum terms
--cursorPagination cursor
Terminal window
npx emdash taxonomy add-term categories --name "Tech" --slug tech
npx emdash taxonomy add-term categories --name "Frontend" --parent 01PARENT123
OptionDescription
--nameTerm label (required)
--slugTerm slug (defaults to slugified name)
--parentParent term ID (for hierarchical taxonomies)

Manage navigation menus.

Terminal window
npx emdash menu list
Terminal window
npx emdash menu get primary

Returns the menu with all its items.

Export database schema and content as a seed file. Works directly on a local SQLite file.

Terminal window
npx emdash export-seed [options] > seed.json
OptionAliasDescriptionDefault
--database-dDatabase file path./data.db
--cwdWorking directoryCurrent directory
--with-contentInclude content (all or comma-separated collections)
--no-prettyDisable JSON formattingfalse

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 $media references and $ref: syntax for portability

Generate an EMDASH_ENCRYPTION_KEY for your deployment. The key is used to encrypt plugin secrets at rest.

Terminal window
npx emdash secrets generate

Prints 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:

Terminal window
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.

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:

Terminal window
npx emdash secrets fingerprint emdash_enc_v1_...

The emdash types command generates TypeScript interfaces for each collection:

.emdash/types.ts
// 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;
}

The command also writes a raw schema export for tooling:

.emdash/schema.json
{
"version": "a1b2c3d4",
"collections": [
{
"slug": "posts",
"label": "Posts",
"fields": [...]
}
]
}
VariableDescription
EMDASH_DATABASE_URLOverride database URL
EMDASH_TOKENAuth token for remote operations
EMDASH_URLDefault URL for commands using the shared remote client
EMDASH_HEADERSNewline-separated custom request headers for the shared remote client and login
EMDASH_ENCRYPTION_KEYKey for encrypting plugin secrets at rest. Operator-provided — never stored in the database. Generate with emdash secrets generate.
EMDASH_PREVIEW_SECRETOptional override for preview HMAC secret. When unset, EmDash generates and persists one in the options table.
EMDASH_IP_SALTOptional override for the commenter-IP hash salt. When unset, EmDash generates and persists one in the options table.
EMDASH_AUTH_SECRETLegacy. Used as the IP-salt source if set, so existing installs keep stable commenter-IP hashes across upgrade. New installs should not set this.

Add common commands as package.json scripts for convenience:

package.json
{
"scripts": {
"dev": "astro dev",
"types": "emdash types",
"export-seed": "emdash export-seed",
"db:reset": "rm -f data.db"
}
}
CodeDescription
0Success
1Error (configuration, network, database)