LifeOS Tldraw 技能深度解析:确定性读写 .tldr 画布文件
2026/9/16 12:08:03 网站建设 项目流程

LifeOS Tldraw 技能深度解析:确定性读写 .tldr 画布文件

【免费下载链接】LifeOS⛰️ The Life Operating System — an intent engineering platform that moves you from your current state to your ideal state, in life and work.项目地址: https://gitcode.com/GitHub_Trending/pe/LifeOS

导读

本文讲解 LifeOS 中 Tldraw 技能(LifeOS/install/skills/Tldraw/SKILL.md)的核心能力:以确定性(deterministic)方式读写 tldraw 的.tldr画布文件,让 AI Agent 既能“画”——按手绘风格把流程图、笔记、框架图直接写入用户可在任意 tldraw 界面打开的画布文件,也能“读”——把人类随手画的杂乱画布解析为结构化数据并整理成有聚类、有框架、有连线的版本。读完本文,你将掌握.tldr的 JSON 文件格式、Tldr.ts的七个子命令、两个标准工作流(SketchDiagram / StructureCanvas)以及全部已知坑位,可直接在 LifeOS 环境中复现同样的读写流程。

技能定位:模型 ↔ 画布的双向通道

Tldraw 技能是 LifeOS 中面向白板/画布场景的专项技能。根据 SKILL.md 的 frontmatter 描述,它适用的典型触发词包括:tldraw.tldr filewhiteboardcanvassketch a diagramhand-drawn diagramdraw this on a canvasstructure my canvasorganize my whiteboardread my canvascluster my sticky notes等;同时明确声明不适用于精美静态图、信息图或 mermaid 图(应使用 Art 技能)、Web UI 设计(Webdesign 技能)、程序化视频(Remotion 技能)。

技能的核心主张是:.tldr格式本质上是纯 JSON({tldrawFileFormatVersion: 1, schema, records}),而 Tools/Tldr.ts 写出的记录能通过 tldraw 自身的校验器(validator),因此生成的文件可以在 tldraw 网页编辑器、VS Code tldraw 扩展、桌面应用中干净打开。它提供两个方向的能力:

  • 模型 → 画布(SketchDiagram):把结构化描述翻译为手绘风格图形;
  • 画布 → 模型(StructureCanvas):读取人类粗糙的思维草稿,整理成结构化画布。

理解 .tldr 文件格式

要安全地读写.tldr,必须先理解其格式。详细规范见 References/TldrFormat.md,其中所有结论都声明是对照 tldraw@5.2.5 验证过的:按此方式构造的记录可以通过parseTldrawJsonFile(tldraw 自身的加载路径)。

文件容器

{ "tldrawFileFormatVersion": 1, "schema": { "schemaVersion": 2, "sequences": { "...": 0 } }, "records": [ ... ] }
  • schema驱动加载时的迁移逻辑。本技能在 References/SchemaSnapshot.json 中内置了一份取自 tldraw 5.2.5 的序列化快照(schemaVersion: 2,含com.tldraw.storecom.tldraw.shape.geocom.tldraw.shape.arrowcom.tldraw.binding.arrow等全部类型序列号)。更旧的 tldraw 界面会拒绝更新 schema 的文件,而更新的界面会自动迁移旧文件。
  • 最小可行记录:一条document:document+ 一条page:pageinstance/camera记录由编辑器在加载时自行合成,不要写入文件

每条形状的 record 信封

{ "id": "shape:<name>", "typeName": "shape", "type": "geo|text|note|frame|arrow", "parentId": "page:page", "x": 0, "y": 0, "rotation": 0, "index": "a1", "isLocked": false, "opacity": 1, "meta": {}, "props": { ... } }
  • index是分数索引字符串(base62,字符集0-9A-Za-z,按字典序决定 z-order),绝不能以0结尾
  • 直接写入文件的原始记录不会经过编辑器默认值填充,因此下面列出的每个 prop 都是必填的。

各类型必填 props(tldraw 5.2.5getDefaultProps()值)

类型Props
geogeo, w, h, color, labelColor, fill, dash, size, font, align, verticalAlign, growY, url, scale, richText
textcolor, size, w, font, textAlign, autoSize, scale, richText
notecolor, richText, size, font, align, verticalAlign, labelColor, growY, fontSizeAdjustment, url, scale, textLastEditedBy
framew, h, name, color
arrowkind ("arc"), elbowMidPoint, dash, size, fill, color, labelColor, bend, start {x,y}, end {x,y}, arrowheadStart, arrowheadEnd, richText, labelPosition, font, scale

箭头绑定记录(每个被绑定的端点一条):

{ "id": "binding:<name>", "typeName": "binding", "type": "arrow", "fromId": "shape:<arrow>", "toId": "shape:<target>", "props": { "isPrecise": false, "isExact": false, "terminal": "start", "normalizedAnchor": { "x": 0.5, "y": 0.5 }, "snap": "none" }, "meta": {} }

注意:terminal"start""end")是校验器强制要求的,尽管ArrowBindingUtil.getDefaultProps()会省略它——这是最容易手写出错的字段之一。

richText:文本不是字符串

tldraw 中所有标签文本都是 ProseMirror 文档 JSON,而不是普通字符串。每个段落一个paragraph节点,空段落省略content

{ "type": "doc", "content": [ { "type": "paragraph", "content": [ { "type": "text", "text": "line 1" } ] } ] }

裸字符串的textprop 会被 tldraw 校验器拒绝。Tldr.ts会替你构造 richText,永远不要手写textprop。

枚举值速查

  • color / labelColor:black, grey, light-violet, violet, blue, light-blue, yellow, orange, green, light-green, light-red, red, white
  • fill:none, semi, solid, pattern, fill
  • dash:draw, solid, dashed, dotted
  • size:s, m, l, xl
  • font:draw(手绘风), sans, serif, mono
  • geo:rectangle, ellipse, triangle, diamond, pentagon, hexagon, octagon, star, rhombus, oval, trapezoid, arrow-right, arrow-left, arrow-up, arrow-down, x-box, check-box, heart, cloud
  • arrowheadStart / arrowheadEnd:none, arrow, triangle, square, dot, pipe, diamond, inverted, bar

以上枚举同时被 Tldr.ts 中的COLORSGEOS集合硬编码约束,非法值会被工具直接拒绝(invalid color/invalid geo错误)。

坐标系

页面空间(page space),y 轴向下,原点任意;x,y表示形状的左上角。绑定了起止形状的箭头会由编辑器根据绑定形状重算路径,所以它们start/end点只在首次渲染前有意义。

Tldr.ts:确定性读写的 CLI 工具

Tldr.ts是纯 Bun 脚本、零外部依赖,核心注释声明其写出的记录“对照 tldraw@5.2.5 的parseTldrawJsonFile验证”,内嵌的 schema 快照保证生成的文件可被该版本及以上的任意 tldraw 界面加载。命令入口在 Tools/Tldr.ts,安装后位于~/.claude/skills/Tldraw/Tools/Tldr.ts(仓库路径为LifeOS/install/skills/Tldraw/Tools/Tldr.ts)。

完整命令签名(见文件头部 Usage 注释与 SKILL.md 的 Quick Reference):

bun Tldr.ts create <file> [--title "Heading text"] bun Tldr.ts inspect <file> [--json] bun Tldr.ts add <file> --spec <spec.json | -> bun Tldr.ts remove <file> --ids id1,id2 bun Tldr.ts move <file> --id <shapeId> --x N --y N bun Tldr.ts settext <file> --id <shapeId> --text "New label" bun Tldr.ts validate <file>

create:建文件

写入两条最小记录(document:documentpage:page,其中 page 的index"a1")。若提供--title,还会追加一个shape:title的 text 形状(坐标为(0, -80),字号xl,宽度 700),用作画布标题。输出形如created <file> (3 records)

add:按 spec 数组批量添加

--spec接受一个 JSON数组,每个条目定义一种形状,支持六种kind

kindRequiredOptional
boxtext 或 name; x, yw, h, color, fill, geo, dash, size, font, url, name
ellipse同 box(geo 强制为 ellipse)
texttext; x, ysize, font, color, w(设置 w 会禁用 autoSize), textAlign, name
notetext; x, ycolor(默认 yellow), size, font, name
frametitle; x, y, w, hcolor, name
arrowfrom, to(指向已存在形状的 name 或 id)text, color, bend, dash, size, arrowheadStart, arrowheadEnd, name

name会成为形状 id(shape:<name>);省略时从文本自动派生(slug函数:小写化、非字母数字替换为-、截断 40 字符、空则回退"shape")。箭头必须排在它连接的形状之后(同一 spec 数组里靠后即可)。从 Tldr.ts 的expandSpec可看到各 kind 的默认值细节:

  • box:默认220×120fill: "none"dash: "draw"size: "m"font: "draw"、对齐middlegrowY: 0url: ""scale: 1
  • ellipse:同一套默认值,但geo被强制为ellipse
  • text:默认宽 400、textAlign: "start",且只有未指定wautoSize才为true
  • note:默认颜色yellow(与 tldraw 便签的视觉惯例一致)、fontSizeAdjustment: 1textLastEditedBy: null
  • frame:默认640×360nametitle
  • arrowkind: "arc"elbowMidPoint: 0.5bend: 0arrowheadStart: "none"arrowheadEnd: "arrow"labelPosition: 0.5,并自动生成两条 binding 记录(terminal: "start"/"end"),normalizedAnchor{x: 0.5, y: 0.5}snap: "none";箭头的起止点取自两个形状的中心(centerOf)。

分数索引由nextIndex生成:若当前最大索引末位不是最后一个 base62 字符则末位 +1,否则追加"1",保证字典序单调且不以0结尾。uniqueId在 id 冲突时自动追加-2-3后缀。

inspect:读回画布

inspect --json输出结构化数据:页面列表、每个形状的id/type/x/y/w/h/color/文本(frame 额外给出标题)、以及由 binding 推导的边列表(每条箭头记录from → to与标签文本)。非 JSON 模式输出人类可读的摘要(2 page(s), 5 shape(s)及各形状的定位、尺寸、文本)。文本通过plainText从 richText 递归提取(text 节点拼字符串、paragraph 追加换行、trimEnd去尾)。

