excalidraw

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Excalidraw Skill

Excalidraw 操作技能

Step 0: Setup

步骤0:环境配置

Load companion skills when needed

根据需求加载配套技能

  • Drawing or styling a diagram → load
    excalidraw-design-guide
    (colors, sizing, anti-patterns)
  • Building a multi-element diagram or reviewing one → load
    excalidraw-workflow
    (planning, progressive drawing, review checklist)
  • Just checking status, exporting, or running a single command → no companion skills needed
  • 绘制或设计图表 → 加载
    excalidraw-design-guide
    (包含颜色、尺寸、反模式相关内容)
  • 构建或审查多元素图表 → 加载
    excalidraw-workflow
    (包含规划、渐进式绘制、审查清单相关内容)
  • 仅检查状态、导出内容或执行单个命令 → 无需加载配套技能

Check if canvas is running

检查画布是否运行

bash
excalidraw status
Returns
{"status":"healthy","elements_count":N}
if running.
bash
excalidraw status
如果画布正在运行,将返回
{"status":"healthy","elements_count":N}

Start canvas if not running

若画布未运行则启动

bash
excalidraw serve --port 3000
Open
http://localhost:3000
in a browser (required for screenshot/image export).
bash
excalidraw serve --port 3000
在浏览器中打开
http://localhost:3000
(截图/图片导出功能需要此操作)。

Install CLI (one-time)

安装CLI(仅需一次)

bash
bun add -g github:opencoredev/excalidraw-cli
bash
bun add -g github:opencoredev/excalidraw-cli

Global URL override

全局URL覆盖

bash
export EXCALIDRAW_URL=http://localhost:3000
All commands respect
EXCALIDRAW_URL
. Override per-command with
--url <url>
.

bash
export EXCALIDRAW_URL=http://localhost:3000
所有命令都会遵循
EXCALIDRAW_URL
配置。也可以通过
--url <url>
参数为单个命令指定URL。

⚡ Draw Element by Element — Don't Make the User Wait

⚡ 逐个绘制元素——不要让用户等待

Never batch everything into one command. Create each element individually so the user sees every shape appear on canvas and can redirect if something is wrong.
bash
undefined
切勿将所有操作批量执行成一个命令。逐个创建每个元素,这样用户可以看到每个形状实时出现在画布上,若出现问题可及时调整。
bash
undefined

Each element is its own call — user sees it appear immediately

每个元素单独调用——用户可立即看到元素出现

excalidraw create --type rectangle --id svc-a --x 100 --y 100 --width 160 --height 60 --text "Service A" excalidraw viewport --fit
excalidraw create --type rectangle --id svc-b --x 100 --y 240 --width 160 --height 60 --text "Service B" excalidraw viewport --fit
excalidraw create --type arrow --x 0 --y 0 --start svc-a --end svc-b excalidraw viewport --fit

**Order**: zones/containers first → nodes one by one → arrows one by one → detail labels last.

**Rule**: your first tool call must be a draw command — no exceptions. Do not reason through the whole diagram before starting. Draw the first element, then think of the next one while it renders.

**`excalidraw batch` is only for** tightly interdependent elements that must exist together. Everything else: one `create` at a time.

---
excalidraw create --type rectangle --id svc-a --x 100 --y 100 --width 160 --height 60 --text "Service A" excalidraw viewport --fit
excalidraw create --type rectangle --id svc-b --x 100 --y 240 --width 160 --height 60 --text "Service B" excalidraw viewport --fit
excalidraw create --type arrow --x 0 --y 0 --start svc-a --end svc-b excalidraw viewport --fit

**绘制顺序**:先绘制区域/容器 → 逐个绘制节点 → 逐个绘制箭头 → 最后添加细节标签。

**规则**:你的第一个工具调用必须是绘制命令——无例外。不要在开始绘制前就构思完整图表。先绘制第一个元素,在它渲染的同时再思考下一个元素。

**`excalidraw batch`仅适用于**必须同时存在的高度关联元素。其他所有元素:都要逐个使用`create`命令创建。

---

Inline Self-Check (do this mentally before EVERY element)

内联自检(在创建每个元素前在脑中完成)

Before issuing each
excalidraw create
, ask yourself:
  1. Will the text fit? Count characters in the label. Apply:
    width = max(160, charCount * 11 + 40)
    . When in doubt, go wider — truncation looks worse than a wide box.
  2. Am I drawing shapes before arrows? Arrows must always be created AFTER both their source and target shapes exist. Never draw an arrow to a shape that doesn't exist yet — it won't bind and will float or overdraw.
  3. Is there enough gap? At least 60px between adjacent shapes, 80px between tiers. Cramped = arrows cross through boxes.
