前言¶
DSH 的运行方式是「一切皆插件」,插件装得越多,环境越贴近自己的工作流,但维护成本也越高:在办公室的桌面端装了一批插件,回家打开另一台设备却只有基础集合,要么手工重新装一遍,要么靠记忆核对哪些插件是开着的。手工复制插件目录的做法有几个问题:目录结构、cordis.patch.yml、依赖和 profile 的差异很难对齐,而且容易遗漏「某台设备上停用了某个插件」这种状态差异。
下面介绍的 wystan68/dsh-plugin-sync 解决的正是这个问题:它同步的不是插件源码,而是一份「插件清单」——包名、版本、启用/停用状态,在登录了 DSH 的设备之间保持一致。
这是什么¶
dsh-plugin-sync 由 Wystan68 维护(package.json 中 author 为 Wystan),分类为 admin-security,当前星标为 0。它定位为一个 DSH Host 插件 + Client 插件,通过同步码或加密中转在设备间搬运插件清单。
它明确不在同步范围内的内容:cordis.patch.yml 里的 config 配置项、插件源码,以及任何密钥或会话数据。也就是说,它解决的是「装上哪些、哪些开着」的问题,不是「配置成什么样」的问题。
安装与启用¶
在 DSH 里装(推荐):打开 设置 → 插件 → 安装插件,粘贴:
github:Wystan68/dsh-plugin-sync
或在终端装(需要 dsh 命令可用):
dsh plugin --profile desktop add github:Wystan68/dsh-plugin-sync
desktop 换成当前正在使用的 profile 名,不填 profile 时默认是 web。桌面版可以用完整路径调用:
"/Applications/DeepSeek Harness.app/Contents/Resources/runtime/cli/bin/dsh" plugin --profile desktop add github:Wystan68/dsh-plugin-sync
装完重启 DSH,左侧栏会出现「插件同步」图标(第 6 个)。卸载时在 设置 → 插件 里停用或移除,或执行:
dsh plugin --profile desktop remove dsh-plugin-sync
使用:同步码或加密中转¶
使用时的固定顺序是:先在每台设备设好同步密钥,再选一种传输方式,最后在差异预览里确认应用。
1、设同步密钥。打开面板,输入一把至少 8 位的密钥(例如 correct horse battery staple),点「设置」。密钥只在本机派生,明文不上传、不写入同步数据。
2、确认设备处在同一组。两台设备使用同一把密钥后,面板上会显示相同的同步组码(如 qvi2a-jwfkq)。
3、选择传输方式:
- 同步码:A 设备点「生成同步码」复制,B 设备点「导入同步码」粘贴 → 预览差异 → 应用。不依赖任何服务器。
- 加密中转:在「加密中转」里部署或填写地址 → A 点「推送」,B 点「拉取」→ 预览差异 → 应用。也可勾选「自动拉取并应用」。
4、确认差异。差异预览会列出:要安装的插件、要切换的启用状态、跳过项(本地链接插件、无安装来源)、版本差异提示。确认后再点「应用变更」。
同步语义¶
几点需要知道的语义,避免误操作:
- 谁推送,以谁为准。同一同步组的远端只有一份最新快照,后推送的会覆盖先前的;应用后本机也变成这份清单的副本。
- 最小改动。只安装缺失的插件、只切换与远端不同的启用状态;未列出的插件不会被卸载。版本不同只提示,不自动升降级。
- 不会同步自己。插件同步自己的停用状态会被忽略,避免应用后界面消失。
- 安装来源。npm 包按
name@version安装;link:/file:本地插件在其它设备上没有源码目录,会列入「跳过」并提示手动安装。 - 账号通道。已登录 DeepSeek 账号时面板会显示账号信息;账号云同步接口尚未开放,当前同步仍由同步密钥驱动。
加密中转¶
一键部署:在「加密中转」里填一个 Cloudflare API Token,点「自动部署」。Token 需要 Account Settings: Read、Workers Scripts: Edit、Workers KV Storage: Edit 三项权限。插件会创建 dsh-plugin-sync KV 命名空间、上传 Worker(绑定 SYNC)、尝试开启 *.workers.dev 子域,最后把地址填回面板,每一步的结果都会显示。
手动部署:在面板里打开「手动部署」复制 Worker 脚本,或在仓库取 worker.mjs:
1、Cloudflare 控制台 → Workers & Pages → 创建 Worker,粘贴脚本。
2、绑定 KV 命名空间,变量名必须是 SYNC。
3、部署后把 https://<worker>.<子域>.workers.dev 填回面板。
中转协议:
GET /health
GET /v1/snapshots/{group} → 密文信封 JSON,或 404
PUT /v1/snapshots/{group} → 写入信封
DELETE /v1/snapshots/{group}
Authorization: Bearer <由密钥派生的令牌>
载荷是端到端加密的 AES-256-GCM 密文,中转无法解密。同一同步组第一次写入时,中转会把令牌的 SHA-256 钉在 KV 里;换成另一把密钥既读不到也覆盖不了这个组。单次请求体上限 200 KB。
安全模型¶
同步码和中转共用同一套加密载荷,派生链路如下:
- 密钥 → PBKDF2-SHA256(210,000 次)→ 32 字节主密钥;同步组码、中转令牌、加密密钥都由主密钥 HMAC 派生。
- 本机只保存派生后的主密钥(DSH 凭据库
plugin-sync/settings),明文口令不会落盘。 - 载荷在加密前先 gzip,使用随机 12 字节 IV 与 AAD(绑定同步组),防止跨组重放。
- 中转只存密文;删除同步组会同时删除令牌哈希。
适用场景与注意¶
适合需要在多台 DSH 设备间保持插件集合一致、又不想手工核对的场景,尤其是明文同步码不方便传递时,可以用自建的 Cloudflare Worker 中转。
需要注意几点:插件以当前 DSH 进程的权限运行,安装前应先阅读源码与许可证(MIT),并确认 github:Wystan68/dsh-plugin-sync 这个来源可信。它只同步插件清单,不同步 config 与源码,配置差异仍需单独管理。中转自建的情况下,*.workers.dev 子域可用性依赖 Cloudflare;如果将来要正式使用账号云同步,需要等待接口开放。
结尾¶
dsh-plugin-sync 做的事情比较单薄但具体:把「设备之间插件集合是否一致」这个问题,收敛成一次同步码导入或一次中转拉取。项目当前版本 0.1.0,纯 ESM、无运行时依赖、要求 Node.js ≥ 20,测试覆盖密钥派生、加解密、同步码、差异计划、Worker 与端到端流程。目录页见 https://www.skillhub.cn/plugins/Wystan68/dsh-plugin-sync ,源码见 https://github.com/Wystan68/dsh-plugin-sync 。