DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

Arlenman /

Arlenman/dsh-backup-sync

Verified

DSH 备份 / 换机同步插件:把技能、插件、配置、记忆、待办打成一个包,换机时按模块做带基线的三方合并导入

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@469fe75f

dsh-backup-sync

给 DeepSeek Harness 的备份 / 恢复 / 换机同步插件: 把技能、插件、配置、记忆、待办打成一个 tar.gz,换台电脑按模块增量导入, 靠一份基线库做三方合并 —— 不覆盖你在这台机器上新改的东西。 也能直接把包推到你自己的 WebDAV 空间(绿联 / 群晖 / 坚果云 / Nextcloud…),换机时下载回来。

CI License: MIT Node


目录

  • 它解决什么问题
  • 和 dsh-backup 有什么不同
  • 安装
  • 界面
  • 六个模块
  • 文件放在哪
  • 增量导入:基线三方合并
  • 两条红线
  • 定时备份
  • 云端备份(WebDAV)
  • HTTP 接口
  • 开发
  • 已知限制
  • English
  • License

它解决什么问题

DSH 的「资产」散落在两个地方:

资产 位置
技能(工作流本体) <userHome>/.agents/skills
插件清单 / 依赖锁 <dshHome>/profiles/<profile>/
核心配置(provider、模型、主题、插件配置) <dshHome>/profiles/<profile>/cordis.patch.yml
记忆 / 待办 <dshHome>/memories/
对话记录 <dshHome>/sessions/

其中 <dshHome> 默认是 ~/.dsh,而技能根本不在它下面。 换电脑时最容易丢的恰好是技能和配置 —— 而它们又最值钱。

这个插件把上面这些一起打包,并且解决第二个问题:导入时不要把人家的新东西冲掉。

和 dsh-backup 有什么不同

@xiaoyuyu6420/dsh-backup 是一个成熟的全量备份插件(本插件作者也在用),但它的 skills 类型找的是 ~/.dsh/skills;技能库实际住在 ~/.agents/skills(~/.dsh 之外),所以在技能装在标准位置的机器上,它备不到技能。

两者的定位:

dsh-backup dsh-backup-sync(本插件)
备份范围 ~/.dsh 整棵树(可按类型排除) 六个模块,含 ~/.agents/skills
导入语义 恢复(覆盖) 带基线的三方合并,逐文件给差异
冲突处理 — 弹差异预览,逐文件选保留哪边
云同步 内置 GitHub 私有仓库同步 推送到「同步目录」(可指向任何被同步工具盯着的目录)
救援 有进程外救援脚本 —

两个可以同时装,互不干扰(备份目录、状态文件都不同名)。

安装

# 从 GitHub 装(推荐锁 tag,可复现)
dsh plugin --profile web add github:Arlenman/dsh-backup-sync#v0.1.0

# 跟 main 分支走
dsh plugin --profile web add github:Arlenman/dsh-backup-sync

# 或直接用发行版里的 tar.gz
dsh plugin --profile web add https://github.com/Arlenman/dsh-backup-sync/releases/download/v0.1.0/dsh-backup-sync-0.1.0.tgz

桌面版(Electron)在 设置 → 插件 里粘贴上面任意一条即可。

换台电脑(家里另一台)就填这一条:

github:Arlenman/dsh-backup-sync#v0.1.0