Fix it now, not later. If you realize a shape is too narrow after creating it,
excalidraw update <id> --width <wider>
immediately before moving on.
在执行每个
excalidraw create
命令前,问自己:
  1. 文本是否能容纳? 统计标签的字符数。应用公式:
    width = max(160, charCount * 11 + 40)
    。拿不准时就设置更宽——文本截断比宽盒子更影响体验。
  2. 我是否先绘制了形状再绘制箭头? 箭头必须在其源形状和目标形状都创建完成后再绘制。永远不要向不存在的形状绘制箭头——这样箭头无法绑定,会漂浮或覆盖其他元素。
  3. 间距是否足够? 相邻形状之间至少保留60px间距,不同层级之间至少保留80px间距。过于拥挤会导致箭头穿过盒子。
立即修正,不要拖延。如果创建后发现形状太窄,在进行下一步前立即执行
excalidraw update <id> --width <更宽的数值>

Sizing formula

尺寸计算公式

  • Shape width:
    max(160, charCount * 11 + 40)
    pixels — the
    +40
    is mandatory padding, never skip it
  • Multi-word labels: measure the longest single word, not total chars:
    max(160, longestWord * 11 + 80)
  • Shape height: 60px single-line, 80px two-line, 100px three-line
  • Background zones: 60px padding on all sides around contained elements (not 50)
  • Arrow minimum gap: 80px between shapes — if shapes are closer, arrows will overdraw the border
  • 形状宽度:
    max(160, charCount * 11 + 40)
    像素——
    +40
    是必填内边距,切勿省略
  • 多词标签:测量最长的单个单词,而非总字符数:
    max(160, longestWord * 11 + 80)
  • 形状高度:单行文本60px,两行80px,三行100px
  • 背景区域:包含元素的四周需保留60px内边距(而非50px)
  • 箭头最小间距:形状之间至少80px——如果形状间距更近,箭头会覆盖边框

Arrow binding rules (prevents overline)

箭头绑定规则(避免覆盖)

  • Always use
    --start <id> --end <id>
    — never use raw coordinates to connect shapes
  • Create shapes first, arrows second — every time, no exceptions
  • If an arrow appears to pass through a box, the shape was too close or the arrow wasn't bound: delete and recreate with proper
    --start
    /
    --end
  • 始终使用
    --start <id> --end <id>
    ——永远不要使用原始坐标连接形状
  • 先创建形状,再创建箭头——每次都要遵守,无例外
  • 如果箭头看起来穿过了盒子,说明形状间距太近或箭头未正确绑定:删除箭头并使用正确的
    --start
    /
    --end
    参数重新创建

Quality Gate (only if something looks off)

质量检查(仅当看起来有问题时执行)

If you suspect a problem after a section of elements:
bash
excalidraw describe   # spot-check element list and IDs
excalidraw viewport --fit
Don't run this after every single element — just when something feels wrong.

如果在创建一部分元素后怀疑存在问题:
bash
excalidraw describe   # 抽查元素列表和ID
excalidraw viewport --fit
不要在每个元素创建后都执行此操作——仅在感觉有问题时使用。

Workflow: Draw a Diagram

工作流:绘制图表

Recommended order

推荐顺序

  1. excalidraw guide
    — load design best practices
  2. Plan coordinate grid on paper first (prevents overlap)
  3. excalidraw clear
    — start fresh (optional)
  4. excalidraw batch diagram.json
    — create all shapes and arrows at once
  5. excalidraw viewport --fit
    — zoom to fit all elements
  6. Run Quality Gate above
  1. excalidraw guide
    —— 加载设计最佳实践
  2. 先在纸上规划坐标网格(避免重叠)
  3. excalidraw clear
    —— 清空画布重新开始(可选)
  4. excalidraw batch diagram.json
    —— 一次性创建所有形状和箭头
  5. excalidraw viewport --fit
    —— 缩放至适配所有元素
  6. 执行上述质量检查步骤

Batch JSON format

批量JSON格式

