dsh-plugin-sticky-wall
skillre/dsh-plugin-sticky-wall
DSH 侧栏自由画布便签板,支持拖动摆放、一键整理和 Markdown 正文渲染。
安装
dsh plugin --profile web add github:skillre/dsh-plugin-sticky-wallREADME
@skillre/dsh-plugin-sticky-wall · 便签墙
状态:experimental · 面向 DSH
0.2.2-rc.1
在 DSH 左侧栏加一个「便签墙」入口:随手记下一闪而过的灵感、临时的活儿和短提醒,像便签贴在桌上一样自由摆放 —— 拖动、缩放、一键整理;正文用 Markdown 写,卡片上直接渲染出来。便签与摆位都由 Host 持久化,而且一张便签就是一个真实的 Markdown 文件:重启 DSH 后位置和内容都在,退出 DSH 也能用任何编辑器打开、搜索、备份。
它解决什么
灵感往往出现在最忙的时候,而「打开一个文档、想个标题、找个位置」的摩擦足以让灵感溜走。便签墙把这件事压缩成三步:点侧栏 → 写一行 → ⌘/Ctrl + Enter。它是速记板,不是知识库:不追求层级、双链或富文本,只保证「想到就记下、回头找得到」。
非目标:不做任务管理(不排期、不分派、不提醒)、不做协作共享、不导出 Markdown 知识库、不做富文本所见即所得编辑器(正文是纯 Markdown 源码,渲染只是阅读视图)。
功能
- 左侧栏入口:
sidebar.panellist中的「便签墙」图标,点击把中央区域切换到便签墙页面。 - 自由画布:便签不是列表项,而是画布上的卡片。位置、旋转角、宽度三档(小/中/大)都属于便签数据,由 Host 保存;同一面墙在另一个窗口打开时摆位一致。
- 拖动摆放:按住卡片任意位置即可拖动,松手立刻落到新位置再把结果写回 Host(不会先弹回原处)。拖动本身不会改
updatedAt,所以「按更新」排序不会因为你整理桌面而乱掉。 - 圆心构图:整理把整面墙排成贴着中心留白的一圈紧凑构图,中心空出一块矩形留白给问候语和快速记录框;相机打开时把整面墙框进视野并居中。排布不是按「圆环」而是按留白矩形的轮廓铺开,所以每张卡片离中心都只有它自己的一半尺寸那么远 —— 同样 14 张便签,0.5.0 的圆环要占 1645×1794、只能框到 36%,现在占 1261×705、能框到 84%。留白按卡片边缘判定;整理时它在世界坐标里恒定,而单张新便签的落点跟随记录框当前在世界里的真实位置,所以平移到别处或放大之后再记一条,卡片仍然落在记录框旁边而不是它背后。
- 中心即入口:便签墙正中是随时可用的快速记录框 —— 写一句按回车就落成一张便签,不用打开表单。新便签落在离记录框最近的空缺位置,不会甩到视野之外,也不会被记录框本身挡住。
- 落点可见:新便签生成时会在落点弹入并亮一圈(约 0.9 秒);如果落点不在视野里,相机会把它带到记录框旁边的空位(上/下/左/右取最省力的那侧),必要时才适度缩小 —— 记下一条之后不用猜它到底有没有生成。相机不会把新便签对到画面正中,因为那里正是记录框。
- 留白是磁吸边界:把卡片拖到中间记录框上会被自动推到最近的空位,不会盖住输入框。
- 一键整理:「整理」把全部便签按确定性算法重新排布并做真实碰撞检测 —— 同一面墙按两次得到同一个结果,卡片永不重叠。
- 三种视图:画布(默认,自由摆位)、网格(响应式瀑布流,适合读长文)、列表(一行一条,适合按标题找)。
- 全幅画布:便签墙占满整个窗口,没有顶部标题栏和工具栏;所有控件收进底部一条浮动菜单栏。
- 紧凑菜单栏:底部只留高频动作 —— 搜索、筛选、三个图标视图切换、缩放(
− / 百分比 / +,百分比本身可点即重置)、整理、新建。排序、显示归档、清空归档收进⋯溢出菜单。菜单栏是单行、居中、宽度自适应窗口,任何按钮都不会溢出背景条。 - 相机:拖动空白纸面平移,滚轮平移,
⌘/Ctrl + 滚轮以指针为锚点缩放(0.35×–2×);打开与重置时自动把整面墙框进视野。 - Markdown 正文:正文按 Markdown 渲染 —— 标题、段落、粗体/斜体/删除线、
代码、代码块、有序/无序列表、- [ ]复选、引用、分隔线、表格、http(s)/mailto 链接。编辑时右侧有「预览」切换。 - 随手记录:
+ 新建打开便签纸,标题可选、正文必填,可打标签、选六种柔和底色、选卡片宽度。便签纸默认就很大(880×680,仍然在遮罩里居中),右下角有一个握把:拖它用指针改尺寸,聚焦后方向键也能改 —— 左右改宽、上下改高,Shift + 方向键一次走更大的步长,0恢复默认,双击握把同样恢复默认。尺寸被限制在「始终待在窗口内、四周留 24px」与 460×380 的下限之间。选好的尺寸记在本机、下次打开照旧,而且记的是你选的那个尺寸本身:小窗口里打开会先缩到装得下,窗口放大后回到你真正选过的尺寸。正文编辑器与预览都撑满整张便签纸,不再各自带一个高度上限。 - 置顶与归档:置顶的便签带左侧色条与星标;归档的便签默认隐藏,「归档」筛选会单独拉取它们,「清空归档」是永久删除。
- 便签操作:悬停或用键盘聚焦便签时,右上角出现置顶、换尺寸、编辑、归档、删除五个按钮;触屏设备上常驻显示。
- 搜索与排序:按正文、标题、标签实时过滤;可按「置顶优先 / 按创建 / 按更新」排序。
- 深浅色:只使用 DSH 主题 token 绘制框架,便签底色与文字色为插件自有配色并各自提供深色变体。
- 中英双语:跟随 DSH 界面语言实时切换,无需刷新。
- 正文编辑器:正文用纯文本框编辑,配一排 Markdown 插入工具栏(一~三级标题、引用、分隔线、代码块、无序/有序/待办列表、表格、粗体/斜体/删除线/行内代码/链接、插入当前时间)。输入框撑满便签纸的剩余高度,内容超出时在框内滚动 —— 便签纸调大,看到的就是更多正文,
Tab/Shift + Tab缩进整行,回车自动续写列表(空列表项再回车就结束列表)。中文/日文输入法正在组合时所有快捷键静默、选区与光标不动,打字不会掉字。 - 保存可靠:保存失败的错误显示在编辑面板内部,不是被面板挡在背后;上一个写入还没回来时再点操作会排队,不会被静默丢掉;有未保存的草稿时离开会先问一句「放弃未保存的内容?」。
- 前台自动刷新:窗口重新获得焦点、标签页重新可见,以及一条慢轮询,都会让墙面刷新(未变化时不重新渲染),所以另一个窗口或 agent 改过的便签会自己出现。
- 模型可用:可选注册
sticky_wall工具,直接对我说「记一下……」即可落成一张便签;list扫标题、read取回一条便签的全文和文件路径、create/update写属性与正文、move摆卡片位置、archive/delete批量改状态、arrange整理整面墙。也可以让我直接用文件工具改便签的.md。
数据与权限
| 项目 | 说明 |
|---|---|
| 数据所有者 | Host。便签与画布摆位都写进真实文件:$DSH_HOME/sticky-notes/ 下一张便签一个 .md 文件,文件名就是便签 id(<id>.md,id 是 UUID;种子欢迎便签的 id 恰好是 welcome)。文件顶部的 YAML frontmatter 存属性,其后就是正文。 |
| 数据位置 | 默认跟随 DSH_HOME(回落 ~/.dsh/sticky-notes),可用 notesDir 覆盖为绝对路径或 ~/…。便签跨 workspace 共享 —— 它们是这台机器上的个人数据,不属于某个项目目录。 |
| 网络 | 无外部网络请求。浏览器 ↔ Host 只走本机 DSH 的 /api 通道。 |
| 文件系统 | 只读写便签目录本身。写入走「先写同目录临时文件再 rename」,单条便签要么是旧的、要么是新的,不会是写了一半的。 |
| 本机偏好 | 便签纸的尺寸存在浏览器的 localStorage(键 skillre-sticky-wall.sheet-size),内容只有宽、高两个数字,不含便签正文。它只是一份便利:存坏了会回落到默认尺寸,浏览器拒绝写入(隐私模式、配额)也不影响打开和保存便签。 |
| 密钥 | 不使用任何密钥。 |
| 模型可见 | 仅当 enableAgentTool 为真(默认)时注册 sticky_wall 工具;read 会返回一条便签的全文与文件路径。 |
| agent 写入成本 | 读便签不需要任何批准(读操作从不经过沙箱)。但 agent 用原生 edit/write 改便签文件时,在 workspace-write 下第一次会被拒绝一次,需要逐次调用带 sandbox_permissions: danger-full-access 和理由才会放行 —— 除非用户把便签目录加进自己 profile 的 additionalWritableRoots。这是真实的摩擦,不是「无缝集成」:不想付这个成本就让 agent 走 sticky_wall 工具改属性,或只让它在编辑器里改正文。 |
文件在哪
默认就是 $DSH_HOME/sticky-notes/(DSH 没设置 DSH_HOME 时是 ~/.dsh/sticky-notes/),可用 notesDir 改到别处。里面一张便签一个 .md,纯 Markdown,任何编辑器都能直接打开、grep、放进 Git 或备份;顶部的 frontmatter 是属性,下面就是正文。文件被另一个工具改过之后,墙面在窗口重新获得焦点或慢轮询时自动刷新。改坏 frontmatter 不会丢便签,见已知限制。
从 0.7 升级
0.7.x 把便签存在 DSH 的 storage domain($DSH_HOME/storages/skillre_sticky_wall/)里,0.8.0 改成上面的 .md 文件。升级不需要任何手动操作:0.8.0 第一次启动时,如果便签目录还是空的、而旧 domain 里还有便签,就把每一条都转成一个 .md(属性、摆位、时间戳和 id 全部保留),先写进同级暂存目录再一次性 rename 发布,所以中途失败不会留下半截目录。迁移完成后 sticky-notes/ 里会多一个 migration.json 记录迁移时间和条数。
- 旧数据不会被删:迁移只读旧 domain,从不回写也不清理。想回退就停掉 DSH、把 0.8.0 写出的
sticky-notes/移走、装回 0.7.x,旧便签还是原样。 - 迁移失败不影响打开:失败时什么也不写,墙面照常打开(空的而不是坏的),下次启动重试。
- 确认一切正常之后,旧 domain 目录
$DSH_HOME/storages/skillre_sticky_wall/可以自行删除。
配置
在 profile 的 cordis.patch.yml 中按行 id 覆盖(config 整行替换,未写出的键取默认值):
- id: skillre-sticky-wall
name: '@skillre/dsh-plugin-sticky-wall'
config:
notesDir: ''
maxNotes: 400
enableAgentTool: true
seedWelcomeNote: true
| 键 | 默认 | 含义 |
|---|---|---|
notesDir | ''(空) | 便签 .md 文件放在哪个目录。空 = 跟随 DSH home:$DSH_HOME/sticky-notes,DSH 没设置 DSH_HOME 时回落 ~/.dsh/sticky-notes。可写绝对路径或 ~/…。便签跨 workspace 共享。 |
maxNotes | 400 | 未归档便签的数量上限(1–5000)。新建、取消归档、批量恢复都受此约束,超出时返回 sticky-wall/wall-full,需先归档或删除。 |
enableAgentTool | true | 是否向模型注册 sticky_wall 工具。 |
seedWelcomeNote | true | 全新的空墙是否写入一张欢迎便签(说明快捷键与用法)。 |
notesDir 指到别处时,插件只会在那里读写 .md,不会自己去动旧目录。不要把两个同时运行的 DSH 实例指到同一个便签目录:每个 Host 在启动时把便签读进内存并把它当作权威缓存,两个进程各写各的整份文件,会互相覆盖而不是合并 —— 想共用一份便签,请用导入/导出或 Git 同步。
安装
开发与测试完成后,由用户本人在 DSH Desktop Client 或 Web UI 的 Plugins / 插件管理界面选择来源并确认安装、启用,开发者或 agent 不在用户 profile 中代装。
- 已加入插件市场:在 Plugins → Discover → Index sources 添加
https://skillre.github.io/dsh-plugin-market/index.json(需先启用实验包 Custom plugin markets),然后在 Discover 里直接安装本插件。 - npm(推荐,也是唯一支持原地更新的来源):在安装对话框输入 npm 包规格
@skillre/dsh-plugin-sticky-wall@<version>。 - 未发布时:可提供已构建产物的
.tgz绝对路径,前提是先核实该管理器接受此来源且包可安装。 - 本仓库是自包含的 Git 源:
lib/构建产物已提交,且不声明scripts.prepare,因此安装不触发构建脚本。对应的固定 spec 形如git+https://github.com/skillre/dsh-plugin-sticky-wall.git#<commit>,已实测可安装。
更新与回滚
DSH 0.2.2 线起,插件页有官方的版本区块(listVersions / updateBundle),可以原地检查并更新。
能否走这条路,只取决于安装来源和包内容,与仓库配置无关:
| 安装来源 | 能原地更新吗 |
|---|---|
npm registry(@skillre/dsh-plugin-sticky-wall@<version>) | ✅ 详情页出现「版本」区块,可检查更新并原地升级 |
git+https://…#<commit>(本仓库的市场条目) | ❌ 没有「版本」区块,只能卸载后重装 |
.tgz 本地文件 / file: | ❌ 同上 |
本插件的 updatable 条件全部满足:第三方 bundle、以自己包名保存的 registry spec、合法 SemVer、
不携带 @deepseek-ai/dsh-plugin-manager 等受保护的插件管理行。因此想获得官方更新能力,请用 npm 包名安装。
更新语义(如实记录,避免误期):
-
只升不降:界面不会提供比已装版本更旧的版本;
-
更新成功后 profile 依赖被写成精确版本(原本是 range 也会变成精确版),失败回装同理;
-
更新 = 先移除再安装两步,HMR 下回装的 bundle 可能排到 bundle 列表末尾,改变配置层顺序;
-
失败可恢复:装不上/取消/起不来会回装原版本;回装也失败则该包处于未安装状态;
-
新版本若需要新的 build-script 批准会失败并回装旧版;
-
版本豁免(
allow-version)只有 CLI 与 agent 工具,插件页没有入口。 -
回滚:npm 版本不可覆盖。故障版本用
npm deprecate标记并发布新的修复版本;用户在插件管理界面 移除故障 bundle 后重装已知可用的版本(若界面不支持指定旧版,需由用户决定恢复渠道)。 -
数据兼容:0.8.0 起便签是
$DSH_HOME/sticky-notes/下的.md文件,不再是 storage domain,所以回滚/备份都是普通的文件拷贝:降级前把sticky-notes/整个目录复制一份即可。0.7.x 的旧 domain 在升级后仍然原样保留,回装 0.7.x 会直接读到它(详见从 0.7 升级)。 -
卸载:见 UNINSTALL.md。卸载插件不会自动删除便签文件。
显示元数据(插件卡片与详情页)
DSH 读取插件卡片与详情页时不激活插件,所以这些资源必须随包发布,且分三层:
| 层 | 文件 | 内容 |
|---|---|---|
| 卡片标题/副标题 | locale/en.json、locale/zh.json 的 meta.title / meta.description | 一行,≤ 120 字符,纯文本 |
| 详情页 | meta.detail → docs/DETAIL.md / docs/DETAIL.zh.md | 只有一行  |
| 开发者文档 | README.md / README.en.md(本文件) | 安装、配置、兼容性、限制…… |
locale/*.json经 Node ESM resolver 解析,因此exports必须声明"./locale/*.json";缺这一条会抛ERR_PACKAGE_PATH_NOT_EXPORTED,而 DSH 会静默吞掉该错误,卡片退化成裸包名 —— 没有任何地方会报错。meta.detail是 DSH0.2.2新增的字段,指向包内相对路径的 Markdown,由 DSH 从包目录直接读(不走 exports), 所以files必须包含docs。缺meta.detail时 DSH 回退到README.md—— 也就是把这份开发者手册塞进详情页, 这正是本版本要修掉的问题。- 详情页图片:
docs/preview.svg(英文)与docs/preview.zh.svg(中文),固定 640×300 逻辑比例(本仓库用 1280×600)。 规则见 fleet 的docs/display-contract.md,画板记录在 docs/PREVIEW.md。
node scripts/preview.mjs check # 离线校验预览图与 locale 元数据(npm run check 会自动跑)
插件市场
本插件已发布到由本舰队生成的插件市场索引:
- 索引:
https://skillre.github.io/dsh-plugin-market/index.json - 条目:
@skillre/dsh-plugin-sticky-wall@0.1.2,来源为 commit-pinned Git(83c932f) - 图标:
https://skillre.github.io/dsh-plugin-market/icons/sticky-wall.svg
安装路径已实测:从线上索引取 spec → 装进隔离 profile → --dump-config → 有界启动 → 路由可用(证据见 docs/evidence/market-install-0.1.2.json)。
已知限制
- 便签墙是速记板:正文上限 20 万字符、标题 120 字符、标签 8 个。20 万是资源护栏(防止一条病态的长文本把 Host 拖垮),不是产品定位 —— 一条便签可以是一篇短文。
- 单个便签文件超过 4 MiB 时会被跳过、不读入(在
readdir/stat阶段就拒掉,不交给解析器),并在 Host 日志里留一行说明。这是防止有人往目录里丢一个 200 MB 的文件把墙拖死,不是正常的便签尺寸。 - frontmatter 写坏(例如手改或模型改错了 YAML 行)不会丢便签:卡片照常显示、正文照常渲染,属性退化成默认值(黄色、未置顶、未归档、无标签、无摆位),并挂一个「元数据异常」角标;整份文件内容也不会被当成正文以外的东西丢弃。由更新版本写出的 frontmatter(
schema比本版本新)同样会读成一张带角标的卡片,并保留本版本看不懂的字段。 - agent 改便签文件的批准成本:读不需要批准,但原生
edit/write在workspace-write下第一次会被拒绝一次,需要逐次调用带danger-full-access与理由,除非把便签目录加进 profile 的additionalWritableRoots。这是有意的安全边界,别期望「agent 随手就能改」。 - Markdown 是刻意的子集,不是完整 CommonMark:支持标题(
#–####)、段落与换行、粗体/斜体/删除线、 行内`code`、```/~~~代码块、有序/无序列表、- [ ]复选、引用、分隔线、管道表格、 http(s)/mailto 链接。不支持嵌套列表缩进、图片、脚注、任务列表交互(复选框是只读字形)。 - 正文里的原始 HTML 一律当文本显示,不会执行也不会渲染 —— 这是安全选择,不是缺陷。
- 卡片宽度只有小/中/大三档预设,不支持任意拖拽调整宽度;拖动会保留卡片原有的轻微倾角。这一条说的是画布上的卡片,大小可调的只有随手记录的便签纸。
- 整理是 O(n) 的螺旋放置 + 网格碰撞检测;便签上限 400 张,超出视野的墙需要自己平移或缩小。
- 画布是二维平面:没有分组、图层、连线或吸附对齐;也不支持双指旋转或触屏捏合之外的手势。
- 自动取景有可读性下限(42%):便签很多时整面墙不会全部挤进视野,而是居中显示、需要平移查看。整理不会把卡片放在问候语和记录框下面;平移到别处再新建时,落点也会避开记录框当前所在的位置。
- 便签的位置由 Host 保存;同一面墙在两个窗口同时打开时,各自渲染自己的快照,不会实时推送另一个窗口的拖动结果 —— 但窗口重新获得焦点/重新可见时会重新拉取,所以不会长期停在旧状态。
- 归档便签不占
maxNotes名额,但恢复它们会占名额;名额已满时恢复会被拒绝而不是悄悄超限。 - 「清空归档」是永久删除,不可撤销。
- 批量归档/删除要么全部生效,要么一条都不改:请求里含一个不存在的 id 时整批被拒绝。
- 目录里的非便签文件(不叫
<合法 id>.md的、子目录、*.md.tmp残片)会被忽略而不是当成便签;写入中断留下的临时文件最多占一点磁盘,不会变成重复便签。 - 本版本仅在 DSH
0.2.2-rc.1上做过真实挂载验证,未宣称兼容其他 DSH 版本。
兼容性
见 compatibility.json:记录真实挂载过的 DSH 版本、验证日期与检查项。engines.dsh 只是安装声明,不是兼容性证据。
开发
npm install
npm run check # typecheck + 测试 + 打包视图
npm pack # 生成可安装的 tarball
包内容:lib/(Host 与 Client 构建产物及声明)、cordis.patch.yml、compatibility.json、locale/*.json、icon.svg、文档与许可证。
许可
MIT