emdash-cli

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

EmDash CLI

EmDash CLI

The EmDash CLI (
emdash
, with the short alias
em
) manages EmDash CMS instances. Commands fall into two categories:
  • Local commands work with project files or a configured database:
    init
    ,
    doctor
    ,
    seed
    ,
    migrate
    ,
    export-seed
    , and
    secrets
    .
  • Remote commands talk to a running EmDash instance:
    types
    ,
    login
    ,
    logout
    ,
    whoami
    ,
    content
    ,
    schema
    ,
    media
    ,
    search
    ,
    taxonomy
    ,
    menu
    , and
    site
    .
Run
npx emdash --help
and
npx emdash <command> --help
for the installed version's exact commands and flags. Resolve the current target with a read command before a destructive or bulk mutation; examples in this skill do not authorize changing an instance the user did not place in scope.
EmDash CLI(
emdash
,短别名为
em
)用于管理 EmDash CMS 实例。命令分为两类:
  • 本地命令用于处理项目文件或已配置的数据库:
    init
    、
    doctor
    、
    seed
    、
    migrate
    、
    export-seed
    和
    secrets
    。
  • 远程命令用于与正在运行的 EmDash 实例通信:
    types
    、
    login
    、
    logout
    、
    whoami
    、
    content
    、
    schema
    、
    media
    、
    search
    、
    taxonomy
    、
    menu
    和
    site
    。
要查看已安装版本的确切命令和标志,请运行
npx emdash --help
和
npx emdash <command> --help
。在执行破坏性或批量修改之前,先使用只读命令确定当前目标;本 skill 中的示例并不授权更改用户未指定范围的实例。

Authentication

身份验证

Remote commands resolve auth automatically:
  1. --token
    flag
  2. EMDASH_TOKEN
    env var
  3. Stored credentials from
    emdash login
  4. Dev bypass (localhost only — no token needed)
For a localhost development server with the development bypass enabled, the client can authenticate automatically. For a remote instance, run
emdash login --url https://example.com
or provide a scoped token.
远程命令会自动按以下顺序解析身份验证信息:
  1. --token
    标志
  2. EMDASH_TOKEN
    环境变量
  3. emdash login
    保存的凭据
  4. 开发绕过(dev bypass,仅限 localhost——无需 token)
对于启用了 dev bypass 的 localhost 开发服务器,客户端可以自动完成身份验证。对于远程实例,请运行
emdash login --url https://example.com
或提供具有限定作用域的 token。

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.
部署在 Cloudflare Access 或其他反向代理之后的站点,需要在每个请求中携带身份验证请求头。CLI 支持通过
--header
标志和环境变量进行配置。

Service tokens for automation

用于自动化的服务令牌

bash
undefined
bash
undefined

Provide sensitive headers through the environment in CI.

在 CI 中通过环境变量提供敏感请求头。

export EMDASH_HEADERS="CF-Access-Client-Id: xxx CF-Access-Client-Secret: yyy" npx emdash whoami --url https://example.com

`emdash login --header` persists custom headers to `~/.config/emdash/auth.json` for later commands. Prefer environment-provided headers in CI so a service secret is not written to the credential file or shell history.
export EMDASH_HEADERS="CF-Access-Client-Id: xxx CF-Access-Client-Secret: yyy" npx emdash whoami --url https://example.com

`emdash login --header` 会将自定义请求头持久化到 `~/.config/emdash/auth.json`,供后续命令使用。在 CI 中应优先通过环境变量提供请求头,以免将服务密钥写入凭据文件或 shell 历史记录。

Cloudflare Access Browser Flow

Cloudflare Access 浏览器流程

If you don't have service tokens and
cloudflared
is installed, the CLI will automatically:
  1. Detect when Access blocks the request
  2. Try to get a cached JWT via
    cloudflared access token
  3. 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.
如果没有服务令牌,但已安装
cloudflared
,CLI 将自动执行以下操作:
  1. 检测 Access 阻止请求的情况
  2. 尝试通过
    cloudflared access token
    获取缓存的 JWT
  3. 回退到
    cloudflared access login
    以执行基于浏览器的身份验证
此方式适用于交互式使用,但不适合 CI。自动化操作应使用服务令牌。

Generic Reverse Proxy Auth

通用反向代理身份验证

The
--header
flag works with any auth scheme:
bash
undefined
--header
标志适用于任何身份验证方案:
bash
undefined

Basic auth

基础身份验证