Create a file
diagram.json
:
json
{
  "elements": [
    {
      "id": "svc-a",
      "type": "rectangle",
      "x": 100, "y": 100,
      "width": 160, "height": 60,
      "label": {"text": "Service A"},
      "strokeColor": "#1971c2",
      "backgroundColor": "#a5d8ff"
    },
    {
      "id": "svc-b",
      "type": "rectangle",
      "x": 100, "y": 240,
      "width": 160, "height": 60,
      "label": {"text": "Service B"},
      "strokeColor": "#2f9e44",
      "backgroundColor": "#b2f2bb"
    },
    {
      "type": "arrow",
      "x": 0, "y": 0,
      "start": {"id": "svc-a"},
      "end": {"id": "svc-b"},
      "label": {"text": "HTTP"}
    }
  ]
}
Then run:
excalidraw batch diagram.json
Critical: Use
"start": {"id": "..."}
/
"end": {"id": "..."}
to bind arrows. Critical: Use
"label": {"text": "..."}
for shape text (not
"text": "..."
). For standalone text elements (
"type": "text"
), use
"text": "..."
directly.

创建文件
diagram.json
json
{
  "elements": [
    {
      "id": "svc-a",
      "type": "rectangle",
      "x": 100, "y": 100,
      "width": 160, "height": 60,
      "label": {"text": "Service A"},
      "strokeColor": "#1971c2",
      "backgroundColor": "#a5d8ff"
    },
    {
      "id": "svc-b",
      "type": "rectangle",
      "x": 100, "y": 240,
      "width": 160, "height": 60,
      "label": {"text": "Service B"},
      "strokeColor": "#2f9e44",
      "backgroundColor": "#b2f2bb"
    },
    {
      "type": "arrow",
      "x": 0, "y": 0,
      "start": {"id": "svc-a"},
      "end": {"id": "svc-b"},
      "label": {"text": "HTTP"}
    }
  ]
}
然后执行:
excalidraw batch diagram.json
关键注意事项:使用
"start": {"id": "..."}
/
"end": {"id": "..."}
来绑定箭头。 关键注意事项:为形状文本使用
"label": {"text": "..."}
(而非
"text": "..."
)。 对于独立文本元素(
"type": "text"
),直接使用
"text": "..."

Command Reference

命令参考

Server management

服务器管理

bash
excalidraw status                       # Health check
excalidraw serve --port 3000            # Start canvas server (blocks)
excalidraw serve --port 3000 --host 0.0.0.0  # Bind to all interfaces
bash
excalidraw status                       # 健康检查
excalidraw serve --port 3000            # 启动画布服务器(阻塞式)
excalidraw serve --port 3000 --host 0.0.0.0  # 绑定到所有网络接口

Element CRUD

元素增删改查(CRUD)

bash
excalidraw create --type rectangle --x 100 --y 100 --width 160 --height 60 --text "Box"
excalidraw create --type arrow --x 0 --y 0 --start <id> --end <id>
excalidraw create --type text --x 50 --y 50 --text "Title" --font-size 24

excalidraw update <id> --text "New Label" --stroke-color "#e03131"
excalidraw update <id> --x 200 --y 300 --width 200 --height 80

excalidraw delete <id>
excalidraw get <id>                     # Get single element
excalidraw query                        # Get all elements
excalidraw query --type rectangle       # Filter by type
bash
excalidraw create --type rectangle --x 100 --y 100 --width 160 --height 60 --text "Box"
excalidraw create --type arrow --x 0 --y 0 --start <id> --end <id>
excalidraw create --type text --x 50 --y 50 --text "Title" --font-size 24

excalidraw update <id> --text "New Label" --stroke-color "#e03131"
excalidraw update <id> --x 200 --y 300 --width 200 --height 80

excalidraw delete <id>
excalidraw get <id>                     # 获取单个元素
excalidraw query                        # 获取所有元素
excalidraw query --type rectangle       # 按类型过滤

Batch operations

批量操作

bash
excalidraw batch diagram.json           # From file
cat diagram.json | excalidraw batch     # From stdin
excalidraw clear                        # Remove all elements
bash
excalidraw batch diagram.json           # 从文件加载
cat diagram.json | excalidraw batch     # 从标准输入加载
excalidraw clear                        # 删除所有元素

Scene I/O

场景导入导出

bash
excalidraw export                       # Print .excalidraw JSON to stdout
excalidraw export --out scene.excalidraw  # Write to file
excalidraw import scene.excalidraw      # Import (replaces canvas)
excalidraw import scene.excalidraw --mode merge  # Merge with existing

excalidraw snapshot v1                  # Save named snapshot
excalidraw restore v1                   # Restore snapshot
bash
excalidraw export                       # 将.excalidraw JSON输出到标准输出
excalidraw export --out scene.excalidraw  # 写入到文件
excalidraw import scene.excalidraw      # 导入(替换当前画布)
excalidraw import scene.excalidraw --mode merge  # 与现有内容合并

excalidraw snapshot v1                  # 保存命名快照
excalidraw restore v1                   # 恢复快照

