Excalidraw 技能
步驟 0:選擇介面
三種介面驅動同一個即時畫布,請選取適用的第一種:
- MCP 工具 — 如果
excalidraw/*工具(例如batch_create_elements)在您的工具清單中,優先使用它們:結果會直接傳到您的上下文,螢幕截圖則以圖片形式返回,無需存取磁碟。 - CLI(當沒有 MCP 工具時的預設值):
無需設定 — 任何觸碰畫布的命令會自動啟動畫布伺服器在npx -y mcp-excalidraw-server <command>http://127.0.0.1:3000(首次執行npx時會下載套件)。如果 CLI 已全域安裝(npm i -g mcp-excalidraw-server),則較短的別名excalidraw-canvas <command>也可使用。 - REST API(最後的手段,例如從應用程式碼呼叫):HTTP 端點位於
http://127.0.0.1:3000— 請參閱references/cheatsheet.md取得請求內容。伺服器必須已在執行中。
畫布 URL 來自 EXPRESS_SERVER_URL(預設為 http://127.0.0.1:3000)。提醒使用者在瀏覽器中開啟該 URL — 螢幕截圖、圖片匯出、mermaid 轉換和視埠控制都需要開啟的分頁(缺少時 CLI 會以代碼 4 退出)。
CLI 快速參考
結果以 JSON 格式輸出到 stdout — 除了 describe(純文字)以及在省略 --out 時的原始內容輸出(export 場景 JSON,screenshot --format svg 輸出原始 SVG)。診斷資訊則輸出到 stderr。結束代碼:0 成功,1 錯誤,2 使用方式錯誤,3 無法連線畫布,4 需要瀏覽器分頁。
| 任務 | 命令 |
|---|---|
| 啟動 / 停止 / 檢查伺服器 | start, stop, status |
| 建立元素(批次) | add elements.json 或 echo '[...]' | add 或 add --one '{...}' |
| 在單一呼叫中執行多操作修補 | apply patch.json — {"create":[...],"update":[{"id":"a","set":{...}}],"delete":[...]} |
| 讀取單一元素 / 查詢多個元素 | get <id>, query [--type t] [--bbox x0,y0,x1,y1] [--filter k=v] [--filter-json '{...}'] |
| 更新 / 刪除 | update <id> --set '{...}', delete <id> [...] |
| 理解場景 | describe(純文字摘要:ID、位置、標籤、連線) |
| 查看場景 | screenshot [--out f.png](若無 --out,PNG 會以 JSON 回傳暫存檔案路徑;若無 --out,SVG 會回傳原始 SVG) |
| 佈局操作 | `arrange align |
| 場景檔案 | export [--out scene.excalidraw], `import [scene.excalidraw |
| Mermaid → 畫布 | `mermaid [diagram.mmd |
| 快照 | `snapshot save |
| 分享連結 | share(加密上傳 → excalidraw.com URL) |
| 清除畫布 | clear --yes |
| 安裝 / 升級此技能 | install-skill --dir <skills-root>(代理選擇專案/全域根目錄) |
元素格式(CLI 和 MCP)
CLI 和 MCP 工具接受相同的代理友好格式,並會自動將其正規化:
- 標籤:在任何形狀上放置
"text": "My Label"— 會自動轉換為 Excalidraw 的綁定標籤格式。 - 箭頭綁定:
"startElementId": "a"/"endElementId": "b"— 箭頭會自動連接到元素邊緣。 - fontFamily:傳入字串名稱(
"helvetica","cascadia","excalifont", ...)或字串數字"1"–"8"。 - points:接受
[[x,y], ...]元組和[{"x":..,"y":..}]物件。 - 修補更新:在
apply中,更新項目可以直接使用欄位({"id":"a","x":120})或set物件({"id":"a","set":{"x":120}})。不要在一個更新項目中混用這兩種形式。
原始 REST 更嚴格:標籤必須使用 "label": {"text": "..."},綁定必須使用 "start": {"id": "..."} / "end": {"id": "..."}。只有在直接 POST 到 API 時才需要擔心這個。
座標系統
畫布使用二維座標網格:(0, 0) 是原點,x 軸向右增加,y 軸向下增加。在撰寫任何 JSON 之前請先規劃好您的佈局。
一般間距指南:
- 層級之間的垂直間距:80–120px(足夠讓箭頭不與標籤重疊)
- 兄弟元素之間的水平間距:最少 40–60px;給有標籤的箭頭留 120px+ 的空間
- 形狀寬度:
max(160, labelCharCount * 12)以保持標籤在一行內 - 單行標籤的形狀高度:60px,雙行標籤:80px
- 背景/區域內邊距:圍繞內部元素四周 50px
專業外觀的樣式設定:
- 形狀使用
"fillStyle": "solid"可獲得清晰的扁平填滿 — 預設為草繪的陰影線圖案 - 將柔和色調的
backgroundColor填滿與其較暗的strokeColor配對(色板在小抄中) - 在區域邊界和非同步箭頭上使用
"strokeStyle": "dashed"表示「邊界 / 背景」
佈局反模式(對複雜圖表至關重要)
這些是最常見的錯誤,會導致圖表難以閱讀。請避免所有這些錯誤。
1. 不要在大型背景區域矩形上使用 label.text(或 text)
當您在背景矩形上放置標籤時,Excalidraw 會建立一個綁定文字元素,並將其置中於該形狀的正中央 — 而這正是您要放置服務方塊的位置。文字會與區域內的所有內容重疊,且無法重新定位。
錯誤:
{"id": "vpc-zone", "type": "rectangle", "x": 50, "y": 50, "width": 800, "height": 400, "text": "VPC (10.0.0.0/16)"}
正確 — 使用一個固定在區域頂部的獨立文字元素:
{"id": "vpc-zone", "type": "rectangle", "x": 50, "y": 50, "width": 800, "height": 400, "backgroundColor": "#e3f2fd"},
{"id": "vpc-label", "type": "text", "x": 70, "y": 60, "width": 300, "height": 30, "text": "VPC (10.0.0.0/16)", "fontSize": 18}
獨立的文字元素位於區域的頂角,不會干擾放置在內部的元素。
2. 在複雜圖表中避免跨區域箭頭
從一個佈局區域中的元素指向另一個遠端區域中元素的箭頭,會畫出一條長對角線,穿過之間的所有東西。在多區域基礎設施圖表中,這會產生一團無法閱讀的麵條亂線。
設計規則: 將箭頭保持在同一個區域或層級內。若要顯示跨區域關係,請使用註解文字,或將區域分開,使它們的邊緣相鄰(之間沒有任何元素),並沿著邊緣繪製箭頭。
如果必須跨區域連接,請使用沿周邊行走的肘形箭頭 — 切勿穿過另一個區域的中間。
3. 節制使用箭頭標籤
箭頭標籤放置在箭頭的中點。在短箭頭上,它們會與兩端的形狀重疊。在擁擠的圖表中,它們會與附近的元素碰撞。
- 只有在關係名稱確實有必要時(例如,協定、連接埠號碼、資料方向)才添加箭頭標籤。
- 如果您要為每個箭頭都添加標籤,請重新考慮 — 這通常會增加視覺噪音,而不是清晰度。
- 將箭頭標籤保持在 ≤ 12 個字元。在密集的圖表中,最好完全省略它們。
品質:為何重要(以及如何檢查)
Excalidraw 圖表是一種視覺溝通。如果文字被截斷、元素重疊或箭頭穿過不相關的形狀,圖表就會變得混亂且不專業 — 這完全違背了繪製它的目的。因此,在每一批元素之後,先驗證再添加更多元素。
品質檢查清單
每次 add / apply / batch_create_elements 之後,拍攝螢幕截圖並檢查:
- 文字截斷 — 所有標籤文字是否完全可見?文字被截斷表示形狀太小。增加
width和/或height。 - 重疊 — 是否有任何形狀佔用相同的空間?背景區域必須完全包含其子元素並留有內邊距。
- 箭頭交叉 — 箭頭是否切穿不相關的元素?如果是,請使用曲線或肘形箭頭繞過它們(請參閱下方的箭頭路線規劃)。
- 箭頭標籤重疊 — 箭頭標籤位於中點。如果它們與形狀重疊,請縮短標籤或調整箭頭路徑。
- 間距 — 元素之間至少要有 40px 的間隙。擁擠的佈局很難閱讀。
- 可讀性 — 正文文字的字型大小 ≥ 16,標題 ≥ 20。
- 區域標籤放置 — 如果您在背景區域矩形上使用了
text/label.text,則區域標籤會置中在區域中間,與內部的所有內容重疊。修正:刪除綁定文字元素,並在區域頂部添加一個獨立的文字元素(請參閱上方的佈局反模式)。
如果您發現任何問題:停止、修正、重新截圖、然後繼續。 說「我看到 [問題],正在修正」,而不是輕描淡寫地帶過。只有在所有檢查都通過後才能繼續。
工作流程:繪製新圖表
Mermaid vs. 直接建立 — 該用哪個?
當以下情況時使用 mermaid / create_from_mermaid:使用者已經有一個 Mermaid 圖表,或者結構可以清楚地映射到流程圖、序列圖或 ER 圖,並使用標準的 Mermaid 語法。它速度很快,可以自動處理轉換,但你對確切佈局的控制較少。
當以下情況時直接建立元素:你需要精確的佈局控制,圖表類型不容易映射到 Mermaid(例如自訂架構、帶註解的雲端圖表),或者你想將元素放置在特定的座標網格中。
步驟(以 CLI 顯示;MCP 工具是 1:1 對應的 — 請參閱小抄)
- 規劃您的座標網格 — 在撰寫 JSON 之前先規劃好層級和 x 位置。(MCP 模式:呼叫
read_diagram_guide取得顏色/大小設定;相同的指南位於references/cheatsheet.md。) - 可選的重新開始:
npx -y mcp-excalidraw-server clear --yes - 在一個呼叫中建立形狀和箭頭。自訂的
id欄位(例如"id": "auth-svc")讓後續更新更容易:(npx -y mcp-excalidraw-server add - <<'EOF' [ {"id": "lb", "type": "rectangle", "x": 300, "y": 50, "width": 180, "height": 60, "text": "Load Balancer"}, {"id": "svc-a", "type": "rectangle", "x": 100, "y": 200, "width": 160, "height": 60, "text": "Web Server 1"}, {"id": "svc-b", "type": "rectangle", "x": 450, "y": 200, "width": 160, "height": 60, "text": "Web Server 2"}, {"id": "db", "type": "rectangle", "x": 275, "y": 350, "width": 210, "height": 60, "text": "PostgreSQL"}, {"type": "arrow", "x": 0, "y": 0, "startElementId": "lb", "endElementId": "svc-a"}, {"type": "arrow", "x": 0, "y": 0, "startElementId": "lb", "endElementId": "svc-b"}, {"type": "arrow", "x": 0, "y": 0, "startElementId": "svc-a", "endElementId": "db"}, {"type": "arrow", "x": 0, "y": 0, "startElementId": "svc-b", "endElementId": "db"} ] EOF-位置參數是可選的 — 如果沒有檔案參數,add會從 stdin 讀取。) - 使用
max(160, labelLength * 12)設定形狀寬度。 screenshot→ 檢視檔案 → 執行品質檢查清單 → 在下一批之前修正問題。
箭頭路線規劃 — 避免重疊
在複雜圖表中,直線箭頭可能會穿過元素。必要時使用曲線或肘形箭頭:
曲線箭頭(平滑弧線越過障礙物):
{
"type": "arrow", "x": 100, "y": 100,
"points": [[0, 0], [50, -40], [200, 0]],
"roundness": {"type": 2}
}
中間路徑點 [50, -40] 將箭頭向上抬起。roundness: {type: 2} 使其平滑。
肘形箭頭(直角 / L 形路線規劃):
{
"type": "arrow", "x": 100, "y": 100,
"points": [[0, 0], [0, -50], [200, -50], [200, 0]],
"elbowed": true
}
何時使用哪種:
- 扇出(一個來源 → 多個目標):使用帶路徑點的曲線箭頭分散開來,避免重疊
- 跨越通道(連接到側面板):使用先向上、再橫向、最後向下的肘形箭頭
- 長水平連線:使用帶有輕微垂直偏移的曲線箭頭
規則: 如果箭頭會穿過不相關的形狀,請添加一個路徑點以繞過它。
工作流程:迭代調整
將 describe 與 screenshot 配對使用,才能發揮此技能的最大功效。
describe(MCP 中的describe_scene)→ 結構化文字:元素 ID、類型、位置、標籤、連線。用它來了解畫布上的內容,然後再進行程式化更新(尋找 ID、理解邊界框)。screenshot(MCP 中的get_canvas_screenshot)→ 實際渲染畫布的 PNG。用它進行視覺品質驗證 — 它會準確顯示使用者看到的內容,包括截斷、重疊和箭頭路線規劃。CLI 會將儲存的檔案路徑以 JSON 格式輸出;請讀取/檢視該檔案。
反饋循環:
add elements
→ screenshot → view → "auth-svc 上的文字被截斷"
→ update auth-svc --set '{"width": 220}' → screenshot → "auth-svc 與 rate-limiter 重疊"
→ update rate-limiter --set '{"x": 520}' → screenshot → "所有檢查通過"
→ proceed
工作流程:調整現有圖表
describe以了解目前狀態 — 記下元素 ID 和位置。- 透過
id或標籤文字(而不是 x/y 座標 — 它們會變動)識別元素。 update <id> --set '{...}'以調整大小/重新著色/移動;delete <id>以移除;或者將所有內容打包在一個apply修補中。當您移動或調整端點大小時,綁定的箭頭會自動重新規劃路線 — 無需刪除並重新建立它們。screenshot以確認變更正確。- 如果更新失敗:使用
get <id>檢查 ID 是否存在;如果被鎖定,使用arrange unlock --ids <id>解鎖。
工作流程:Mermaid 轉換
echo 'graph TD
A[Client] --> B[API]
B --> C[(DB)]' | npx -y mcp-excalidraw-server mermaid
需要一個開啟的瀏覽器分頁(轉換在前端執行;結束代碼 4 會提示您開啟畫布 URL)。之後 screenshot 以驗證佈局。如果自動佈局不佳(節點擁擠、邊緣交叉),使用 describe 找出問題元素,並使用 update 重新定位它們。
工作流程:檔案 I/O
- 匯出場景:
export --out diagram.excalidraw(無--out→ JSON 輸出到 stdout) - 匯入場景:
import diagram.excalidraw(附加)或import diagram.excalidraw --replace - 圖片:
screenshot --out diagram.png/screenshot --format svg --out diagram.svg(需要瀏覽器分頁) - 分享連結:
share— 加密場景並回傳一個可分享的 excal
…
[翻譯時已截斷]