这条路已经实测过(2026-10-15,拿上面那条 spec 对真仓库跑 pnpm add,51.5 秒装完): pnpm 拉的是 codeload 从仓库树打的 tarball(锁文件里记的是 gitHosted: true + sha512 integrity), 装出来 22 个文件(lib/*.js 18 个 + package.json + cordis.patch.yml + README.md + LICENSE), 与 Release 里那个 .tgz 逐个文件、逐字节一致(22/22,sha256 全等); 解析到的提交是 289819f(= tag v0.1.0),装出来的 lib/index.js 用 node 直接 import 就能加载。 仓库里没有 prepare / prepublish / postinstall 脚本、没有 dependencies, lib/ 是提交进仓库的现成 JS ⇒ 目标机器不需要构建,也不需要装任何依赖。

两个前提:

  • 目标机器要能连上 github.com。插件管理器在装 git 依赖前有 5 秒 github.com 预检, 之后 pnpm 拉 codeload.github.com 的 tarball(60 秒 idle 超时)。包本体约 150 KB,慢网也够。
  • 装完重启一次 DSH(宿主半边不热重载,见下)。

暂未发布到 npm,所以 dsh plugin --profile web add dsh-backup-sync 这个写法现在装不到东西 —— 请用上面的 GitHub 写法。

注意:插件的宿主半边(HTTP 路由)不热重载,装完要重启一次 DSH; 界面半边刷新页面即可生效。

要求:DSH 0.2.0-rc.2,Node.js ≥ 22。零 npm 运行时依赖(只用 Node 内置模块 + 平台提供的 react;打包那一步调用系统自带的 tar)。

界面

入口在 设置 → 备份同步(与「插件」「技能」并列),四个页签:

备份 历史版本
备份 历史版本
导入 同步
导入 同步
  • 备份:勾模块 → 填输出目录 → 打一个包(可选打包前跑校验)。
  • 历史版本:列出输出目录里的包(时间、体积、来源机器、模块数、文件数), 可就地校验(比对 sha256)、导入、复制路径。
  • 导入:选一个包 → 扫描 → 逐文件差异预览(新增 / 修改 / 删除 / 冲突)→ 逐项裁决 → 应用。 应用前自动把当前状态快照到 <输出目录>/pre-restore-<时间戳>/。
  • 同步:把包推到「同步目录」(OneDrive / 坚果云 / 群晖 / U 盘都行),带 sha256 校验。 下面还有一张**云端(WebDAV)**卡片:填地址 / 账号 / 口令 / 远端目录 →「保存并测试连接」→ 上传 / 列出远端 / 下载到本机 / 删远端(详见云端备份)。

六个模块

模块 界面名 根目录 收录内容 默认
skills 技能 <userHome>/.agents/skills 整棵技能树(按技能目录计数) ✅
plugins 插件 <dshHome>/profiles/<profile>/ package.json、pnpm-lock.yaml、.npmrc、pnpm-workspace.yaml ✅
config 配置 <dshHome>/profiles/<profile>/ 与 <dshHome>/ cordis.patch.yml、settings.yaml、AGENTS.md ✅
memory 记忆 <dshHome>/memories/ MEMORY.md / USER.md / KEY.md / daily/*.md 等(不含待办文件) ✅
todo 待办 <dshHome>/memories/ TODOS-life.md、TODOS-work.md、projects/<hash>/TODOS.md、daily/YYYY-MM-DD.todo.md ✅
sessions 对话 <dshHome>/sessions/ 全部会话记录 ⬜ 本地专用 · 不上云

两个设计细节:

  1. 模块按「文件模式」切分,不按目录切分。记忆与待办同居 memories/ 一棵树: projects/<hash>/MEMORY.md 是记忆,隔壁的 projects/<hash>/TODOS.md 是待办。 按目录切必然切错,所以用文件模式互斥认领(有测试钉住「每个路径恰好属于一个模块」)。
  2. 对话默认不勾选,并在界面上标注「本地专用 · 不上云」——它体积大、含隐私, 而且通常没必要跟着人走。

文件放在哪

插件自己的状态(都在本机,不进包):

<dshHome>/backup-sync/settings.json   # 你的设置(输出目录、同步目录、定时…)
<dshHome>/backup-sync/state.json      # 基线库:上次打包时各文件的 sha256

备份包(默认输出目录,可用设置覆盖):

dsh-sync-20261014-093012.tar.gz        # 归档本体
dsh-sync-20261014-093012.tar.gz.sha256 # 边车校验文件

包内结构(归档内是归一化布局,与机器无关):

dsh/      ← 对应 <dshHome> 下的文件(profiles/… memories/… sessions/…)
agents/   ← 对应 <userHome>/.agents 下的文件(skills/…)
manifest.json   ← 格式版本、时间、来源机器、模块清单、逐文件 sha256

默认输出目录的选取规则:Windows 上确实存在 D: 盘、且 <dshHome> 位于 <userHome> 之下(判定为「真实安装」)时用 D:\dsh-backups-sync; 否则落在 <userHome>/dsh-backups-sync。 绝不默认写到一个这台机器上不存在的路径。

增量导入:基线三方合并

导入不是「解压覆盖」,而是三方合并:

base   = 基线库(上次打包时,两边都认可的共同祖先)
ours   = 这台机器现在的状态
theirs = 包里的状态

逐文件判定:

情况 动作
只有 theirs 变了 采纳包里的版本
只有 ours 变了 保留本地,静默跳过
两边都变了且内容不同 冲突 → 弹差异预览,逐个选
本地删了、包里改了 冲突(默认保留本地)
包里删了、本地没动 删除(需显式开启 allowDelete,默认关闭)

几个刻意的选择:

  • 冲突默认「保留本地」。裁决完之后,基线记的是归档版本而不是本地版本 —— 否则下次导入会把用户刚裁决保留的版本判成「归档改了、本地没动」而擅自覆盖,裁决等于白做。
  • 合并粒度按内容类型定:技能 = 整个目录;配置文件 = 整个文件(默认保留本地); 插件清单 = JSON 字段级;记忆 = 按内容行去重;待办 = 按 8 位十六进制 id;会话 = 整个文件。
  • 删除是关着的。allowDelete 默认 false,想同步「删除」这个动作必须手动开。
  • 导入前自动快照:<输出目录>/pre-restore-<时间戳>/ 就是一份能原样还原的包。

两条红线

  1. 凭据永不进包、永不进基线。 ~/.dsh/.credentials.yaml 之类的凭据文件在扫描阶段 就被排除(26 个凭据文件名 + 7 个后缀的黑名单,另有 1 MiB 内容闸)。 导入侧还会再拦一次:老版本打的包、别人给的包里若带着这类文件,只会显示为 「跳过」,不会写进本机。包里不可能出现 API key。
  2. 对话默认不参与。 想备份对话要手动勾 —— 它只在本机流转,不会被同步。

定时备份

在设置里打开后,插件在宿主进程里定时打包。两种频率:每天某个时刻(默认 03:00) 或每隔 N 小时(1–720,默认 24)。约定:

  • DSH 没开就不补跑(不做启动补跑,也不装系统计划任务);
  • 失败不重试,下一次到点照常;
  • 只清理自己打的包,且 keep <= 0 表示不清理;
  • 「立即跑一次」按钮绕过开关,用于验证;
  • 定时范围默认跟随「备份」页当前勾选的模块,可 pin 成固定集合;
  • 对话永远不会进定时包。

云端备份(WebDAV)

「同步」页签里有一张**云端(WebDAV)**卡片。填四个字段就能用:

字段 例子 说明
云端地址 http://192.168.3.1:5005/ NAS 上 WebDAV 服务给出的地址(要带协议,端口按 NAS 说明填)
账号 / 口令 dsh / ****** 口令建议用 NAS 里给应用生成的专用密码,不要用登录密码
远端目录 dsh-backup 云端根目录下的一个子目录,第一次上传会自动创建
传完自动上传 开关 打开后每次「立即跑一次」或定时打包成功,自动把最新的包传上去

点「保存并测试连接」会当场告诉你通不通(口令错会明确显示 401);界面上还有 传最新一份上去 / 列出远端 / 下载到本机 / 删远端 四个动作。

换机流程:新机器装好插件 → 填同一个 WebDAV 地址与目录 → 「列出远端」→ 挑一份 →「下载到本机」→ 到「导入」页签选它 → 预览 → 应用。

安全约定(这几条是硬编码的,不是提示):

  • 口令单独存在 <dshHome>/backup-sync/cloud-credentials.json(权限 0600), 不进设置文件、不进日志、界面里读不回来(只显示「已保存」)。
  • 这个凭据文件名在黑名单里 —— 既不会被打进备份包,也不会被导入。
  • 远端只认自己打的包:名字必须匹配 dsh-sync-<时间戳>.tar.gz。别的名字(包括 ../ 这类路径穿越)一律拒绝,而且拒绝发生在发请求之前。
  • 上传/下载/删除都会核对 sha256 边车文件;下载采用「先写临时文件再改名」, 同名包默认不覆盖(要显式确认)。
  • ⚠️ 备份包里是明文(配置、技能、待办、记忆)。所以云端目录必须是私有的, 别用公开分享目录。要加密请自己在外面套一层(如 restic / rclone crypt)。

兼容性:只依赖 WebDAV 标准动词(OPTIONS / PROPFIND / MKCOL / PUT / GET / DELETE), Basic 认证,不依赖任何厂商私有 API。NAS 上记得先把 WebDAV 服务打开。 真机实测的服务器方言记在 docs/notes/webdav-servers.md。

HTTP 接口

宿主半边在 /api/dsh-backup-sync 下注册了 20 条路由(都走 DSH 自带的连接鉴权):

GET  /state               GET  /settings          POST /settings
POST /backup              POST /import/preview    POST /import/apply
POST /verify              POST /sync/push         GET  /sync/list
POST /schedule            POST /schedule/run-now
GET  /skills              GET  /file
GET  /cloud/state         POST /cloud/config      POST /cloud/password
POST /cloud/test          POST /cloud/upload      POST /cloud/list
POST /cloud/download      POST /cloud/remove

云端那 8 条失败时也返回 HTTP 200,把业务结论放在 {ok:false, error} 里 (callApi 才能把「口令不对」这类人话原样显示到卡片上),抛异常才走顶栏报错。

开发

git clone https://github.com/Arlenman/dsh-backup-sync.git
cd dsh-backup-sync
npm test              # node --test,483 项,零依赖、不需要 install(约 7 秒)
npm run e2e:cloud     # 云端链路端到端:真起一台假 WebDAV 服务器,65 项断言

目录:

lib/index.js      宿主入口(注册 HTTP 路由 + 定时器)
lib/client.js     界面半边(手写 CJS bundle,注册 settings.section)
lib/scan.js       扫描六个模块 → 文件清单 + 哈希
lib/archive.js    打包 / 解包 / manifest / sha256 校验
lib/diff.js       三方合并与冲突判定
lib/apply.js      应用导入计划(带快照回滚)
lib/guard.js      凭据黑名单(永不进包)
lib/schedule.js   定时配置归一化与描述(纯函数)
lib/scheduler.js  宿主进程内定时器(心跳、到点跑一次、轮换旧包)
lib/webdav.js     WebDAV 客户端(零依赖,自己实现请求与 XML 解析)
lib/cloud.js      云端编排层(凭据隔离、只认自己的包、上传/下载/删除)
lib/routes.js     20 条 HTTP 路由
docs/notes/       逆向内核得到的插件契约(模块加载器、settings 槽位)
docs/plans/       设计文档与实施计划(含逐条决策理由)
scripts/          开发期验收脚本(含云端端到端)
test/             node:test 单测(含跨平台路径断言与假 WebDAV 服务器)

仓库里的三份文档对写 DSH 插件的人可能有用:

  • docs/notes/module-loader-contract.md —— 客户端模块加载器契约(种子表、dsh.client、槽位 API)
  • docs/notes/settings-section-contract.md —— settings.section 槽位的注册契约
  • docs/plans/ —— 本插件的设计与实施记录

仓库内的脚本

scripts/ 下的几个脚本是开发期真机验收工具,它们读真实的 ~/.dsh:

脚本 作用 会写哪里
scan-report.mjs 只读扫描,打印各模块文件数/体积 不写
guard-report.mjs 校验凭据黑名单是否真的拦住了 不写
cloud-e2e.mjs 云端链路端到端(起真进程的假 WebDAV 服务器,--report 可落成 markdown) 只写仓库下 .tmp-cloud-e2e-*,跑完删除(--keep 保留)
backup-now.mjs 命令行打一个包 --out 指定目录,并更新真实基线库(--no-baseline 可跳过)
verify-restore.mjs 拿真实包在空目录里跑完整导入并逐文件核对 只写仓库下 .tmp-restore-*,跑完删除

已知限制

  • 归档格式为 tar.gz(打包调用系统自带的 tar),不支持加密。要加密请用同步目录那一侧的工具。
  • 导入的合并粒度里,配置文件是「整文件」级别:两边都改了同一个配置文件就会判冲突, 不会做字段级合并(除了插件清单的 JSON)。
  • 定时器跑在宿主进程里,DSH 退出即停(这是有意的,见上)。
  • 界面半边是手写的 CJS bundle(本机没有打包器),所以没有 JSX、没有 TS。
  • 云端目前只有 WebDAV 一种后端(传输层是分开写的,加 S3 / 对象存储属于新增一个 lib/cloud-*.js, 不影响现有路径)。认证目前只支持 Basic(Digest 会明确报「暂不支持」)。
  • 云端不自动合并:远端只是包的存放处,冲突判断仍在导入那一侧做。
  • .npmrc / .yarnrc 既不进包、也不导入(按凭据类文件名拦截,而且里面的 store-dir 本来就是机器专属路径 —— 实测把它导到另一台机器会让 pnpm 直接 ERR_PNPM_UNEXPECTED_STORE)。 代价:目标机器若依赖 profile 级 .npmrc 里的镜像源 / 代理,导入后要手动补一次。

English

dsh-backup-sync is a backup / restore / machine-migration plugin for DeepSeek Harness.

  • Six modules: skills (~/.agents/skills — which other backup plugins miss), plugin manifests, core config, memories, todos, and sessions (opt-in, local-only).
  • Three-way merge import: a local baseline records the hashes of the last backup, so importing on another machine never silently overwrites changes made there. Conflicts show a per-file diff.
  • Credentials never enter an archive (deny-list of credential filenames/suffixes).
  • WebDAV cloud sync: upload archives to your own WebDAV space (UGREEN / Synology / Nutstore / Nextcloud) and pull them back on the new machine. The password lives in its own 0600 file, only self-made archive names are accepted (path traversal is rejected before any request is sent).
  • Zero npm runtime dependencies (system tar does the packing), tar.gz + sha256 sidecar, settings entry under Settings → 备份同步.
dsh plugin --profile web add github:Arlenman/dsh-backup-sync#v0.1.0

Requires DSH 0.2.0-rc.2 and Node.js ≥ 22. MIT licensed.

License

MIT © 2026 Arlenman

—/ 5

No ratings yet

Verified DSH bundle

Commit 469fe75fd422

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout