Install
openclaw skills install @darrenli6/boardrawTurn a natural-language description into a real Excalidraw whiteboard file (.excalidraw) — flowcharts, mind maps, architecture/system diagrams, org charts, wireframes, sticky-note brainstorms, sequence diagrams. Always use this skill whenever the user asks to draw, sketch, diagram, whiteboard, mind-map, or map something out, or mentions "excalidraw", "boardraw", "白板", "画一个", "流程图", "思维导图", "架构图", "组织架构图", "线框图", "泳道图", "看板", or wants a file they can open in Excalidraw or Boardraw. Do NOT hand-write raw .excalidraw JSON directly — the schema has fragile id/seed/binding requirements — always build it with the bundled scripts/excalidraw_builder.py helper instead.
openclaw skills install @darrenli6/boardraw这个技能让你把用户的一句话描述("帮我画个用户注册流程图"、"给这个项目搭个思维导图"、"画一下微服务架构")直接转成一个可以在 Excalidraw 或 Boardraw 里打开、且元素仍然可编辑、可拖动、可连线的 .excalidraw 文件——而不是一张静态图片。
Language policy: Always respond in English by default. If the user writes in any other language (e.g. Chinese, Japanese, Spanish), mirror that language for all replies in that conversation.
Core rule: Never hand-write raw .excalidraw JSON. The format has strict id/seed/versionNonce/boundElements two-way binding requirements — hand-writing it almost always breaks things (text detaches from shapes, arrows don't snap to nodes). Always use the ExcalidrawDoc class in scripts/excalidraw_builder.py to build elements.
先在心里(或简单笔记里)把用户想要的东西拆成:
如果用户的描述比较模糊(比如"帮我画个流程图"没给具体步骤),直接用一个合理的示例流程走完整个骨架,并在回复里简单说明你是怎么理解的。
把设计作为文字大纲呈现给用户:
📋 图表预览
标题:用户注册流程
[开始] → [填写表单] → [验证邮箱] → {邮箱有效?}
├── 是 → [创建账户] → [发送欢迎邮件] → [结束]
└── 否 → [显示错误] → [填写表单]
配色:开始/结束 = 绿色,判断 = 黄色,步骤 = 蓝色
然后询问:"这个是你想要的吗?确认后我来生成并上传到 boardraw.com。"
等用户确认后再继续。
scripts/excalidraw_builder.py 里带了几个坐标计算的小工具,不用自己心算坐标:
vertical_flow_positions(count, ...) — 自上而下的直线流程图horizontal_flow_positions(count, ...) — 从左到右的直线流程图grid_positions(count, cols, ...) — 网格布局(看板、便签墙、并列卡片)复杂布局(思维导图的放射状分支、树状组织架构图、有分叉/合并的流程图)直接手动算坐标即可——核心是保证同一层级/同一分支的节点间距一致(横向流程图节点间距一般 150–250px,纵向 250–350px 的行高,太挤会导致文字溢出到相邻节点上)。
ExcalidrawDoc 搭建元素import sys
sys.path.insert(0, "scripts") # 视实际技能挂载路径调整
from excalidraw_builder import ExcalidrawDoc, vertical_flow_positions
doc = ExcalidrawDoc()
positions = vertical_flow_positions(4, x0=300, y0=40, w=200, h=80, gap=80)
labels = ["用户提交需求", "判断是否合规", "生成方案", "交付客户"]
nodes = []
for (x, y), text in zip(positions, labels):
shape = doc.diamond(x - 20, y, 240, 100, bg="orange") if "判断" in text \
else doc.rectangle(x, y, 200, 80, bg="blue")
doc.label(shape, text) # 文字必须用 label() 绑定进形状,不要单独摆 text 叠在上面
nodes.append(shape)
for a, b in zip(nodes, nodes[1:]):
doc.arrow(a, b) # 相邻节点直接用 arrow()
doc.arrow(nodes[1], nodes[0], label="不合规,退回", stroke="red")
doc.save("/tmp/用户需求处理流程.excalidraw")
用 Bash 把脚本写成 .py 文件执行,不要在对话里手写 JSON。
arrow() 只画两个元素中心点之间的直线。这在两个节点严格上下相邻、中间没有其它节点时没问题;但只要出现下面任一情况,直线就会斜着穿过别的节点,图会变得很乱:
这两种情况都要用 doc.elbow_arrow()(直角走线)代替 doc.arrow():
# 情况一:3 个测试项汇入 1 个判断节点,走"下 -> 中间横切 -> 下",不要直线斜交叉
bend_y = (test_nodes[-1]["y"] + test_nodes[-1]["height"] + decision["y"]) / 2
for node in [functest, perftest, sectest]:
doc.elbow_arrow(node, decision, exit="bottom", enter="top", bend=bend_y)
# 情况二:回退箭头要跳过中间好几个节点——走"侧道"绕开,而不是斜线穿过去
lane_x = doc.right_lane_x(margin=160)
doc.elbow_arrow(rollback_node, deploy_node, exit="right", enter="right",
bend=lane_x, stroke="red", label="重新部署")
exit/enter 要用同一个轴向配对(top/bottom 配 top/bottom,left/right 配 left/right),这样自动算出的拐点路径才会"绕开"而不是"横切"中间的东西。拿不准的复杂路径,直接用 waypoints=[[x1,y1],[x2,y2],...] 手动指定完整绕行路径。
什么时候用 arrow():只有两个节点严格同列(纵向流程图里紧挨着的上一步/下一步)或严格同行、且中间没有第三个节点卡在直线路径上时。其它一律 elbow_arrow()。
find_crossings(),不能直接交付crossings = doc.find_crossings()
if crossings:
print(crossings) # [(箭头id, 被穿过的节点id, 节点类型), ...]
# 说明有线穿过了不该穿的节点:把对应连线换成 elbow_arrow()/调整 bend 或 waypoints,
# 或者加大节点间距,重新生成,直到这里返回空列表再保存交付
这是强制步骤,不是可选优化——不要在 find_crossings() 还有报错的情况下就把文件保存交付给用户。
1. 保存到本地(文件名可以用中文,UTF-8 no BOM)。
2. 校验 JSON 格式:
python3 -c "import json; json.load(open('output.excalidraw')); print('OK')"
3. 上传 — 从环境变量 BOARDRAW_API_KEY 或目录树向上查找 .env 文件读取 API Key:
python scripts/upload.py output.excalidraw
或者用 curl:
curl -s -X POST "https://www.boardraw.com/api/keys/auth" \
-H "Content-Type: application/json" \
-H "x-api-key: $BOARDRAW_API_KEY" \
-d "{\"whiteboard\": $(cat output.excalidraw)}"
API 响应处理:
| 状态码 | 处理方式 |
|---|---|
| 201 | 提取 file.uuid → 展示 https://www.boardraw.com/workspace/{uuid} |
| 401(缺少 key) | 提示用户设置 BOARDRAW_API_KEY |
| 401(key 无效/已撤销) | 提示用户在 boardraw.com 设置页检查 key |
| 403 | 提示用户升级到 Pro 或 Team 计划 |
| 400 | 白板 JSON 格式有误,重新运行 builder 脚本 |
4. 回复格式——不需要列举每个节点,一行说明即可:
✅ 图表已上传到 boardraw.com!
🔗 在线查看/编辑:https://www.boardraw.com/workspace/{uuid}
📁 文件名:{fileName}
👤 账户:{user.name} ({user.email})
文件也可以直接在 Excalidraw 或任何兼容工具里打开。
label()/text() 默认用 font_family=2(Helvetica/无衬线体)。不要改成 font_family=1(Excalifont 手绘体)去写中文/日文/韩文——那个字体没有 CJK 字形,中文渲染出来会变形、缺笔画甚至乱码。font_family=1 只适合简短英文标题想要手绘风格的场景;中日韩文字一律留默认的 2。font_family=3(等宽代码字体)可以用在代码片段/接口名标签上。
doc.diamond),从判断菱形出去的每条分支箭头都用 label= 写上"是/否"之类的条件arrow()elbow_arrow(),见第 4 步doc.ellipse(x, y, 220, 100, bg="violet")angle = i * 360/8),用 doc.line() 或不带箭头的 doc.arrow(start_arrowhead=None, end_arrowhead=None) 连到中心stroke= 区分(red/green/blue/orange/violet)doc.frame(x, y, w, h, name="前端") 把同一层的服务框起来,再用 doc.put_in_frame(el, frame_el) 把里面的矩形放进这个 framelabel= 标注协议或调用方式(比如 "HTTPS"、"gRPC");跨层级、不相邻的调用关系用 elbow_arrow() 走线,避免线穿中间层的框grid_positions 或手动坐标摆节点,每一层用 y 递增arrow() 即可;上级同时连多个平级下属,一律 elbow_arrow(exit="bottom", enter="top") 走"下-横-下",不要用直线放射状连接(节点一多马上变成"X 交叉")end_arrowhead="triangle" 更接近组织图的连接线观感,不需要箭头可以两端都设 Nonegrid_positions(count, cols=3) 排列彩色便签矩形,bg= 换不同颜色区分类别/优先级/负责人要使用此技能,请配置你的 boardraw.com API Key:
1. 登录 boardraw.com → 设置 → API Keys
2. 创建新的 API Key(需要 Pro 或 Team 计划)
3. 添加到项目根目录的 .env 文件:
BOARDRAW_API_KEY=br_your_api_key_here
或者设置环境变量:
export BOARDRAW_API_KEY=br_your_api_key_here
references/excalidraw-schema.md — 完整的原始 JSON 字段说明(元素通用字段、text/arrow/line 专有字段、颜色调色板、frame 规则)。只有当 excalidraw_builder.py 提供的方法覆盖不了用户的定制需求(比如自由手绘 freedraw、图片元素、特殊圆角、非默认字体大小)时才需要查阅,直接调 builder 的方法通常已经够用。