🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

同步与备份 jeweis/dsh-sync

DeepSeek Harness
jeweis17 天前有提交已提供中文文档扫描:含敏感能力

用 WebDAV 跨设备同步配置与密钥,随时预览恢复历史备份

29.5/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/23 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add jeweis/dsh-sync
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:仅索引
是什么[目录]—
dsh 原生插件 · tool
暂无时间戳·判据 →
装得上吗[实装验证]—
本站尚未做安装检查
暂无时间戳·判据 →
安全吗[自动扫描]—
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
数据截至 2026/11/04·判据 →
还在维护吗[仓库]✓
活跃:最近一次提交在 17 天前
暂无时间戳·判据 →
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

读写/删除本地文件写入剪贴板(不计风险)发起外部网络请求
查看扫描证据(共 41 处,展示前 40 条)
  • 读取本地文件
    src/files.mjs:18
    const info = await lstat(current)
  • 删除本地文件
    src/files.mjs:53
    if (content === null) { try { await unlink(target) } catch (error) { if (error.code !== 'ENOENT') throw error }; return }
  • 写入本地文件
    src/files.mjs:54
    await mkdir(dirname(target), { recursive: true, mode: 0o700 })
  • 写入本地文件
    src/files.mjs:61
    await rename(temporary, target)
  • 删除本地文件
    src/files.mjs:64
    await unlink(temporary).catch(error => { if (error.code !== 'ENOENT') throw error })
  • 读取本地文件
    src/settings.mjs:54
    try { entries = await readdir(await safePath(home, 'profiles'), { withFileTypes: true }) }
  • 发起网络请求
    src/webdav.mjs:28
    const req = client.request(url, { method, signal: combined, headers: { Authorization: this.authorization, ...body ? { 'Content-Length': body.length }
  • 发起网络请求
    src/webdav.mjs:50
    const result = await this.request('PROPFIND', url, { body, signal, stage, headers: { Depth: '0', 'Content-Type': 'application/xml; charset=utf-8' }, l
  • 发起网络请求
    src/webdav.mjs:85
    const result = await this.request('MKCOL', directory, { signal, limit: 65536 })
  • 发起网络请求
    src/webdav.mjs:97
    const result = await this.request('PUT', this.object(id), { body: bytes, signal, headers: { 'Content-Type': 'application/octet-stream', 'If-None-Match
  • 发起网络请求
    src/webdav.mjs:106
    const result = await this.request('GET', this.object(id), { signal })
  • 发起网络请求
    src/webdav.mjs:113
    const result = await this.request('DELETE', this.object(id), { signal, headers: { 'If-Match': etag }, limit: 65536 })
  • 写入本地文件
    src/retention.mjs:24
    await mkdir(await safePath(home, 'config-vault'), { recursive: true, mode: 0o700 })
  • 删除本地文件
    src/retention.mjs:54
    if (await readManaged(home, path) === raw) await unlink(await safePath(home, path)).catch(error => { if (error.code !== 'ENOENT') throw error })
  • 删除本地文件
    src/retention.mjs:61
    if (raw && JSON.parse(raw).token === token) await unlink(await safePath(home, path))
  • 读取本地文件
    src/retention.mjs:92
    const entries = await readdir(await safePath(home, dir), { withFileTypes: true })
  • 写入本地文件
    src/restore.mjs:36
    await mkdir(await safePath(home, 'config-vault'), { recursive: true, mode: 0o700 })
  • 读取本地文件
    src/restore.mjs:41
    const saved = JSON.parse(await readFile(await safePath(home, LOCK), 'utf8'))
  • 删除本地文件
    src/restore.mjs:45
    await unlink(await safePath(home, LOCK))
  • 删除本地文件
    src/restore.mjs:49
    return () => unlink(resolve(home, LOCK))
  • 读取本地文件
    src/provider-transition.mjs:15
    const PACKAGE = JSON.parse(await readFile(new URL('../package.json', import.meta.url), 'utf8')).name
  • 读取本地文件
    src/provider-transition.mjs:36
    const bytes = await readFile(path)
  • 读取本地文件
    src/provider-transition.mjs:86
    const directories = await readdir(await safePath(home, 'profiles'), { withFileTypes: true }), profiles = []
  • 读取本地文件
    src/provider-transition.mjs:120
    const ownInfo=JSON.parse(await readFile(new URL('../package.json',import.meta.url),'utf8'))
  • 读取本地文件
    src/provider-transition.mjs:123
    inputs.push(['provider-module', module, hash(await readFile(module))])
  • 写入本地文件
    src/auto-backup.mjs:19
    await mkdir(await safePath(home, 'config-vault'), { recursive: true, mode: 0o700 })
  • 删除本地文件
    src/auto-backup.mjs:33
    if (await readManaged(home, LOCK) === raw) await unlink(path).catch(error => { if (error.code !== 'ENOENT') throw error })
  • 删除本地文件
    src/auto-backup.mjs:40
    if (raw && JSON.parse(raw).token === token) await unlink(path)
  • 写入本地文件
    src/sync-lock.mjs:6
    await mkdir(await safePath(home, 'config-vault'), { recursive: true, mode: 0o700 })
  • 删除本地文件
    src/sync-lock.mjs:18
    if (await readManaged(home, relative) === raw) await unlink(path).catch(error => { if (error.code !== 'ENOENT') throw error })
  • 删除本地文件
    src/sync-lock.mjs:22
    return async () => { const raw = await readManaged(home, relative); if (raw && JSON.parse(raw).token === token) await unlink(path) }
  • 发起网络请求
    src/sync-remote.mjs:12
    const result = await this.dav.request('GET', url, { signal, limit: 1048576 })
  • 发起网络请求
    src/sync-remote.mjs:20
    const result = await this.dav.request('PUT', url, { body: bytes, signal, limit: 65536, headers: { 'Content-Type': 'application/octet-stream', ...etag
  • 发起网络请求
    src/sync-remote.mjs:34
    const result = await this.dav.request('PUT', url, { body: Buffer.from('must not replace'), headers, signal, limit: 65536 })
  • 发起网络请求
    src/sync-remote.mjs:42
    if (latest) await this.dav.request('DELETE', url, { headers: { 'If-Match': latest.etag }, signal, limit: 65536 }).catch(() => {})
  • 发起网络请求
    src/client/controller.cjs:26
    constructor(fetcher = (...args) => fetch(...args)) {
  • 发起网络请求
    src/client/controller.cjs:41
    async read() { const host = await this.request('GET'); if (!validState(host)) throw new Error('operation-failed'); return host }
  • 发起网络请求
    src/client/controller.cjs:59
    const value = await this.request('POST', { ...payload, action, revision: before.host.revision })
  • 发起网络请求
    src/client/controller.cjs:72
    try { const answer = await this.request('POST', { action: 'list', revision: value.state.revision }); if (!Array.isArray(answer.snapshots) || !answer.s
  • 写入剪贴板
    src/client/recovery-view.cjs:58
    button(t('recoveryCopy'),false,async()=>{try{await navigator.clipboard.writeText(command);setCopyResult('recoveryCopied')}catch{setCopyResult('recover
扫描于 2026/11/4(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/cordis-plugin-include@deepseek-ai/dsh-client-connection@deepseek-ai/dsh-client-store@deepseek-ai/dsh-credentials-local@deepseek-ai/dsh-launch-environment@deepseek-ai/dsh-system-prompt@deepseek-ai/dsh-tools
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

DeepSeek Harness 同步与备份插件:通过 WebDAV 同步常用配置和 API Key,自动备份,并可预览、恢复历史配置。

README

由 DeepSeek 最新模型翻译生成
DSH Sync · 同步与备份 DeepSeek Harness 的跨设备配置同步与备份插件。用你自己的 WebDAV 存储同步常用配置、保留历史快照,需要时预览并恢复。 适用于 DeepSeek Harness 0.2.1-rc.2。目前支持 WebDAV,暂不支持 S3、GitHub 存储。 快速开始 1. 在 DeepSeek Harness 中打开 插件管理,点击 添加插件。 2. 在「输入插件的包名、GitHub 仓库地址或本地目录路径」输入框中,填写下面任意一种: npm 包名(推荐): @jeweis/dsh-sync GitHub 仓库地址: https://github.com/jeweis/dsh-sync 3. 点击 安装。安装完成后,在 已安装插件 中打开 同步与备份 右侧的启用开关。npm 包名使用所选安装源;刚发布的包若在镜像源找不到,可切换为 npm 官方源。GitHub 安装需要能访问 GitHub,并按 Harness 提示授权源码构建。 在哪里使用 安装并启用后,点击 DeepSeek Harness 左下角 更多 → 设置 → 同步与备份。 页面分为 连接存储、同步到其他设备、备份与恢复 三个页签,每次只显示一项任务。可以连接 WebDAV、选择同步内容、开启自动备份、查看备份记录和恢复预览。
展开完整文档(README 剩余 1 节)
DSH Sync · 同步与备份

DeepSeek Harness 的跨设备配置同步与备份插件。用你自己的 WebDAV 存储同步常用配置、保留历史快照,需要时预览并恢复。

适用于 DeepSeek Harness 0.2.1-rc.2。目前支持 WebDAV,暂不支持 S3、GitHub 存储。

快速开始

1. 在 DeepSeek Harness 中打开 插件管理,点击 添加插件。
2. 在「输入插件的包名、GitHub 仓库地址或本地目录路径」输入框中,填写下面任意一种:

npm 包名(推荐):

@jeweis/dsh-sync

GitHub 仓库地址:

https://github.com/jeweis/dsh-sync

3. 点击 安装。安装完成后,在 已安装插件 中打开 同步与备份 右侧的启用开关。npm 包名使用所选安装源;刚发布的包若在镜像源找不到,可切换为 npm 官方源。GitHub 安装需要能访问 GitHub,并按 Harness 提示授权源码构建。

在哪里使用

安装并启用后,点击 DeepSeek Harness 左下角 更多 → 设置 → 同步与备份。

页面分为 连接存储、同步到其他设备、备份与恢复 三个页签,每次只显示一项任务。可以连接 WebDAV、选择同步内容、开启自动备份、查看备份记录和恢复预览。超时、检查间隔等参数放在各部分的「更多设置」中,通常不用调整。无需编辑 YAML,也无需先运行终端命令;只有凭据扩展接入/回退与完整恢复需要按页面指引离线确认。

插件安装完成后,跨设备同步、API Key 同步和自动备份均需自行开启。

连接两台设备

在两台设备上分别安装插件,然后:

1. 在 连接存储 填写相同的 WebDAV 文件夹地址,然后开启 同步到其他设备 → 开启自动同步。
2. 在 选择同步内容 中选择需要的项目,点击 保存设置。「更多同步设置」中的 同步分组 通常保留 default,两台设备一致即可。
3. 在「同步状态」输入相同的 两台设备共用的同步口令,点击 解锁并检查更新。口令须为 12–1024 个字符,且与 WebDAV 密码不同。
4. 首次连接时核对差异:第一台设备点击 使用本机设置开始同步;新设备点击 接收云端设置。也可展开逐项比较;本机独有内容会保留。

之后默认每 3 分钟核对一次,也可手动点击「立即同步」。两台设备同时修改同一项时会提示选择,不会直接以最后上传者覆盖另一端。

| 内容 | 当前支持方式 |
| 主题、字体、字号和界面语言 | 支持的字段可自动同步并在线生效 |
| 默认模型及部分 DeepSeek 参数 | 支持的字段可自动同步并在线生效 |
| 供应商 API Key | 单独开启,仅加密同步,接收方式见下文 |
| 插件清单 | 显示差异,需要在 Harness 中手动安装或移除 |

同步作用于当前运行的配置(如 web 或 desktop),与「要备份的配置」独立选择。不同用途的配置请使用不同同步分组。会话、附件、OAuth 登录状态、MCP/技能文件和任意第三方插件配置不在当前同步范围内。

API Key 不想重复填写?

在两台设备分别开启 同时同步 API Key。支持 DeepSeek 与 pi-ai 中已绑定的 API Key;两端需先有对应的供应商配置,插件不会自动创建供应商。

- 受支持的 Key 记录:可自动双向同步。
- 引用型 Key(如供应商使用 DEEPSEEK_API_KEY):默认只加密上传,接收端提示在 Harness 手动配置。要让新设备自动接收、避免重复填写,请在 更多同步设置 → API Key 自动接收设置 中预览接入。

高级接入先预览变更,再按页面指引停止共享凭据存储的全部 Harness 进程,在终端确认切换并重启。退出仅发生在接入、回退或完整恢复时,日常同步和备份无需退出。 接入可安全回退,并保留接入后更新的 Key。步骤见 API Key 自动接收指南。

API Key 同步默认关闭,始终加密,不受备份加密开关影响。页面不显示 Key;缺失的 Key 不会清空另一台设备的 Key。

历史备份

在 备份与恢复 点击 立即备份,输入加密口令后点击 开始备份。要调整配置范围、保留份数或加密方式,展开 更多备份设置。备份包含插件依赖清单、profile 配置补丁及存在的锁文件,不包含凭据文件、会话、附件或已安装的 node_modules。

- 自动备份:可开启配置变更后自动备份;默认等配置稳定 30 秒,两次尝试至少间隔 5 分钟。
- 保留数量:默认保留本设备最近 30 份。仅在新备份校验成功后清理本设备有归属记录的旧快照,不清理其他设备快照。
- 加密:默认开启。可明确选择明文备份,但配置里直接填写的秘密值也会随文件明文保存。

加密口令需自行妥善保管,丢失后无法恢复加密数据。手动操作不保存口令;自动备份和同步的解锁仅对当前 Harness 进程有效,重启后需要重新解锁。

在新设备上恢复

1. 在新设备安装并启用插件,连接与旧设备相同的 WebDAV 文件夹,点击 保存设置。页面会查找已有备份。
2. 在 备份与恢复 点击 恢复备份,选择备份,输入这份备份的加密口令,再点击 检查并预览恢复。
3. 核对恢复内容;备份含多份配置时,选择其中一份。它将恢复到当前运行的配置,例如将旧设备的 desktop 配置带到新设备的 desktop。默认保留新设备已安装的插件版本和额外插件;所选配置的插件设置会被替换。
4. 若缺少插件,可点击 检查 npm 版本。核对名称和版本后,点击 确认安装此版本,由 Harness 安装,再重新检查。旧设备的本地插件需要先在新设备安装可信副本;不能把旧路径直接带过来。构建授权仍遵循 Harness 提示。
5. 检查通过后点击 生成离线恢复步骤,然后 复制恢复命令。此时只在本机加密暂存恢复任务,尚未替换配置文件。
6. 退出使用该配置位置的全部 Harness 窗口和后台进程,在系统终端运行复制的命令。输入口令(不会回显),核对变化并输入 确认恢复,再重新打开 Harness 检查。

只需运行一条命令,无需设置环境变量、复制确认码或再次连接 WebDAV。终端会重新检查文件;若准备后配置又有修改,会停止并要求重新预览。恢复前会保留加密回退副本。
新设备向导不会导入旧设备的锁文件、安装脚本、包管理策略或全局配置补丁,会保留本机启动方式。它恢复配置与插件清单,不包含聊天记录或凭据文件。API Key 仍通过独立、默认关闭的加密同步功能接收,不会因恢复备份而自动开启。

如需逐文件原样还原,在 恢复备份 向导中展开 高级:原样还原配置文件。这里仍使用原来的预览、确认码和离线 CLI 流程。这里的「离线」指停止相关 Harness 进程,不是断开网络。回退和中断处理见 恢复说明。

常见问题

测试连接成功,为什么备份失败? 测试只确认目录读取情况,写入和创建子目录还需要额外权限。填写 WebDAV 对外的共享目录路径,勿直接使用 NAS 内部磁盘路径;缺失目录会在备份时尝试逐级创建。

关闭设置页后还会同步吗? Harness 进程仍运行时会继续;退出 Harness 后停止,不会创建系统登录启动项。

能使用 HTTP 吗? 支持 HTTP 和 HTTPS。HTTP 会暴露连接上的 WebDAV 用户名和密码,优先使用 HTTPS。数据加密不等于连接加密。

同步为什么暂停? 先查看是否需要解锁、首次比较或处理冲突。设备同步要求 WebDAV 支持强 ETag 和条件写;不支持时仍可使用普通备份。

更多说明

- 双设备同步与支持范围
- 自动备份 · 快照保留策略
- 版本兼容与改名说明 · 品牌与数据兼容
- 开发、CLI 与验收说明 · 维护者发布流程

问题反馈:GitHub Issues。
预览分享卡片长什么样 ↓jeweis/dsh-sync
分享 · DeepSeek Harness Hub
jeweis/dsh-sync

用 WebDAV 跨设备同步配置与密钥,随时预览恢复历史备份

这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。
认领条目 →
回到顶部