--- title: CLI Reference description: Command-line interface for EmDash CMS. --- import { Aside } from "@astrojs/starlight/components"; The EmDash CLI provides commands for managing an EmDash CMS instance — database setup, type generation, content CRUD, schema management, media, and more. ## Installation The CLI is included with the `emdash` package: ```bash npm install emdash ``` Run commands with `npx emdash` or add scripts to `package.json`. The binary is also available as `em` for brevity. ## Authentication Commands that talk to a running EmDash instance (everything except `init`, `seed`, `export-seed`, and `auth secret`) 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 Most commands accept `--url` (default `http://localhost:4321`) and `--token` flags. When targeting a local dev server, no token is needed. ## Common Flags These flags are available on all remote commands: | Flag | Alias | Description | Default | | --------- | ----- | --------------------------- | ------------------------ | | `--url` | `-u` | EmDash instance URL | `http://localhost:4321` | | `--token` | `-t` | Auth token | From env/stored creds | | `--json` | | Output as JSON (for piping) | Auto-detected from TTY | ## Output When stdout is a TTY, the CLI pretty-prints results with consola. When piped or when `--json` is set, it outputs raw JSON to stdout — suitable for `jq` or other tools. ## Commands ### `emdash init` Initialize the database with core schema and optional template data. ```bash npx emdash init [options] ``` #### Options | Option | Alias | Description | Default | | ------------ | ----- | ---------------------- | ----------------- | | `--database` | `-d` | Database file path | `./data.db` | | `--cwd` | | Working directory | Current directory | | `--force` | `-f` | Re-run schema and seed | `false` | #### Behavior 1. Reads `emdash` config from `package.json` 2. Creates the database file if needed 3. Runs core migrations (creates system tables) 4. Runs template `schema.sql` if configured 5. Runs template `seed.sql` if configured ### `emdash dev` Start the development server with automatic database setup. ```bash npx emdash dev [options] ``` #### Options | Option | Alias | Description | Default | | ------------ | ----- | ---------------------------------------- | ----------------- | | `--database` | `-d` | Database file path | `./data.db` | | `--types` | `-t` | Generate types from remote before starting | `false` | | `--port` | `-p` | Dev server port | `4321` | | `--cwd` | | Working directory | Current directory | #### Examples ```bash # Start dev server npx emdash dev # Custom port npx emdash dev --port 3000 # Generate types from remote before starting npx emdash dev --types ``` #### Behavior 1. Checks for and runs pending database migrations 2. If `--types` is set, generates TypeScript types from a remote instance (URL from `EMDASH_URL` env or `emdash.url` in `package.json`) 3. Starts Astro dev server with `EMDASH_DATABASE_URL` set ### `emdash types` Generate TypeScript types from a running EmDash instance's schema. ```bash npx emdash types [options] ``` #### 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 ```bash # 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 ``` #### Behavior 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 ### `emdash login` Log in to an EmDash instance using OAuth Device Flow. ```bash npx emdash login [options] ``` #### Options | Option | Alias | Description | Default | | ------- | ----- | --------------------- | ---------------------- | | `--url` | `-u` | EmDash instance URL | `http://localhost:4321` | #### Behavior 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. ### `emdash logout` Log out and remove stored credentials. ```bash npx emdash logout [options] ``` #### Options | Option | Alias | Description | Default | | ------- | ----- | --------------------- | ---------------------- | | `--url` | `-u` | EmDash instance URL | `http://localhost:4321` | ### `emdash whoami` Show the current authenticated user. ```bash npx emdash whoami [options] ``` #### 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` Manage content items. All subcommands use the remote API via `EmDashClient`. #### `content list ` ```bash npx emdash content list posts npx emdash content list posts --status published --limit 10 ``` | Option | Description | | ---------- | -------------------- | | `--status` | Filter by status | | `--limit` | Maximum items | | `--cursor` | Pagination cursor | #### `content get ` ```bash npx emdash content get posts 01ABC123 npx 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 prove you've seen what you're overwriting. #### `content create ` ```bash 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 ``` | Option | Description | | ---------- | ------------------------------ | | `--data` | JSON string with content data | | `--file` | Read data from a JSON file | | `--stdin` | Read data from stdin | | `--slug` | Content slug | | `--status` | Initial status (draft, published) | Provide data via exactly one of `--data`, `--file`, or `--stdin`. #### `content update ` Like a file editor that requires you to read before you write — you must provide the `_rev` token from a prior `get` to prove you've seen the current state. This prevents accidentally overwriting changes you haven't seen. ```bash # 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"}' ``` | 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 ` ```bash npx emdash content delete posts 01ABC123 ``` Soft-deletes the content item (moves to trash). #### `content publish ` ```bash npx emdash content publish posts 01ABC123 ``` #### `content unpublish ` ```bash npx emdash content unpublish posts 01ABC123 ``` #### `content schedule ` ```bash npx emdash content schedule posts 01ABC123 --at 2026-03-01T09:00:00Z ``` | Option | Description | | ------ | ------------------------------- | | `--at` | ISO 8601 datetime (required) | #### `content restore ` ```bash npx emdash content restore posts 01ABC123 ``` Restores a trashed content item. ### `emdash schema` Manage collections and fields. #### `schema list` ```bash npx emdash schema list ``` Lists all collections. #### `schema get ` ```bash npx emdash schema get posts ``` Shows a collection with all its fields. #### `schema create ` ```bash npx emdash schema create articles --label Articles npx 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 ` ```bash npx emdash schema delete articles npx emdash schema delete articles --force ``` | Option | Description | | --------- | ------------------- | | `--force` | Skip confirmation | Prompts for confirmation unless `--force` is set. #### `schema add-field ` ```bash 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 ` ```bash npx emdash schema remove-field posts featured ``` ### `emdash media` Manage media items. #### `media list` ```bash npx emdash media list npx emdash media list --mime image/png --limit 20 ``` | Option | Description | | ---------- | ------------------------ | | `--mime` | Filter by MIME type | | `--limit` | Number of items | | `--cursor` | Pagination cursor | #### `media upload ` ```bash npx emdash media upload ./photo.jpg npx emdash media upload ./photo.jpg --alt "A sunset" --caption "Taken in Bristol" ``` | Option | Description | | ----------- | -------------- | | `--alt` | Alt text | | `--caption` | Caption text | #### `media get ` ```bash npx emdash media get 01MEDIA123 ``` #### `media delete ` ```bash npx emdash media delete 01MEDIA123 ``` ### `emdash search` Full-text search across content. ```bash 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` Manage taxonomies and terms. #### `taxonomy list` ```bash npx emdash taxonomy list ``` #### `taxonomy terms ` ```bash npx emdash taxonomy terms categories npx emdash taxonomy terms tags --limit 50 ``` | Option | Alias | Description | | ---------- | ----- | ----------------- | | `--limit` | `-l` | Maximum terms | | `--cursor` | | Pagination cursor | #### `taxonomy add-term ` ```bash npx emdash taxonomy add-term categories --name "Tech" --slug tech npx 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` Manage navigation menus. #### `menu list` ```bash npx emdash menu list ``` #### `menu get ` ```bash npx emdash menu get primary ``` Returns the menu with all its items. ### `emdash seed` Apply a seed file to the database. This command works directly on a local SQLite file (no running server needed). ```bash npx emdash seed [path] [options] ``` #### Arguments | Argument | Description | Default | | -------- | ----------------- | --------------------- | | `path` | Path to seed file | `.emdash/seed.json` | #### Options | Option | Alias | Description | Default | | ------------------ | ----- | --------------------------------------- | --------------------------- | | `--database` | `-d` | Database file path | `./data.db` | | `--cwd` | | Working directory | Current directory | | `--validate` | | Validate only, don't apply | `false` | | `--no-content` | | Skip sample content | `false` | | `--on-conflict` | | Conflict handling: skip, update, error | `skip` | | `--uploads-dir` | | Directory for media uploads | `.emdash/uploads` | | `--media-base-url` | | Base URL for media files | `/_emdash/api/media/file` | | `--base-url` | | Site base URL (for absolute media URLs) | | #### Seed File Resolution The command looks for seed files in this order: 1. Positional argument (if provided) 2. `.emdash/seed.json` (convention) 3. Path from `package.json` `emdash.seed` field ### `emdash export-seed` Export database schema and content as a seed file. Works directly on a local SQLite file. ```bash npx emdash export-seed [options] > seed.json ``` #### 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 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 ### `emdash auth secret` Generate a secure authentication secret for your deployment. ```bash npx emdash auth secret ``` Outputs a random secret suitable for `EMDASH_AUTH_SECRET`. ## Generated Files ### `.emdash/types.ts` TypeScript interfaces generated by `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; } ``` ### `.emdash/schema.json` Raw schema export for tooling: ```json { "version": "a1b2c3d4", "collections": [ { "slug": "posts", "label": "Posts", "fields": [...] } ] } ``` ## Environment Variables | Variable | Description | | ------------------------- | ---------------------------------------- | | `EMDASH_DATABASE_URL` | Database URL (set automatically by `dev`) | | `EMDASH_TOKEN` | Auth token for remote operations | | `EMDASH_URL` | Default remote URL for `types` and `dev --types` | | `EMDASH_AUTH_SECRET` | Secret for passkey authentication | | `EMDASH_PREVIEW_SECRET` | Secret for preview token generation | ## Package Scripts ```json { "scripts": { "dev": "emdash dev", "init": "emdash init", "types": "emdash types", "seed": "emdash seed", "export-seed": "emdash export-seed", "db:reset": "rm -f data.db && emdash init" } } ``` ## Exit Codes | Code | Description | | ---- | ---------------------------------------- | | `0` | Success | | `1` | Error (configuration, network, database) |