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

数据备份与恢复 xiaoyuyu6420/dsh-backup

DeepSeek Harnessv0.13.4
xiaoyuyu642017 天前有提交已提供中文文档扫描:含敏感能力

一条命令备份、恢复、迁移 DSH 全部数据(~/.dsh):升级前快照、换机迁移(会话、插件、MCP、技能)、会话日志修复、进程外救援、凭据脱敏。

47.7/100
综合分
27
GitHub 星标
1,003
npm 周下载
—/5
用户评分

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

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add @xiaoyuyu6420/dsh-backup
npm 源 · @xiaoyuyu6420/dsh-backup 的发布者账号已校验与本仓库一致

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
dsh 原生插件 · platform
装得上吗
本站已在 dsh 0.2.1-rc.2 下真实安装成功
非静态推断
L5 · 运行时冒烟等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 17 天前
档位由哪些信号合成

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

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查✓ 自动检查通过
展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✓npm 包@xiaoyuyu6420/dsh-backup @ 0.13.4
✓Node 引擎要求 >=20 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/30 02:40:17

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

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

可执行外部命令读写/删除本地文件写入剪贴板(不计风险)发起外部网络请求
查看扫描证据(共 216 处,展示前 57 条)
  • 读取本地文件
    lib/index.js:361
    const v = JSON.parse(readFileSync(c, 'utf8')).version;
  • 读取本地文件
    lib/index.js:370
    const v = JSON.parse(readFileSync(createRequire(import.meta.url).resolve('@deepseek-ai/dsh/package.json'), 'utf8')).version;
  • 读取本地文件
    lib/index.js:384
    const v = JSON.parse(readFileSync(p, 'utf8')).version;
  • 读取本地文件
    lib/index.js:400
    const pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'));
  • 读取本地文件
    lib/index.js:435
    try { return existsSync(p); } catch { return false; }
  • 读取本地文件
    lib/index.js:1010
    return await readFile(read.spillPath, 'utf8');
  • 请求外部主机registry.npmjs.org
    lib/index.js:1202
    const res = await fetch(`https://registry.npmjs.org/${encodeURIComponent(SELF_META.name)}`, {
  • 发起网络请求
    lib/index.js:1202
    const res = await fetch(`https://registry.npmjs.org/${encodeURIComponent(SELF_META.name)}`, {
  • 删除本地文件递归
    lib/index.js:1403
    await rm(`${vaultDir}/${n}`, { recursive: true, force: true }).catch(() => {});
  • 写入本地文件
    lib/index.js:1414
    await mkdir(dirname(dst), { recursive: true });
  • 写入本地文件
    lib/index.js:1415
    await copyFile(src, dst);
  • 删除本地文件
    lib/index.js:1469
    await Promise.all(names.map((n) => unlink(`${dir}/${n}`).catch((err) => {
  • 写入本地文件
    lib/index.js:1479
    await rename(`${dir}/${srcName}`, `${dir}/${dstName}`);
  • 写入本地文件
    lib/index.js:1572
    await mkdir(dirname(p), { recursive: true });
  • 写入本地文件
    lib/index.js:1573
    await writeFile(p, content, 'utf8');
  • 写入本地文件
    lib/index.js:1578
    await mkdir(dirname(p), { recursive: true });
  • 删除本地文件
    lib/index.js:1769
    await rm(out, { force: true }).catch(() => {});
  • 删除本地文件
    lib/index.js:1788
    await rm(tmpEnc, { force: true }).catch(() => {});
  • 删除本地文件
    lib/index.js:1953
    await rm(`${root}/${GITHUB_TOKEN_FILE}`, { force: true });
  • 删除本地文件
    lib/index.js:2143
    await unlink(staging).catch(() => {});
  • 发起网络请求
    lib/index.js:3178
    const res = await fetch(url, { signal: ctrl.signal, headers: { accept: 'application/json' } });
  • 发起网络请求
    lib/index.js:3249
    const res = await fetch(entry.url, { signal: ctrl.signal });
  • 执行外部命令来自配置/变量
    lib/index.js:5486
    const child = spawn(dsh, ['web', '--profile', name], { detached: true, stdio: 'ignore', cwd: profilesDir() });
  • 请求外部主机json-schema.org
    lib/client.js:67
    Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.`)}for(let a of t.seen.entries()){let s=a[1];if(r===a[0]){n(a);continu
  • 请求外部主机json-schema.org
    lib/client.js:67
    Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.`)}for(let a of t.seen.entries()){let s=a[1];if(r===a[0]){n(a);continu
  • 请求外部主机json-schema.org
    lib/client.js:67
    Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.`)}for(let a of t.seen.entries()){let s=a[1];if(r===a[0]){n(a);continu
  • 请求外部主机json-schema.org
    lib/client.js:67
    Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.`)}for(let a of t.seen.entries()){let s=a[1];if(r===a[0]){n(a);continu
  • 请求外部主机json-schema.org
    lib/client.js:67
    Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.`)}for(let a of t.seen.entries()){let s=a[1];if(r===a[0]){n(a);continu
  • 请求外部主机json-schema.org
    lib/client.js:67
    Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.`)}for(let a of t.seen.entries()){let s=a[1];if(r===a[0]){n(a);continu
  • 发起网络请求
    lib/client.js:67
    Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.`)}for(let a of t.seen.entries()){let s=a[1];if(r===a[0]){n(a);continu
  • 写入剪贴板
    lib/client.js:67
    Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.`)}for(let a of t.seen.entries()){let s=a[1];if(r===a[0]){n(a);continu
  • 执行外部命令来自配置/变量
    rescue/rescue.mjs:83
    const r = spawnSync(argv[0], argv.slice(1), { cwd, encoding: 'buffer', maxBuffer: 256 * 1024 * 1024 });
  • 读取本地文件
    rescue/rescue.mjs:100
    createReadStream(absPath).on('data', (d) => h.update(d)).on('error', reject).on('end', () => resolve(h.digest('hex')));
  • 执行外部命令来自配置/变量
    rescue/rescue.mjs:683
    spawn(cmd, args, { detached: true, stdio: 'ignore' }).unref();
  • 读取本地文件
    lib/encrypt.js:181
    createReadStream(inPath),
  • 写入本地文件
    lib/encrypt.js:184
    createWriteStream(outPath, { mode: 0o600 }),
  • 删除本地文件
    lib/encrypt.js:187
    await rm(outPath, { force: true }).catch(() => {});
  • 读取本地文件
    lib/encrypt.js:226
    createReadStream(inPath),
  • 写入本地文件
    lib/encrypt.js:228
    createWriteStream(outPath, { mode: 0o600 }),
  • 删除本地文件
    lib/encrypt.js:231
    await rm(outPath, { force: true }).catch(() => {});
  • 写入本地文件
    lib/zip.js:191
    const ws = createWriteStream(outputPath);
  • 读取本地文件
    lib/zip.js:199
    const info = isBuffer ? null : await fsStat(entry.sourcePath);
  • 读取本地文件
    lib/zip.js:213
    const rs = createReadStream(entry.sourcePath);
  • 写入本地文件
    lib/zip.js:353
    await mkdir(dirname(target), { recursive: true });
  • 写入本地文件
    lib/zip.js:354
    const ws = createWriteStream(target);
  • 读取本地文件
    lib/oplock.js:46
    return JSON.parse(await readFile(lockPath, 'utf8'));
  • 写入本地文件
    lib/oplock.js:57
    await mkdir(dirname(lockPath), { recursive: true });
  • 删除本地文件
    lib/oplock.js:68
    await rename(tmp, lockPath).catch(async (err) => { await rm(tmp, { force: true }).catch(() => {}); throw err; });
  • 写入本地文件
    lib/oplock.js:68
    await rename(tmp, lockPath).catch(async (err) => { await rm(tmp, { force: true }).catch(() => {}); throw err; });
  • 删除本地文件
    lib/oplock.js:81
    await rm(lockPath, { force: true }).catch(() => {});
  • 删除本地文件
    lib/oplock.js:96
    await rename(tmp, lockPath).catch(async (err) => { await rm(tmp, { force: true }).catch(() => {}); throw err; });
  • 写入本地文件
    lib/oplock.js:96
    await rename(tmp, lockPath).catch(async (err) => { await rm(tmp, { force: true }).catch(() => {}); throw err; });
  • 删除本地文件
    lib/oplock.js:104
    await rm(lockPath, { force: true }).catch(() => {});
  • 删除本地文件
    lib/oplock.js:119
    await rm(lockPath, { force: true }).catch(() => {});
  • 发起网络请求
    lib/sync-channels.js:57
    res = await fetch(url, { method: 'PUT', headers: h, body, signal, redirect: 'follow' });
  • 发起网络请求
    lib/sync-channels.js:115
    await fetch(dir, { method: 'MKCOL', headers: { authorization: auth }, signal });
  • 发起网络请求
    lib/sync-channels.js:144
    res = await fetch(url, { method: gistId ? 'PATCH' : 'POST', headers, body: JSON.stringify(payload), signal });
扫描于 2026/11/3(0 天前) · 范围 入口闭包 + 全包扫描 · 来源 npm 发布包
涉及外部主机:registry.npmjs.org、json-schema.org、github.com

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

依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-commands@deepseek-ai/dsh-fs@deepseek-ai/dsh-settings@deepseek-ai/dsh-subprocess@deepseek-ai/dsh-tools@deepseek-ai/dsh-typert-protocol@deepseek-ai/schemastery
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

界面预览

2 张 · 点击查看大图

功能亮点

  • 一键备份恢复全部数据
  • 升级快照
  • 会话日志体检修复
v0.14.22026-10-30
· dsh-backup 0.14.2 · 一句话 对 0.14.0/0.14.1 做了两轴(规范 + 规格)独立复核,本版修掉复核发现的问题:加密不再整包入内存、写盘改为临时文件后原子替换,并补齐文案/契约/守门测试。 · 修了什么 数据安全(最高优先级) · 加密与解密改为分块流式(encryptFile / decryptFile),归档不再整包入内存 —— 大归档不再撞 Buffer 上限。 · 写盘一律「先写临时文件 → rename 原子替换」:加密时明文原件在替换成功前完好;中途崩溃/OOM 只会留下完整明文或完整密文,不会出现半截密文。解密失败会删掉半截明文再抛人话报错。 · 恢复侧解密同样流式,不再先 readFile 整包密文。 · 回归断言(新增 7 条):无 .enc-*.tmp 残留、边车 ciphertextSize 与实际密文一致、口令错误后无 .decrypt-* 半截明文、6MB 多块往返一致。 契约与守门 · setGithubToken 补上客户端 descriptor —— 面板早就在调它(src/tab.jsx 的 GitHub token 输入),但没有 descriptor,实际是断链。 · 新增反向断言:面板调用的每个方法都必须在 descriptors 里(此前只断言 descriptor ⊆ panel,#97 的镜像面没守住)。 · redactSyncChannel 补花括号:此前 out.username / out.passwordSet 会无条件执行,导致 s3 / gist 通道在 syncStatus 里出现假的 passwordSet: false。 · 移除生产路径里的测试故障注入钩子(DSH_BACKUP_IMPORT_FAIL,无任何测试使用)。 诚实的文案 · 聊天记录导入的中英文案补上 Codex(Claude Code / Codex,路径含 ~/.codex/sessions)。 · 导入预览不再承诺「界面上逐项选择覆盖」(面板实际固定「保留本机」);改为如实写「默认保留本机,不改动已有文件」。 · README / 对齐文档把多通道同步写清为单向推送(跨机恢复走 GitHub 通道拉取或 ZIP 导入),并标注 Gist 单文件 10MB 上限。 · About 卡补「反馈问题」入口(直接开 issue)。 · rescue sessions repair --fix --map 会改写会话 header 的 cwd(动用户日志),现在必须显式加 --yes 才执行,不加时拒绝并零写入。 · scripts/acceptance-notes.md 里陈旧的验收数字(578/66、411/32)同步为当前值。 · 验收 | 套件 | 结果 | |---|---| | smoke(宿主零依赖桩) | 596/596(Windows 583) | | settings | 47/47 | | client bundle | 62/62(44 个端点) | | 真机 e2e(DSH 0.2.1-rc.2,从打包产物安装) | 70/70 | · 装 dsh plugin --profile web add @xiaoyuyu6420/dsh-backup@0.14.2 · 复核中确认但本版未动的项 · 多通道同步仍是单向推送(WebDAV / S3 / Gist 无 pull/restore;只有 GitHub 通道能拉取)。要不要补拉取能力,是功能决策,不是补丁。 · 配置导入的「逐项决策 / 路径 remap / 市场节段选择」后端支持、面板未接 → 本版只把文案改诚实,没做界面。 · 若干坏味道(重复的 zip 头解析、三处存档名→日期解析、BackupTab 1400 行十类职责)按重构处理,不放进补丁版。
v0.14.12026-10-30
· dsh-backup 0.14.1 · 一句话 0.14.0 的 npm 包在 Codex 支持合并之前就已由 tag 自动发布;0.14.1 把「跨工具聊天记录导入」的双来源(Claude Code / Codex)补齐到 npm 版本,并同步验收数字。代码面与 v0.14.0 的 GitHub tag 一致,只是 npm 轨道对齐。 · 装 dsh plugin --profile web add @xiaoyuyu6420/dsh-backup@0.14.1 旧版本迁移(0.13.x → 0.14.x)与 0.14.0 相同:默认目录 ~/Desktop/dsh-backups → ~/Desktop/DSH Backups 同盘自动改名,显式配置不动。 · 本版相对 npm 0.14.0 的新增 · Codex 聊天记录导入:扫 ~/.codex/sessions/**/rollout-*.jsonl,解析 session_meta / response_item(message / reasoning / function_call / custom_tool_call 及其 output)/ turn_context;函数调用与结果按 call_id 配对成 tool/call + tool/result;developer 指令与仅加密的推理跳过并计数。 · 导入目标仍是新会话(sessions/_no-cwd//),原 Codex 数据零改动;流程为 扫描 → 预览(消息/事件/跳过计数)→ 确认。 · 宿主级验收:导入产物通过宿主严格模式解码(recovery:'strict')与表面投影(能渲染成 user / assistant / tool 三类消息)。 · 验收 | 套件 | 结果 | |---|---| | smoke(宿主零依赖桩) | 587/587(Windows 574) | | settings | 47/47 | | client bundle | 60/60 | | 真机 e2e(DSH 0.2.1-rc.2,从打包产物安装) | 70/70 | · 已知说明 · npm 上的 0.14.0 是 0.14.0 核心大版本(备份目录 UX / 面板重构 / 加密 / 同步 / 市场 / Rewind / Claude Code 导入),不含 Codex 导入;需要 Codex 导入请装 0.14.1。 · GitHub Release v0.14.0 附带的 tgz 已含 Codex 导入。
v0.14.02026-10-30
· dsh-backup 0.14.0 · 一句话 一条命令备份、恢复与迁移 DeepSeek Harness(DSH)的全部数据——升级翻车、误删、换机,都能找回来;凭据默认不出本机,还能再上口令加密。 · 为什么现在升级 · 怕升级翻车:宿主版本一变就自动拍升级前快照,坏了随时回滚。 · 怕误删 / 改坏:恢复前先预览,当前数据先自动快照,失败自动回滚。 · 怕换机重来:单文件 ZIP 导出/导入 + 本地插件迁移 + WebDAV / S3 兼容 / Gist 多通道同步。 · 怕凭据上云:API Key / Token 默认脱敏,明文只留本机 vault;可选口令加密(scrypt + AES-256-GCM)。 · 怕看不懂:面板重构成三个 Tab(备份 / 恢复 / 设置),首启三步引导,主按钮只有一个「立即备份」。 · 0.14.0 新增 1. 备份目录 UX - 默认 ~/Desktop/dsh-backups → ~/Desktop/DSH Backups - 从未配置过目录的用户升级后首次启动同盘自动改名(原子、不丢备份);显式配置过的不动;失败继续用旧目录 - 每次备份在根目录写「使用说明.txt」:每个文件是什么 + 三条恢复路径 2. 面板重构:三 Tab + 首启引导 + 分类型 chips + 文案去术语 + 响应式 3. 备份能力:口令加密备份、单文件 ZIP 导出/导入(节段预览 → 冲突默认保留 → 自动快照 → 失败回滚)、本地 link:/file: 插件迁移 4. 同步与运维:WebDAV / S3 兼容 / Gist 多通道、GFS 月/年保留、操作锁 + 残留锁回收、磁盘占用报告 + 分级清理、每周调度 5. 生态:配置市场、从 Claude Code / Cursor / Codex 导入技能与全局指令(MCP 只检测报告)、Profiles 管理、会话 Rewind 分叉、About、agent 工具 6 个、离线 CLI(reinstall / sessions repair / recover-stale-lock) 6. 兼容:DSH 0.2.1-rc.2 真机 e2e 70/70;peers/engines 仍覆盖 0.2.1 列车,下一边界 0.3.0 7. 跨工具聊天记录导入:把 Claude Code / Codex 的会话导入为新的 DSH 会话(扫描 → 预览 → 确认;原数据零改动,仅文本与工具调用/结果)——导入产物经宿主自带解码器严格解码 + 表面投影双重验证 · 老版本迁移 · 0.13.x → 0.14.0:旧默认目录自动改名;旧归档(无边车 / 0.6.x)照常校验恢复;旧设置 redact:'none' 自动归一化 · 升级前建议先 /backup 一次(插件也会自动留 dsh-pre-upgrade- 快照) · 安装 dsh plugin --profile web add @xiaoyuyu6420/dsh-backup · dsh-backup 0.14.0 dsh plugin --profile web add github:xiaoyuyu6420/dsh-backup 桌面端(DSH Desktop):应用内「设置 → 插件 → 添加插件」,粘贴 npm 包名 / GitHub 地址 / 本地 tarball 绝对路径。 · 安全 · 凭据默认脱敏:不进归档、不进同步;明文只在本机 vault/(0700/0600) · 可选加密:口令只经内存传入,不落盘、不进日志 · 恢复:先快照、先预览、失败回滚;从备份目录到救援控制台全程仅本机 · 验收 | 项 | 结果 | |---|---| | smoke(宿主零依赖桩)| 587/587(Windows 574)| | settings seam | 47/47 | | client bundle | 60/60 | | 真机 e2e(DSH 0.2.1-rc.2)| 70/70 | --- · English (short) dsh-backup 0.14.0 — one-command backup, restore and migration for DeepSeek Harness. New: friendlier backup folder (~/Desktop/DSH Backups) with an auto-generated guide, three-tab panel, password-encrypted backups, single-file ZIP export/import with preview + roll
数据来自仓库的 GitHub Release,可能与插件实际版本不一致。

README

由 DeepSeek 最新模型翻译生成
dsh-backup Listed on DSH Directory 你所有的 DeepSeek Harness(DSH)工作数据都在一个目录里:~/.dsh。一次升级失败、一次误删、一次换电脑——没有备份,会话、设置、技能全没了。dsh-backup 用一条命令把它们找回来。 dsh plugin --profile web add @xiaoyuyu6420/dsh-backup # 安装 重启 dsh web,然后输入: /backup # → 一份带校验的备份落在 ~/Desktop/dsh-backups/ v0.9.0 全新安装的真实输出: 备份完成: dsh-20260826-195150036.tar.gz sha256: 8f9ae6322ef782d21554981cf4547220d5bb3e64d7964a883317415ad54e3cbb 轮换删除 0 份(保留 7 份) 不想敲命令也行:dsh web → 设置 → 插件 → 备份 里有可视化面板——列备份、校验、恢复、删除、改设置,全都立即生效不用重启。
展开完整文档(README 剩余 1 节)
dsh-backup

Listed on DSH Directory

你所有的 DeepSeek Harness(DSH)工作数据都在一个目录里:~/.dsh。一次升级失败、一次误删、一次换电脑——没有备份,会话、设置、技能全没了。dsh-backup 用一条命令把它们找回来。

dsh plugin --profile web add @xiaoyuyu6420/dsh-backup # 安装
重启 dsh web,然后输入: /backup # → 一份带校验的备份落在 ~/Desktop/dsh-backups/

v0.9.0 全新安装的真实输出:

备份完成: dsh-20260826-195150036.tar.gz sha256: 8f9ae6322ef782d21554981cf4547220d5bb3e64d7964a883317415ad54e3cbb 轮换删除 0 份(保留 7 份)

不想敲命令也行:dsh web → 设置 → 插件 → 备份 里有可视化面板——列备份、校验、恢复、删除、改设置,全都立即生效不用重启。

备份面板

它替你挡掉哪些事

| 你担心的 | dsh-backup 做的事 |
| 「升级把环境搞坏了」 | 宿主版本一变就自动拍 dsh-pre-upgrade- 快照——放心试新版,坏了随时回滚 |
| 「我误删 / 改坏了东西」 | /backup restore latest --dry-run 先预览要恢复什么再动手;恢复失败自动回滚并给出结果回执 |
| 「DSH 根本起不来了」 | 每次备份都会往备份目录放一个零依赖的救援控制台(dsh-rescue / rescue.mjs,或双击「点我恢复」)——不依赖 DSH 的网页版恢复界面 |
| 「API Key 会被传到云上吗」 | 凭据默认脱敏,不进备份包;明文只存本机 vault,永不离开这台机器 |
| 「会话日志损坏了」 | /backup doctor 体检并从备份定点修复;损坏文件先隔离再入档,防止轮换把好副本也带走 |
| 「升级后老会话打不开了」 | /backup migrate-check 迁移预检:升级前静态扫描全部会话,预测哪些会被新宿主拒绝、挂在哪条规则;旧版扁平凭据文件在宿主改写前自动存底 |
| 「换新电脑了」 | GitHub 同步:/backup github pull 拉回云端备份,restore --sync-deps 顺手重装插件 |
| 「备份悄悄坏了没人知道」 | 每份归档带 sha256,/backup verify all 随时体检;每日/每周分级保留,留得住有用的历史 |
| 「我会忘记备份」 | /backup auto 12——每 12 小时自动跑,重启不中断,旧副本自动轮换(默认保留 7 份) |

遇到具体报错? 按症状与报错原文查的排错手册:故障排查(会话打不开、29 字节空包、面板消失、Token 按钮报错、换机迁移……各条的版本与修法都写明)。

备份设置

安装

要求:macOS / Linux / Windows 10+(自带 tar),DSH 0.1.1-rc.2+(0.1.1 / 0.1.2 / 0.1.5 / 0.1.6 / 0.1.7 列车均已实测,0.2.0 列车自 0.13.2 起支持;当前兼容状态见 兼容性矩阵)。

dsh plugin --profile web add @xiaoyuyu6420/dsh-backup
或者直接从 GitHub 安装:
dsh plugin --profile web add github:xiaoyuyu6420/dsh-backup

装完重启 dsh web 后插件才生效。

安装时可能刷出 ✕ missing peer @deepseek-ai/... 警告,属预期现象:这些 peer 包由 DSH 宿主在运行时提供,不装在 profile 目录里。只要命令以 Done 结尾就是装成功了。

快速上手

1. 按上面装好插件,重启 dsh web
2. 输入 /backup
3. 搞定 —— 备份出现在 ~/Desktop/dsh-backups/,文件名带时间戳,旁边一份 .sha256 想定时自动跑?/backup auto 12(每 12 小时一次;off 关闭,status 看状态)。

命令速查

| 场景 | 命令 |
| 立即备份 | /backup |
| 分类型备份(只备份选中类型) | /backup --types skills,sessions(可选:credentials·mcp·skills·sessions·settings·profiles;--only 同义) |
| 定时备份(重启不中断) | /backup auto 12 · off · status |
| 恢复(先预览) | /backup restore latest --dry-run |
| 正式恢复 | /backup restore latest |
| 分类型恢复(merge,不动其他类型) | /backup restore <归档> --types skills |
| 列出备份 | /backup list |
| 校验完整性 | /backup verify [前缀\|all] |
| 会话日志体检/修复 | /backup doctor · --repair [前缀\|latest] |
| 升级前迁移预检 | /backup migrate-check |
| DSH 起不来时自救 | 双击备份目录里的「点我恢复」,或 dsh-rescue / node rescue.mjs |
| 删除 / 保留策略 | /backup delete <前缀\|latest> · /backup --keep N(默认 7) |

分类型备份

只想备份/恢复某几类数据?--types(或 --only)按内容类型子集操作,可选类型:credentials(凭据/api key)、mcp(MCP 配置)、skills(技能)、sessions(会话)、settings(设置)、profiles(插件 profiles)。

- 备份:/backup --types skills,sessions 生成 dsh-t- 前缀的子集归档,与全量备份分开轮换、互不挤占保留份数
- 恢复:/backup restore <归档名> --types skills 只把 skills 合并回现有 ~/.dsh(先 --dry-run 预览;覆盖的现有文件自动留档 .pre-merge-*),其他类型完全不碰
- 凭据类型特殊:--types credentials 会把 api key 明文打进归档(默认全量备份是脱敏的)——这类归档绝不进 GitHub 同步,仅建议本机保存或手动拷到新机
- 安全护栏:分类型归档不带 --types 直接整包恢复会被拒绝(防止误覆盖丢数据);rescue 救援通道同样不列、不整包恢复它们
- 面板(Settings → 插件 → 备份)同样支持:备份按钮下方勾选类型;分类型归档在独立分区展示与恢复

换新电脑

前提:旧电脑配过 GitHub 同步(配置方法)。

1. 新电脑装好插件,配置里填同一个 githubRepo
2. /backup github pull —— 拉回云端备份
3. /backup restore latest --sync-deps —— 恢复并重装插件依赖
4. 重启 dsh

常见问题

API Key / 密码会进备份包吗? 不会。已知的凭据文件打包前会脱敏,明文留在本机 vault 里不离开这台机器;恢复时自动还原。

到底备份了什么? ~/.dsh 下的全部——会话、设置、技能、插件配置——减去你配置的排除模式和 node_modules。

我把 ~/.dsh 搞坏了,dsh 都启动不了,还有救吗? 有——这正是救援通道的用途。每次备份都会往备份目录写 rescue.mjs 和双击启动器(macOS .command / Windows .bat / Linux .sh)。它只用普通 Node 就能跑,不需要 DSH,起一个本地网页让你浏览和恢复备份。

升级后老会话打不开了怎么办? 先别再点开它。运行 /backup migrate-check:静态扫描全部会话日志,告诉你哪些会话会被新宿主拒绝、挂在哪条规则(subagent descriptor 旧版本、插件注入的历史事件等),并检查文件系统硬链接支持。升级前先 /backup 拍一份,坏掉的会话可用 /backup doctor --repair 从更早的归档定点修复。

支持 Windows 吗? 支持——Windows 10+(用系统自带 tar),救援启动器是 .bat 文件。

备份默认放哪? ~/Desktop/dsh-backups/——在面板(设置 → 插件 → 备份)里随时可改,立即生效不用重启。

反馈

用过吗?哪里坏了、缺什么、喜欢什么,都欢迎说——反馈直接决定路线图:

- 💬 分享反馈(GitHub Discussions)
- 🐛 报告问题

更新日志

最近的版本

- 0.13.4 —— 元数据版(无代码与行为变更):npm 描述与关键词对齐检索用词——补入「迁移 / 换机 / 插件 / MCP / 技能 / 会话 / 工作区」等,让"搬家换机、升级翻车"场景的人在 npm 搜索里能找到本插件。功能、归档格式、设置项、RPC 与 0.13.3 完全一致;升级到本版与停留在 0.13.3 在行为上没有任何区别。
- 0.13.3 —— 修复三条真实用户报障 + 两个自建缺陷,全部在四条宿主列车(0.1.5-rc.3 / 0.1.7-rc.2 / 0.2.0-rc.2 / 0.2.1-alpha.1)真机 e2e 各 41/41 复验:① 含附件的归档恢复全链路不可用(#112,@zevs281):DSH 附件库用硬链接(tar 记为 h 条目),而恢复校验器只放行 -/d——0.13.2 及更早对这类归档的完整恢复/dry-run/分类型合并/doctor 修复一律拒绝。修法:条目与目标都在备份根内的硬链接放行(符号链接、设备仍拒)。② 大归档恢复被误拒(#119,@Yoshino-JF):归档清单超过宿主 subprocess 的 spill 上限时,宿主会丢弃 spill 文件、只留 8 KB 尾窗,校验器把「断在文件名中间的碎片」当成不安全条目 → 整包拒绝(备份成功、verify 报完整、只在恢复时炸)。修法:清单改走原始流逐行校验(无上限,发现违规立即终止)。③ doctor/migrate 看不见 v4 会话日志(#117,@xiuwufangoc-design):宿主 0.1.7 起会话格式为 v4(session.v4.jsonl.zstd),而文件名与校准代写死到第 0 代/v3——体检与迁移预检一份都扫不到。修法:按宿主同源形态匹配文件名、校准代推进到 v4、更新代只提示。④ 一键更新跨不过 minor(#115):pnpm update 只在声明范围内升级,跨 minor 停在旧版且回执谎报成功。修法:update --latest + 跑完读回 profile 内真实版本核对。⑤ 迁移预检误报(#113,@zevs281):未知 source.kind 从「判打不开」降级为提示,名单对齐宿主权威集合(真机曾把 81/82 份健康日志误报)。
- 0.13.2 —— 适配 dsh 0.2.0 列车:peers/engines 追加 ^0.2.0-rc.1(宿主自 0.1.7-rc.1 起有安装期兼容闸门,不覆盖会被拒绝安装);修复 0.1.7 起失效的设置表单(宿主改从条目 Config schema 派生表单且只认 volatile 字段——本插件导出 Config 并逐字段 .volatile(),设置卡片恢复可读可写);修复 Windows 调度器启动卡死(#103:流式哈希 + 启动宽限 + 尝试锚点落盘);review P2 债清偿与产品内 Star 入口。
- 0.13.1 —— 修复两个面板问题(均感谢用户报告):① 0.1.6+ 宿主上面板标签静默消失(#94,@jackovibe):宿主 0.1.6 起要求客户端 Remote 贡献的 strict codec 带 create() 惰性工厂(旧版只读 schema),缺失时 $mount 在校验阶段抛错且只有 console 日志——标签页因此永不注册。修法:strictCodec() 同时提供 schema 与 create(),两代宿主共用同一 zod 实例;$mount 改为声明式等待 remote 服务就绪(0.1.6 客户端模块按依赖图结算);并新增 BackupTabFallback 降级标签页——万一挂载失败会在面板位置给出可见提示与命令指路,不再静默消失。peers/engines 追加 ^0.1.6-alpha.1 || ^0.1.7-alpha.1(0.1.6-alpha.2 / 0.1.7-alpha.2 / 0.1.7-rc.1 / 0.1.7-rc.2 实机验证通过)。② 「GitHub Token」保存按钮报错(#97,@CheeseTJ):客户端 panel 代理漏接了 setGithubToken(该 RPC 0.12.0 加入宿主半时即漏,因当时面板无入口而潜伏两版)。修法:补接该行,并给 smoke-client 加「panel 面必须与贡献 descriptors 一一对应」的防漏断言。
- 0.13.0 —— 更新感知 + 一键更新(#A+B):① /backup check-update 与面板「插件更新」卡——查 npm 最新版(8s 超时、断网静默降级,绝不阻断运行),发现新版即出现「更新到 x.y.z」按钮;设置项 updateCheck(默认关)开启后打开面板自动静默检查一次(本插件不联网上报,检查只读 registry)。② /backup update [--profile 名] 一键更新——更新前自动留 dsh-pre-upgrade- 升级前快照(失败可 /backup restore 回滚),再走官方 dsh plugin --profile <名> update(pnpm 语义,插件不自己覆写依赖文件),完成提示重启 dsh web 生效。说明:宿主在启动时结算插件 Loader 树、插件是 profile 的 pnpm 依赖,运行中热替换(不重启生效)在宿主现行架构下不可行——一键更新 + 重启是此架构下的最佳形态。
- 0.12.2 —— 修复 Windows 数据安全隐患(#88,感谢 @Liuyeyuyangy0 出色的报告):DSH_HOME 位于盘符根目录(如 D:\dsh_data)时,求父目录的字符串截取退化成裸盘符 D:,tar -C D: 在 bsdtar/GNU tar 下必然失败——而 tar 失败前已创建归档文件,留下 29 字节空壳被面板当正常备份列出(无 .sha256/.meta.json,静默零可用备份;恢复、doctor 修复、rescue 救援通道同样中招)。备份/恢复/修复/救援共 7 处 tar -C 统一改传补过分隔符的父目录;paths() 对 DSH_HOME 补上与 HOME 一致的尾斜杠归一化(尾斜杠曾让 tar 位置参数变空串、产出 0 字节坏包);tar 失败路径删除空壳归档再抛错,失败不再静默。smoke 新增场景 28(四种路径布局断言 + 尾斜杠真实备份 e2e)。归档格式、设置项、RPC 均不变。
- 0.12.1 —— 修复 client bundle 顶层 var module / var exports 泄漏为全局变量(#85,感谢 @geyonder 报告):CJS shim 移入 __ModuleLoader__.load factory 体内,不再创建 window.module——此前会把 Monaco 的 AMD loader(dsh-vscode-mode 等)误判成 Node 环境并破坏同页插件。冒烟测试新增经典脚本全局泄漏回归断言(vm.runInContext)。纯 client 半区修复,node 侧行为与归档格式不变。
- 0.12.0 —— 迁移安全网第一弹,对准官方社区集中爆发的「升级后老会话打不开」(#6151/#6297/#6355):① /backup migrate-check 迁移预检——升级前静态扫描全部代会话日志(v0/v1/v2/v3),预测哪些会话升完会打不开、挂在哪条规则(descriptor v2、permission/preset origin、冻结清单外事件类型、自定义来源 kind、seq 漂移、文件名代际不一致……规则烤入自宿主 0.1.5-rc.2,摘要如实标注覆盖边界),并探测文件系统硬链接支持(exFAT 上宿主发布会失败的 #6358 场景);② 凭据哨兵——旧扁平布局的 .credentials.yaml 会被宿主原子替换成 version:1(不可逆),检测到即先自动存底 vault 再让宿主动它。③ GitHub token 面板直配——设置面板(或 /backup github token <token>)直接粘贴保存,存本机备份目录 github.token(0600,不进归档、不进 GitHub 同步),优先于环境变量,跨机恢复后重填。另:新增 engines.dsh 声明(插件市场的兼容卡片读取它)。
- 0.11.3 —— 跟进 dsh 0.1.5 列车:peerDependencies 追加 ^0.1.5-rc.1(0.11.2 在 0.1.5 宿主上会报 peer 警告)。兼容实测:宿主 0.1.5-rc.2 真机 e2e 32/32;六个 node 侧 peer 包 rc.1↔rc.2 逐字节相同(tarball diff),client 包列车未动——本次升列车零适配面;跨列车原地升级 e2e(rc.1 宿主 + 0.11.2 → rc.2 宿主 + 0.11.3)14/14,设置与归档无损。顺带修了升级 e2e 脚本自身的一个坑:新版期望版本从写死改为从 tarball 动态推导,换版本对不再改脚本。
- 0.11.2 —— doctor 行级 SessionHeader 校验对齐宿主 isHeaderLine(闭环 0.11.0 已知遗留):补 version/createdAt/delegationDepth 类型与非负安全整数三连(含 -0 拒绝)、seedLength/origin/agentPreset 可选分支、退役字段 sandboxMode/approvalPolicy——宿主拒载的 header 不再被误报健康。对照双列车宿主编译产物逐字段验证(rc.1 为严格超集),独立复核结论 ALIGN;测试套新增 11 种坏 header 负样本 + 修复往返。
- 0.11.1 —— 适配 dsh 0.1.2-rc.1:跟随 @deepseek-ai/dsh-settings 移除 settingsNamespace(改用普通 dsh-backup 命名空间注册——取值完全一致,原地更新后设置、备份与旧归档全部无损),支持 Web 强制鉴权(303 + HttpOnly cookie),peer 范围放宽为 ^0.1.1-rc.2 || ^0.1.2-rc.1。双列车真宿主 e2e 各 32/32 通过,另做了 0.11.0 → 0.11.1 原地升级测试(设置保留、旧归档可恢复)。
- 0.11.0 —— doctor 容器契约校验:首帧必须解出「恰好一行 header、单个换行结尾」(字节精确,对齐宿主读端)。单帧重写、首帧多余空行、缺行尾、skippable 帧现在都会判损坏(此前报健康但宿主拒载);救援台同步。来自 deepseek-harness 官方讨论区 #1047 的社区审计。
- 0.10.0 —— 分类型备份:只备份需要的部分(/backup --types skills,sessions),按类型 merge 恢复(/backup restore <归档> --types skills);类型归档独立轮换不挤全量配额。含凭据的类型归档永不进 GitHub 同步,跨机护栏不变。
- 0.9.1 —— 面板新增反馈入口;README 重做。六路 agent UX 深审后的加固:恢复确认按钮补主题色兜底重新可见、修复恢复快照时自毁目标快照的 bug、双击救援启动器自动探测 node、报错文案全面改为"人话 + 下一步"。
- 0.9.0 —— /backup doctor 会话日志体检与定点修复;宿主起不来也能用的进程外救援通道(备份目录里的 dsh-rescue / 双击启动器);恢复失败自动回滚与结果导向回执;智能备份:宿主升级前自动快照、损坏会话先隔离再入档、每日/每周分级保留。
- 0.8.0 —— 面板里直接改备份设置(目录、保留份数、排除模式),立即生效写入 settings.yaml 不用重启;两处同时改有冲突提示,不会静默覆盖。
- 0.7.x —— 凭据脱敏(本机 vault)、跨机恢复。

更多

定时备份策略、敏感文件脱敏、GitHub 同步、恢复保护机制、配置参考、故障排查、开发说明——都在进阶文档。跨运行时兼容性说明:compatibility.md。

致谢

- @beastrobin —— #1 中对保留方法名的根因分析,直接促成 v0.5.1 修复
- @mlosun —— #2 中详尽的复现与根因报告
- @Choi-Peng —— #5 中协助把受影响用户指引到修复版本

支持这个项目

如果 dsh-backup 帮到了你:⭐ 给个 Star 是最直接的鼓励,也能让更多 DSH 用户找到它。遇到问题或有想法,欢迎到反馈帖留言。

许可证

MIT
预览分享卡片长什么样 ↓xiaoyuyu6420/dsh-backup
分享 · DeepSeek Harness Hub
xiaoyuyu6420/dsh-backup

一条命令备份、恢复、迁移 DSH 全部数据(~/.dsh):升级前快照、换机迁移(会话、插件、MCP、技能)、会话日志修复、进程外救援、凭据脱敏。

回到顶部