Viewport & visualization

视口与可视化

bash
excalidraw viewport --fit               # Zoom to fit all elements
excalidraw viewport --element <id>      # Center on element
excalidraw viewport --zoom 1.5          # Set zoom level

excalidraw describe                     # List all elements (text summary)
excalidraw screenshot                   # Capture canvas (requires browser)
excalidraw screenshot --format svg --out diagram.svg
bash
excalidraw viewport --fit               # 缩放至适配所有元素
excalidraw viewport --element <id>      # 居中显示指定元素
excalidraw viewport --zoom 1.5          # 设置缩放级别

excalidraw describe                     # 列出所有元素(文本摘要)
excalidraw screenshot                   # 捕获画布截图(需要浏览器)
excalidraw screenshot --format svg --out diagram.svg

Layout tools

布局工具

bash
excalidraw align id1 id2 id3 --alignment left   # Align left edges
excalidraw align id1 id2 id3 --alignment top    # Align top edges
excalidraw align id1 id2 id3 --alignment center # Center horizontally
excalidraw align id1 id2 id3 --alignment middle # Center vertically

excalidraw distribute id1 id2 id3 --direction horizontal
excalidraw distribute id1 id2 id3 --direction vertical

excalidraw group id1 id2 id3            # Group elements
excalidraw ungroup <groupId>            # Ungroup

excalidraw duplicate id1 id2 --dx 20 --dy 20
excalidraw lock id1 id2                 # Lock (prevent UI edits)
excalidraw unlock id1 id2
bash
excalidraw align id1 id2 id3 --alignment left   # 左对齐边缘
excalidraw align id1 id2 id3 --alignment top    # 顶部对齐
excalidraw align id1 id2 id3 --alignment center # 水平居中
excalidraw align id1 id2 id3 --alignment middle # 垂直居中

excalidraw distribute id1 id2 id3 --direction horizontal
excalidraw distribute id1 id2 id3 --direction vertical

excalidraw group id1 id2 id3            # 组合元素
excalidraw ungroup <groupId>            # 取消组合

excalidraw duplicate id1 id2 --dx 20 --dy 20
excalidraw lock id1 id2                 # 锁定(防止UI编辑)
excalidraw unlock id1 id2

Export & sharing

导出与分享

bash
excalidraw url                          # Export as encrypted excalidraw.com URL
excalidraw mermaid diagram.mmd          # Convert Mermaid to Excalidraw
echo "graph TD; A-->B" | excalidraw mermaid
bash
excalidraw url                          # 导出为加密的excalidraw.com链接
excalidraw mermaid diagram.mmd          # 将Mermaid转换为Excalidraw格式
echo "graph TD; A-->B" | excalidraw mermaid

Design guide

设计指南

bash
excalidraw guide                        # Print color palette, sizing, layout rules

bash
excalidraw guide                        # 打印调色板、尺寸、布局规则

Element Types Reference

元素类型参考

TypeRequiredNotes
rectanglex, y, width, heightUse
label: {text}
for labels
ellipsex, y, width, heightUse
label: {text}
for labels
diamondx, y, width, heightUse
label: {text}
for labels
textx, y, textStandalone text; use
text
not
label
arrowx, yBind with
start
/
end
; auto-routes edges
linex, y, pointsManual points array [[x,y],[x,y]]
freedrawx, y, pointsFreehand path

类型必填参数说明
rectanglex, y, width, height标签使用
label: {text}
ellipsex, y, width, height标签使用
label: {text}
diamondx, y, width, height标签使用
label: {text}
textx, y, text独立文本元素;使用
text
而非
label
arrowx, y使用
start
/
end
绑定;自动路由边缘
linex, y, points手动指定点数组 [[x,y],[x,y]]
freedrawx, y, points手绘路径

Common Patterns

常见模式

Architecture diagram

架构图

