dsh-config-sync

August 17, 2026 · View on GitHub

dsh-config-sync logo

把 DSH 配置目录(默认 ~/.dsh~/.agents/skills)镜像同步到 iCloud(或任意本地目录), 设置页「配置同步」按钮一键触发。MinIO / OSS 作为预留存储后端,已在配置 schema 与后端注册表中留位。

快速开始

# 1. link 安装进 web profile(已做则跳过)
#    在 ~/.dsh/profiles/web/package.json 的 dependencies 加:
#      "dsh-config-sync": "link:/Users/apple/dev/dsh-config-sync"
#    然后 cd ~/.dsh/profiles/web && pnpm install

# 2. cordis.patch.yml 注册(见 cordis.patch.yml.example)
# 3. 重启 DSH(服务端插件需重启加载)
# 4. 打开 设置 → 配置同步 → 点「立即同步」

功能

  • 一键同步:设置页「配置同步」Tab 的按钮 → POST /dsh-sync/run,后台按源目录逐个镜像。
  • 双向同步:支持 export(本机→备份,默认)与 import(备份→本机,恢复)。
    • 导入是破坏性操作:UI 强制「预演导入(dry-run,不改动)→ 执行导入(二次确认)」两步;
    • 引擎护栏:源==目标、导入目标落在备份根目录内 → 拒绝执行。
  • 镜像语义(rsync 式):
    • 大小或 mtime 不同的文件才复制(2ms 容差);
    • 目标里源已不存在的文件删除、空目录修剪(rsync --delete);
    • 排除项按路径段精确名匹配(node_modules.git)或根锚前缀(pnpm-lock.yaml);
    • 符号链接默认跟随(followSymlinks: true):指向文件的链接复制为普通文件,指向目录的链接递归拷贝其内容——镜像跨机器可移植(如 dws/find-skills 指向 ~/.tokentracker/... 的场景)。
  • 符号链接自动还原:导出时把链接目标记录进备份根的 .dsh-sync-manifest.json;导入时——
    • 同机(原链接目标仍存在)→ 重建符号链接,保住 tokentracker 等活链接;
    • 新机 / 目标已迁移 → 自动降级为文件副本,技能照常可用(结果里提示)。
  • 配置热生效:settings namespace dsh-syncsettings.yaml 用户层)覆盖 patch base,UI 或改文件均免重启。

存储后端扩展(MinIO / OSS 预留)

后端注册表在 lib/index.js 顶部(registerBackend / getBackend / listBackends):

registerBackend({
  id: 'minio',                    // 配置 `backend: minio` 即可路由到这里
  label: 'MinIO 对象存储',
  describe(cfg) { return { kind: 'object-store', ... } },
  async mirror({ source, dest, excludes, followSymlinks }, emit) {
    // dest 在此语义为对象键前缀;用 minio SDK 逐个 put / delete
  },
})

核心引擎不做任何存储假设——只调 backend.mirror(opts, emit)。本地 backend 已实现; minio/oss 配置块已 schema 化(Config.minio / Config.oss),UI 会显示为 「预留」并允许选中(选中后运行会给出明确的「后端未实现」错误)。

HTTP 路由(同源)

路由方法说明
/dsh-sync/statusGET生效配置 + 可用/预留后端 + 上次同步结果
/dsh-sync/runPOST立即同步;body { direction: 'export'|'import', dryRun: bool }(重入保护,忙时 409)
/dsh-sync/configPOST写入用户层配置(白名单键:backend/localRoot/excludes/followSymlinks)
# 预演导入(不改动任何文件,列出将发生的变化)
curl -X POST http://127.0.0.1:3080/dsh-sync/run \
  -H 'content-type: application/json' -d '{"direction":"import","dryRun":true}'

目录结构

lib/index.js       宿主半区:schema / 后端注册表 / 同步引擎 / webServer 路由 / settings ns
src/client/index.tsx 客户端源码(TSX → esbuild 打包)
scripts/build.mjs    客户端打包脚本(esbuild,产物提交到 lib/client.js)
assets/logo.svg      插件 logo(双向同步双箭头 + 中心配置点)
cordis.patch.yml.example  注册示例

开发

pnpm install
node scripts/build.mjs   # 重新打包 lib/client.js(改客户端后执行)

已知行为

  • 活跃会话的 sessions/*/session.jsonl.zstdstorages/* 持续写入,每次同步都会重拷——属预期。
  • 首次改宿主代码后需重启 DSH 才生效;客户端 bundle 改动刷新页面即可(带 rev 参数)。
  • 导入仅在「已用新版本导出过一次」(备份根里存在 .dsh-sync-manifest.json)后才会还原链接;旧备份可直接导入,只是没有链接元数据、按纯文件恢复。

License

MIT