remove / move / settext / validate

  • remove--ids以逗号分隔。实现了一个级联删除(注释标明移植自 tldraw 公共 PR #1739,@elhoim):反复迭代到不动点,凡是 binding 引用了被删形状(toIdfromId),则删除该 binding 以及它所属的箭头——因为删掉箭头会孤立其另一条 binding,单趟遍历会漏掉。输出removed N record(s)
  • move--id指定形状,--x/--y缺省时保持原值,用于重排画布。
  • settext:对 frame 修改props.name,对带richText的形状重写 richText;无文本的形状会报错。
  • validate:内置一致性门禁——检查document/page记录存在、每条记录有id/typeName、形状的parentId有效、binding 必须有terminal且两端不悬空(fromId/toId都在文件内)、颜色必须在枚举内;任一失败即输出INVALID:错误列表并以退出码 1 结束,通过则输出valid: <file> (N records)

实战一:SketchDiagram 工作流(画出手绘风格图表)

工作流定义在 Workflows/SketchDiagram.md,用于“把用户口头描述的流程/结构画成手绘风画布”。其目标是:生成的文件通过Tldr.ts validate,用户点名的每个概念都是一个形状、每条关系都是一条箭头,无多余元素;布局按流程顺序从左到右或从上到下,形状不重叠,相关内容用邻近或 frame 分组。

Step 0 — 充分性检查

动笔前先确认三件事:图表要传达什么、大约多少个元素、文件落在哪里(默认按用户偏好进入Canvases/目录,否则放当前项目)。如果存在解释分叉会改变图表结构,用一行标注(⚠️ Picking X over Y because R; redirect if wrong.)并继续采用最佳默认值。

工具契约

T=~/.claude/skills/Tldraw/Tools/Tldr.ts bun $T create <file.tldr> [--title "Heading"] bun $T add <file.tldr> --spec <spec.json> # spec: JSON array, kinds: box, ellipse, text, note, frame, arrow bun $T validate <file.tldr> bun $T inspect <file.tldr> # confirm what actually landed

布局约束(经验约定)

  • 盒子默认 220×120,水平间隙 ≥140 px、垂直间隙 ≥100 px,给绑定箭头留足空间;
  • 箭头按name引用形状并自动绑定——先加盒子(或同一 spec 数组内盒子在前);
  • 颜色即语义:从枚举中最多挑 2–4 种颜色,fill: "solid"只用于想突出的形状;
  • 一个 frame 分组并命名一个区域,一个聚类一个 frame,优于散落的浮动标签。

验证门(gate)

validate通过 +inspect输出与预期的形状/边列表一致,才能闭环。技能明确要求诚实表达:你无法看到渲染后的像素,所以应报告“结构上已验证;请打开画布目测布局”,而不能说“看起来不错”

一个完整的示例(SKILL.md Examples):

User: "Sketch the three-stage pipeline as a hand-drawn diagram" → Invokes SketchDiagram workflow → Writes spec JSON, runs Tldr.ts create + add, validates → Returns the .tldr path and how to open it; user nudges shapes and exports

实战二:StructureCanvas 工作流(读并整理人类画布)

工作流定义在 Workflows/StructureCanvas.md,处理反向场景:读取用户散落的笔记、盒子、碎片,写回一个整理后的版本——聚类、加框架、连线,不丢失任何内容

Step 0 与安全门

先确认文件路径,以及用户要的是原地修改同一文件(默认)还是旁边生成结构化副本。若画布正在编辑器中打开,请用户关闭或预期需要重开(见下文的 Gotchas)。在第一次改动前,先把文件复制为<file>.bak.tldr并明确告知——这是用户亲手创作的内容,备份就是撤销按钮。

工具契约与理想状态

T=~/.claude/skills/Tldraw/Tools/Tldr.ts bun $T inspect <file.tldr> --json # full read: shapes, text, positions, edges bun $T move <file.tldr> --id <id> --x N --y N # regroup existing shapes bun $T add <file.tldr> --spec <spec.json> # frames, arrows, summary labels bun $T validate <file.tldr>

理想结果:用户的每一条文本都原样保留——整理意味着移动、分组、加框、连线,而不是改写用户的话(新增摘要/标签形状是允许且鼓励的);相关内容进入带标题的命名聚类并与其它聚类空间分离;跨聚类关系用带标签的箭头画出;文件仍通过validateinspect前后用户文本完全一致;最后把“读懂了什么”作为交付物——回复中总结聚类结构与画布的一行式故事,而不只是返回文件改动。

隐私

创意画布属于个人内容,所有读写都应保持在本地,绝不建议把私人画布放到网页界面。

对应的示例:

User: "I dumped ideas on my canvas — structure them" → Invokes StructureCanvas workflow → Tldr.ts inspect --json reads every shape's text and position → Clusters related items, adds frames + arrows, moves shapes into groups → User reopens the same file and sees the organized version

六个已知坑位(Gotchas)

SKILL.md 把踩过的坑全部列了出来,逐条解读:

  1. zsh 的echo会破坏 spec JSON——它会把字符串里的\n展开成真实换行,导致 JSON 损坏。解法:把 spec 写进文件后以--spec <file>传入;或使用printf '%s'。工具也支持--spec -从 stdin 读取,但只能交给不重新解释转义的来源。
  2. 文本永远是richText,绝不是普通字符串——geo/text/note/arrow 的标签是 ProseMirror doc JSON。裸字符串 prop 会被校验器拒绝。Tldr.ts会替你构建,永远不要手写textprop。
  3. 箭头绑定必须有terminal: "start"|"end"——tldraw 自身的ArrowBindingUtil.getDefaultProps()会漏掉它,但 schema 校验器拒绝缺它的绑定(对照 5.2.5 验证)。工具会设置它;若手工编辑绑定,务必保留。
  4. 原始记录需要每个 prop——直接写入文件的记录绕过了编辑器默认值填充,缺 prop(如 geo 的growY)会导致加载校验失败。始终走Tldr.ts add,不要手工拼接记录。
  5. 分数索引字符串决定形状顺序——indexa1a2…)是 base62 字典序且不能以0结尾;工具自动生成,重复会导致编辑器 z-order 错乱。
  6. 桌面应用的.tldraw格式是另一种东西——tldraw 桌面应用的原生保存是 zip(内含 sqlite + assets + scripts),不是这个 JSON。本技能针对可移植的.tldrJSON,网页编辑器、VS Code 扩展、桌面应用都能打开/导入。
  7. 编辑器会持有文件内存副本——用户开着画布时你改磁盘文件,界面可能不重载(或在保存时覆盖你的改动)。改之前先关闭画布,或写完后告知用户重开。

