| name | emdash-cli |
| description | Use the EmDash CLI to manage content, schema, media, and more. Use this skill when you need to interact with a running EmDash instance from the command line — creating content, managing collections, uploading media, generating types, or scripting CMS operations. |
EmDash CLI
The EmDash CLI (emdash or ec) manages EmDash CMS instances. Commands fall into two categories:
- Local commands — work directly on a SQLite file, no running server needed:
init, dev, seed, export-seed, auth secret
- Remote commands — talk to a running EmDash instance via HTTP:
types, login, logout, whoami, content, schema, media, search, taxonomy, menu
Authentication
Remote commands resolve auth automatically:
--token flag
EMDASH_TOKEN env var
- Stored credentials from
emdash login
- Dev bypass (localhost only — no token needed)
For local dev servers, just run the command — auth is handled automatically. For remote instances, run emdash login --url https://my-site.pages.dev first.
Custom Headers & Reverse Proxies
Sites behind Cloudflare Access or other reverse proxies need auth headers on every request. The CLI supports this via --header flags and environment variables.
Service Tokens (Recommended for CI/Automation)
npx emdash login --url https://my-site.pages.dev \
--header "CF-Access-Client-Id: xxx.access" \
--header "CF-Access-Client-Secret: yyy"
npx emdash login -H "CF-Access-Client-Id: xxx" -H "CF-Access-Client-Secret: yyy"
export EMDASH_HEADERS="CF-Access-Client-Id: xxx
CF-Access-Client-Secret: yyy"
npx emdash login --url https://my-site.pages.dev
Headers are persisted to ~/.config/emdash/auth.json after login, so subsequent commands inherit them automatically.
Cloudflare Access Browser Flow
If you don't have service tokens and cloudflared is installed, the CLI will automatically:
- Detect when Access blocks the request
- Try to get a cached JWT via
cloudflared access token
- Fall back to
cloudflared access login for browser-based auth
This works for interactive use but isn't suitable for CI. Use service tokens for automation.
Generic Reverse Proxy Auth
The --header flag works with any auth scheme:
npx emdash login --url https://example.com -H "Authorization: Basic dXNlcjpwYXNz"
npx emdash login --url https://example.com -H "X-API-Key: secret123"
Quick Reference
Database Setup
npx emdash init
npx emdash dev
npx emdash dev --types
npx emdash seed .emdash/seed.json
npx emdash export-seed > seed.json
npx emdash export-seed --with-content > seed.json
Type Generation
npx emdash types
npx emdash types --url https://my-site.pages.dev
npx emdash types --output src/types/cms.ts
Writes .emdash/types.ts (TypeScript interfaces) and .emdash/schema.json.
Authentication
npx emdash login --url https://my-site.pages.dev
npx emdash whoami
npx emdash logout
npx emdash auth secret
Content CRUD
The CLI is designed for agents. Create and update auto-publish by default so agents get read-after-write consistency without managing drafts.
npx emdash content list posts
npx emdash content list posts --status published --limit 10
npx emdash content get posts 01ABC123
npx emdash content get posts 01ABC123 --raw
npx emdash content get posts 01ABC123 --published
npx emdash content create posts --data '{"title": "Hello", "body": "# World"}'
npx emdash content create posts --file post.json --slug hello-world
npx emdash content create posts --draft --data '...'
cat post.json | npx emdash content create posts --stdin
npx emdash content update posts 01ABC123 --rev MToyMDI2... --data '{"title": "Updated"}'
npx emdash content update posts 01ABC123 --rev MToyMDI2... --draft --data '...'
npx emdash content delete posts 01ABC123
npx emdash content publish posts 01ABC123
npx emdash content unpublish posts 01ABC123
npx emdash content schedule posts 01ABC123 --at 2026-03-01T09:00:00Z
npx emdash content restore posts 01ABC123
Schema Management
npx emdash schema list
npx emdash schema get posts
npx emdash schema create articles --label Articles --description "Blog articles"
npx emdash schema delete articles --force
npx emdash schema add-field posts body --type portableText --label "Body Content"
npx emdash schema add-field posts featured --type boolean --required
npx emdash schema remove-field posts featured
Field types: string, text, number, integer, boolean, datetime, image, reference, portableText, json.
Media
npx emdash media list
npx emdash media list --mime image/png
npx emdash media upload ./photo.jpg --alt "A sunset" --caption "Bristol, 2026"
npx emdash media get 01MEDIA123
npx emdash media delete 01MEDIA123
Search
npx emdash search "hello world"
npx emdash search "hello" --collection posts --limit 5
Taxonomies
npx emdash taxonomy list
npx emdash taxonomy terms categories
npx emdash taxonomy add-term categories --name "Tech" --slug tech
npx emdash taxonomy add-term categories --name "Frontend" --parent 01PARENT123
Menus
npx emdash menu list
npx emdash menu get primary
Drafts and Publishing
The CLI auto-publishes on create and update by default. This means:
create creates the item and immediately publishes it
update updates the item and publishes if a draft revision was created
get returns draft data if a pending draft exists (e.g. from the admin UI)
Use --draft on create/update to skip auto-publishing. Use --published on get to ignore pending drafts.
Collections that support revisions store edits as draft revisions. The CLI handles this transparently — agents don't need to know whether a collection uses revisions or not.
JSON Output
All remote commands support --json for machine-readable output. It's auto-enabled when stdout is piped.
npx emdash content list posts --json | jq '.items[].slug'
ID=$(npx emdash content create posts --data '{"title":"Hello"}' --json | jq -r '.id')
Editing Flow
For details on how content editing works — Portable Text/markdown conversion, _rev tokens, and raw mode — see EDITING-FLOW.md.