npx emdash login --url https://example.com -H "Authorization: Basic dXNlcjpwYXNz"
npx emdash login --url https://example.com -H "Authorization: Basic dXNlcjpwYXNz"

Custom auth header

自定义身份验证请求头

npx emdash login --url https://example.com -H "X-API-Key: secret123"
undefined
npx emdash login --url https://example.com -H "X-API-Key: secret123"
undefined

Quick Reference

快速参考

Database Setup

数据库设置

For normal site startup, use the project's package script. The first request runs pending migrations and, before setup is completed, applies the bundled seed's schema and structure once; sample content comes from the setup wizard,
/_emdash/api/setup/dev-bypass
, or
emdash seed
. The Astro integration generates
emdash-env.d.ts
when the server starts.
bash
undefined
正常启动站点时,请使用项目的 package script。首次请求会执行待处理的 migration;在 setup 完成前,还会一次性应用 bundled seed 的 schema 和结构。示例内容来自 setup wizard、
/_emdash/api/setup/dev-bypass
或
emdash seed
。服务器启动时,Astro integration 会生成
emdash-env.d.ts
。
bash
undefined

Start the site with its package script

使用项目的 package script 启动站点

pnpm dev
pnpm dev

Export an existing database as a seed file

将现有数据库导出为 seed 文件

(the runtime auto-discovers .emdash/seed.json on first boot;

(运行时会在首次启动时自动发现 .emdash/seed.json;

mkdir -p
because the directory may not exist yet)

使用 mkdir -p,因为该目录可能尚不存在)

mkdir -p .emdash npx emdash export-seed > .emdash/seed.json npx emdash export-seed --with-content=all > .emdash/seed.json
undefined
mkdir -p .emdash npx emdash export-seed > .emdash/seed.json npx emdash export-seed --with-content=all > .emdash/seed.json
undefined

Type Generation

类型生成

bash
undefined
bash
undefined

Generate types from local dev server

从本地开发服务器生成类型

npx emdash types
npx emdash types

Generate from remote

从远程实例生成类型

npx emdash types --url https://example.com
npx emdash types --url https://example.com

Custom output path

自定义输出路径

npx emdash types --output src/types/cms.ts

Writes `.emdash/types.ts` (TypeScript interfaces) and `.emdash/schema.json`.
npx emdash types --output src/types/cms.ts

将类型写入 `.emdash/types.ts`(TypeScript interfaces)和 `.emdash/schema.json`。

Authentication

身份验证

bash
undefined
bash
undefined

Login (OAuth Device Flow)

登录(OAuth Device Flow)

npx emdash login --url https://example.com
npx emdash login --url https://example.com

Check current user

查看当前用户

npx emdash whoami
npx emdash whoami

Logout

退出登录

npx emdash logout
npx emdash logout

Generate an encryption key for deployment

为部署生成加密密钥

npx emdash secrets generate
undefined
npx emdash secrets generate
undefined

Content CRUD

内容 CRUD

The CLI is designed for agents. Create and update auto-publish by default so agents get read-after-write consistency without managing drafts.
bash
undefined
该 CLI 专为 agents 设计。create 和 update 默认会自动发布,让 agents 无需管理草稿即可获得写后读一致性。
bash
undefined

List content

列出内容

npx emdash content list posts npx emdash content list posts --status published --limit 10
npx emdash content list posts npx emdash content list posts --status published --limit 10

Get a single item (Portable Text fields converted to markdown)

获取单个条目(Portable Text 字段会转换为 markdown)

Returns draft data if a pending draft exists

如果存在待处理草稿,则返回草稿数据

npx emdash content get posts 01ABC123 npx emdash content get posts 01ABC123 --raw # skip PT->markdown conversion npx emdash content get posts 01ABC123 --published # ignore pending drafts
npx emdash content get posts 01ABC123 npx emdash content get posts 01ABC123 --raw # 跳过 PT->markdown 转换 npx emdash content get posts 01ABC123 --published # 忽略待处理草稿

Create content (auto-publishes by default)

创建内容(默认自动发布)

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 '...' # keep as draft cat post.json | npx emdash content create posts --stdin
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

Update (requires --rev from a prior get, auto-publishes by default)

更新(需要使用先前 get 获得的 --rev,默认自动发布)

npx emdash content update posts 01ABC123 --rev MToyMDI2... --data '{"title": "Updated"}' npx emdash content update posts 01ABC123 --rev MToyMDI2... --draft --data '...' # keep as draft
npx emdash content update posts 01ABC123 --rev MToyMDI2... --data '{"title": "Updated"}' npx emdash content update posts 01ABC123 --rev MToyMDI2... --draft --data '...' # 保留为草稿

Delete (soft delete)

删除(软删除)

npx emdash content delete posts 01ABC123
npx emdash content delete posts 01ABC123

Lifecycle

生命周期

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
undefined
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
undefined

Schema Management

Schema 管理

bash
undefined
bash
undefined

List collections

列出 collection

npx emdash schema list
npx emdash schema list

Get collection with fields

获取 collection 及其 fields

npx emdash schema get posts
npx emdash schema get posts

Create collection

创建 collection

npx emdash schema create articles --label Articles --description "Blog articles"
npx emdash schema create articles --label Articles --description "Blog articles"

Delete a collection after inspecting it and confirming the target

删除 collection 前先检查并确认目标

npx emdash schema get articles npx emdash schema delete articles
npx emdash schema get articles npx emdash schema delete articles

Add field

添加 field

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 add-field posts body --type portableText --label "Body Content" npx emdash schema add-field posts featured --type boolean --required

Remove field

移除 field

npx emdash schema remove-field posts featured

`schema add-field` supports the field types printed by `npx emdash schema add-field --help`. The full product schema supports additional field types that are not necessarily creatable through this command.
npx emdash schema remove-field posts featured

`schema add-field` 支持 `npx emdash schema add-field --help` 输出的 field 类型。完整产品 schema 还支持其他 field 类型,但这些类型不一定能通过此命令创建。

Media

Media

bash
undefined
bash
undefined

List media

列出 media

npx emdash media list npx emdash media list --mime image/png
npx emdash media list npx emdash media list --mime image/png

Upload

上传

npx emdash media upload ./photo.jpg --alt "A sunset" --caption "Bristol, 2026"
npx emdash media upload ./photo.jpg --alt "A sunset" --caption "Bristol, 2026"

Get / delete

获取/删除

npx emdash media get 01MEDIA123 npx emdash media delete 01MEDIA123
undefined
npx emdash media get 01MEDIA123 npx emdash media delete 01MEDIA123
undefined

Search

搜索

bash
npx emdash search "hello world"
npx emdash search "hello" --collection posts --limit 5
bash
npx emdash search "hello world"
npx emdash search "hello" --collection posts --limit 5

Taxonomies

Taxonomy

bash
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
bash
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

Menu

bash
npx emdash menu list
npx emdash menu get primary
bash
npx emdash menu list
npx emdash menu get primary

Site Export and Import

站点导出与导入

emdash site
copies a whole site (content model, content, history, settings, and media, but no users or secrets) into a
.emdash
site package, and imports a package into an empty site. The token needs
admin
, which the
emdash login
token has, or the
transfer:export
,
transfer:analyze
, and
transfer:execute
scopes. An
INSUFFICIENT_SCOPE
error means the token has neither. A package holds every entry and the email addresses of authors and commenters: treat it like a database backup.
bash
undefined
emdash site
会将整个站点(content model、content、history、settings 和 media,但不含 users 或 secrets)复制到
.emdash
站点包中,也可将站点包导入空站点。Token 需要具备
admin
权限,而
emdash login
token 已具备该权限;也可以使用包含
transfer:export
、
transfer:analyze
和
transfer:execute
作用域的 token。出现
INSUFFICIENT_SCOPE
错误,意味着 token 不具备上述任一权限。站点包包含所有条目以及 authors 和 commenters 的电子邮件地址,应将其视为数据库备份。
bash
undefined

Export (re-run the same command to resume after an interruption)

导出(中断后可重新运行同一命令以继续)

npx emdash site export --url https://old.example.com --output site.emdash npx emdash site export --url https://old.example.com --output site.emdash --no-comments
npx emdash site export --url https://old.example.com --output site.emdash npx emdash site export --url https://old.example.com --output site.emdash --no-comments

Import, step 1: upload and analyze; prints the plan and its digest

导入第 1 步:上传并分析;打印计划和摘要

npx emdash site import site.emdash --url https://new.example.com --analyze npx emdash site import site.emdash --url https://new.example.com --analyze
--map-principal editor@example.com=editor@example.com --use-target-title
npx emdash site import site.emdash --url https://new.example.com --analyze npx emdash site import site.emdash --url https://new.example.com --analyze
--map-principal editor@example.com=editor@example.com --use-target-title

Import, step 2: execute exactly the reviewed plan

导入第 2 步:严格执行已审阅的计划

npx emdash site import site.emdash --url https://new.example.com --plan sha256:<hex> --confirm
npx emdash site import site.emdash --url https://new.example.com --plan sha256:<hex> --confirm

Follow up on an import by operation id

通过 operation ID 跟踪导入

npx emdash site import status <operation-id> --url https://new.example.com npx emdash site import resume <operation-id> [site.emdash] --url https://new.example.com npx emdash site import receipt <operation-id> --url https://new.example.com
npx emdash site import status <operation-id> --url https://new.example.com npx emdash site import resume <operation-id> [site.emdash] --url https://new.example.com npx emdash site import receipt <operation-id> --url https://new.example.com

Stop an import, or lift the write block a failed or cancelled import leaves

停止导入,或解除失败或已取消导入留下的写入锁定

(neither deletes what the import wrote; --yes skips the prompt)

(两者都不会删除导入已写入的数据;--yes 会跳过提示)

npx emdash site import cancel <operation-id> --url https://new.example.com npx emdash site import abandon <operation-id> --url https://new.example.com

Show the user the plan (differences from the source site, warnings, blockers, principal mappings) and get their confirmation before running `--confirm`; it writes to the target site and blocks other writes there until it finishes. `site import` exits `2` when the plan has blockers, and `site import status` exits `1` for an import that failed, was cancelled or abandoned, or expired. Only cancel or abandon an import when the user asks: abandoning leaves partial data on the site, which then has to be reset before another import. `--map-principal` takes `<principal id or email>=<user id, email, or none>` and is repeatable; decision flags only work with `--analyze`, and each change produces a new plan digest. The public site is not hidden during an import, so the target should stay private until the command prints a receipt with `receiptDigestValid: true`.
npx emdash site import cancel <operation-id> --url https://new.example.com npx emdash site import abandon <operation-id> --url https://new.example.com

向用户展示计划(与源站点的差异、警告、阻塞项和 principal 映射),并在运行 `--confirm` 前获得用户确认。该命令会写入目标站点,并在完成前阻止该站点上的其他写入操作。当计划包含阻塞项时,`site import` 的退出码为 `2`;如果导入失败、被取消、被放弃或已过期,`site import status` 的退出码为 `1`。仅在用户要求时取消或放弃导入:放弃会在站点中留下部分数据,之后必须重置才能再次导入。`--map-principal` 接受 `<principal id or email>=<user id, email, or none>` 格式且可以重复使用;决策标志仅在配合 `--analyze` 时有效,每次更改都会生成新的计划摘要。导入期间不会隐藏公开站点,因此目标站点应保持私有,直到命令打印包含 `receiptDigestValid: true` 的 receipt。

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.
CLI 默认在 create 和 update 时自动发布。这意味着:
  • create
    创建条目后立即发布
  • update
    更新条目;如果创建了草稿 revision,则会将其发布
  • get
    如果存在待处理草稿(例如来自 admin UI),则返回草稿数据
在 create/update 时使用
--draft
可跳过自动发布。在 get 时使用
--published
可忽略待处理草稿。
支持 revisions 的 collection 会将编辑存储为草稿 revision。CLI 会透明地处理这些操作,agents 无需了解 collection 是否使用 revisions。

JSON Output

JSON 输出

All remote commands support
--json
for machine-readable output. It's auto-enabled when stdout is piped.
emdash site
always writes progress to stderr, so stdout holds only the JSON result; errors are
{ "error": { "code", "message" } }
.
bash
undefined
所有远程命令都支持
--json
,用于输出机器可读的数据。当 stdout 被管道传输时,该选项会自动启用。
emdash site
始终将进度写入 stderr,因此 stdout 仅保留 JSON 结果;错误格式为
{ "error": { "code", "message" } }
。
bash
undefined

Pipe to jq

管道传输至 jq

npx emdash content list posts --json | jq '.items[].slug'
npx emdash content list posts --json | jq '.items[].slug'

Use in scripts

在脚本中使用

ID=$(npx emdash content create posts --data '{"title":"Hello"}' --json | jq -r '.id')
undefined
ID=$(npx emdash content create posts --data '{"title":"Hello"}' --json | jq -r '.id')
undefined

Editing Flow

编辑流程

For details on how content editing works — Portable Text/markdown conversion,
_rev
tokens, and raw mode — see EDITING-FLOW.md.
有关内容编辑工作原理的详细信息——Portable Text/markdown 转换、
_rev
token 和 raw mode——请参阅 EDITING-FLOW.md。