打开与导出画布

根据 SKILL.md 的 “Opening a canvas”:

  • VS Code / Cursor:官方 tldraw 扩展可在编辑器内打开.tldr文件——完全本地,适合私密内容;
  • tldraw.com:File → Open。内容会进入第三方 Web 应用,只用于本来就打算公开的内容
  • 导出图片:在任意 tldraw 界面全选 → Export as SVG/PNG(本技能不随附无头导出路径)。

与 LifeOS 的集成机制

Tldraw 技能不是孤立工具,它嵌入了 LifeOS 的几项平台机制:

  • 个性化定制(Customization):执行前检查~/.claude/LIFEOS/USER/CUSTOMIZATIONS/SKILLS/Tldraw/(仓库中对应的模板目录为 LifeOS/install/USER/CUSTOMIZATIONS/SKILLS/)。若存在,加载其中的PREFERENCES.md(默认画布目录、偏好颜色/寄存器、默认打开界面);否则使用默认值。
  • 语音通知(Voice Notification):每次执行工作流时双通道通知——向 LifeOS 本地通知服务(http://localhost:31337/notify)POST 一条 JSON 消息,同时在文本输出中给出Running **WorkflowName** in **Tldraw**...
  • 执行日志(Execution Log):工作流完成后向~/.claude/LIFEOS/MEMORY/SKILLS/execution.jsonl追加一条 JSONL:
echo '{"ts":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","skill":"Tldraw","workflow":"WORKFLOW_USED","input":"8_WORD_SUMMARY","status":"ok|error","duration_s":SECONDS}' >> ~/.claude/LIFEOS/MEMORY/SKILLS/execution.jsonl
  • Schema 维护(Maintenance):若 tldraw 大版本升级导致生成文件打不开,需要重新快照 schema:在临时目录bun add tldraw,然后执行createTLStore({shapeUtils: defaultShapeUtils, bindingUtils: defaultBindingUtils}).schema.serialize(),把结果 JSON 覆盖写入 References/SchemaSnapshot.json,并再次用parseTldrawJsonFile验证一个生成文件。

小结

Tldraw 技能的价值在于把“白板”变成了 Agent 可读写的结构化数据源:Tldr.ts以 7 个确定性子命令覆盖画布文件全生命周期,SketchDiagramStructureCanvas两个工作流分别覆盖“画”与“读/整理”两个方向,而格式规范(TldrFormat.md)、schema 快照(SchemaSnapshot.json)与源码(Tldr.ts)共同保证了生成文件在 tldraw 5.2.5 及更新版本界面中的兼容性。对于需要在 Agent 工作流里落地“手绘式图表产出”或“思维草稿整理”的场景,这套技能提供了一条不依赖渲染、纯结构化、可验证的实现路径。

【免费下载链接】LifeOS⛰️ The Life Operating System — an intent engineering platform that moves you from your current state to your ideal state, in life and work.项目地址: https://gitcode.com/GitHub_Trending/pe/LifeOS

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询