json
{
  "elements": [
    {"id":"zone","type":"rectangle","x":40,"y":40,"width":500,"height":400,
     "backgroundColor":"#e9ecef","strokeColor":"#868e96","opacity":50,
     "label":{"text":"Backend"}},
    {"id":"api","type":"rectangle","x":80,"y":100,"width":160,"height":60,
     "strokeColor":"#1971c2","backgroundColor":"#a5d8ff","label":{"text":"API Gateway"}},
    {"id":"db","type":"rectangle","x":80,"y":260,"width":160,"height":60,
     "strokeColor":"#0c8599","backgroundColor":"#99e9f2","label":{"text":"Database"}},
    {"type":"arrow","x":0,"y":0,"start":{"id":"api"},"end":{"id":"db"},
     "label":{"text":"SQL"}}
  ]
}
json
{
  "elements": [
    {"id":"zone","type":"rectangle","x":40,"y":40,"width":500,"height":400,
     "backgroundColor":"#e9ecef","strokeColor":"#868e96","opacity":50,
     "label":{"text":"Backend"}},
    {"id":"api","type":"rectangle","x":80,"y":100,"width":160,"height":60,
     "strokeColor":"#1971c2","backgroundColor":"#a5d8ff","label":{"text":"API Gateway"}},
    {"id":"db","type":"rectangle","x":80,"y":260,"width":160,"height":60,
     "strokeColor":"#0c8599","backgroundColor":"#99e9f2","label":{"text":"Database"}},
    {"type":"arrow","x":0,"y":0,"start":{"id":"api"},"end":{"id":"db"},
     "label":{"text":"SQL"}}
  ]
}

Flowchart

流程图

json
{
  "elements": [
    {"id":"start","type":"ellipse","x":160,"y":40,"width":120,"height":60,
     "strokeColor":"#2f9e44","backgroundColor":"#b2f2bb","label":{"text":"Start"}},
    {"id":"step1","type":"rectangle","x":140,"y":160,"width":160,"height":60,
     "strokeColor":"#1971c2","backgroundColor":"#a5d8ff","label":{"text":"Process Data"}},
    {"id":"decide","type":"diamond","x":140,"y":280,"width":160,"height":80,
     "strokeColor":"#e8590c","backgroundColor":"#ffd8a8","label":{"text":"Valid?"}},
    {"type":"arrow","x":0,"y":0,"start":{"id":"start"},"end":{"id":"step1"}},
    {"type":"arrow","x":0,"y":0,"start":{"id":"step1"},"end":{"id":"decide"}}
  ]
}

json
{
  "elements": [
    {"id":"start","type":"ellipse","x":160,"y":40,"width":120,"height":60,
     "strokeColor":"#2f9e44","backgroundColor":"#b2f2bb","label":{"text":"Start"}},
    {"id":"step1","type":"rectangle","x":140,"y":160,"width":160,"height":60,
     "strokeColor":"#1971c2","backgroundColor":"#a5d8ff","label":{"text":"Process Data"}},
    {"id":"decide","type":"diamond","x":140,"y":280,"width":160,"height":80,
     "strokeColor":"#e8590c","backgroundColor":"#ffd8a8","label":{"text":"Valid?"}},
    {"type":"arrow","x":0,"y":0,"start":{"id":"start"},"end":{"id":"step1"}},
    {"type":"arrow","x":0,"y":0,"start":{"id":"step1"},"end":{"id":"decide"}}
  ]
}

Iterative Refinement Loop

迭代优化循环

excalidraw batch diagram.json
  → excalidraw describe          (verify elements exist with correct IDs)
  → excalidraw viewport --fit    (auto-fit view)
  → excalidraw screenshot --out /tmp/check.png   (visual check)
  → [if issues] excalidraw update <id> --width 200 --height 80
  → excalidraw screenshot --out /tmp/check2.png  (re-verify)
  → [all good] done

excalidraw batch diagram.json
  → excalidraw describe          (验证元素是否存在且ID正确)
  → excalidraw viewport --fit    (自动适配视口)
  → excalidraw screenshot --out /tmp/check.png   (可视化检查)
  → [若有问题] excalidraw update <id> --width 200 --height 80
  → excalidraw screenshot --out /tmp/check2.png  (重新验证)
  → [无问题] 完成

Troubleshooting

故障排除

  • Server unreachable: Run
    excalidraw status
    . If error →
    excalidraw serve --port 3000
  • Screenshot fails: Open
    http://localhost:3000
    in a browser first
  • Arrow not connecting: Use
    "start": {"id": "..."}
    not coordinate points
  • Label not showing: Use
    "label": {"text": "..."}
    for shapes (not
    "text": "..."
    )
  • Elements lost after restart: Use
    excalidraw export --out backup.excalidraw
    before stopping
  • 服务器无法访问:执行
    excalidraw status
    。若报错 → 执行
    excalidraw serve --port 3000
  • 截图失败:先在浏览器中打开
    http://localhost:3000
  • 箭头未连接:使用
    "start": {"id": "..."}
    而非坐标点
  • 标签未显示:为形状使用
    "label": {"text": "..."}
    (而非
    "text": "..."
  • 重启后元素丢失:停止前执行
    excalidraw export --out backup.excalidraw
    进行备份