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

插件搬家 chenzhihan1751-cyber/dsh-plugin-porter

Cordis
chenzhihan1751-cyber17 天前有提交已提供中文文档扫描:含敏感能力

打包带走插件配置记忆,换电脑一键还原

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

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

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

状态速览

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

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

验证判据与等级说明 →

可信度证据

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

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

读写/删除本地文件写入剪贴板(不计风险)发起外部网络请求
查看扫描证据(共 192 处,展示前 66 条)
  • 写入本地文件
    lib/index.js:42
    mkdirSync(dirname(stateFile()), { recursive: true })
  • 写入本地文件
    lib/index.js:43
    writeFileSync(stateFile(), JSON.stringify({ ...readState(), ...patch }, null, 2) + '\n', 'utf8')
  • 读取本地文件
    lib/index.js:79
    const readJson = (p) => { try { return JSON.parse(readFileSync(p, 'utf8').replace(/^ FEFF/, '')) } catch { return null } }
  • 写入本地文件
    lib/index.js:88
    mkdirSync(dest, { recursive: true })
  • 读取本地文件
    lib/index.js:90
    for (const e of readdirSync(src, { withFileTypes: true })) {
  • 写入本地文件
    lib/index.js:96
    else if (e.isFile()) { copyFileSync(from, to); files += 1 }
  • 读取本地文件
    lib/index.js:107
    try { entries = readdirSync(d, { withFileTypes: true }) } catch { return }
  • 读取本地文件
    lib/index.js:112
    else if (e.isFile()) { try { bytes += statSync(p).size; files += 1 } catch { } }
  • 读取本地文件
    lib/index.js:149
    if (!existsSync(file)) return []
  • 读取本地文件
    lib/index.js:150
    const text = readFileSync(file, 'utf8')
  • 写入本地文件
    lib/index.js:406
    if (cur && typeof cur === 'object') { cur[h.keyPath[h.keyPath.length - 1]] = ''; writeFileSync(file, JSON.stringify(obj, null, 2) + '\n', 'utf8'); n +
  • 写入本地文件
    lib/index.js:410
    if (re.test(text)) { writeFileSync(file, text.replace(re, '$1'), 'utf8'); n += 1 }
  • 删除本地文件递归
    lib/index.js:677
    if (unzipRoot && res.ok) { try { rmSync(unzipRoot, { recursive: true, force: true }) } catch { } }
  • 删除本地文件
    lib/index.js:755
    if (process.platform === 'win32') rmdirSync(linkPath)
  • 删除本地文件
    lib/index.js:756
    else rmSync(linkPath, { force: true })
  • 发起网络请求
    lib/client.js:122
    return fetch(API + path, {
  • 写入剪贴板
    lib/client.js:608
    await navigator.clipboard.writeText(r.text);
  • 写入剪贴板
    lib/client.js:731
    await navigator.clipboard.writeText(r2.text);
  • 读取本地文件
    lib/zip.mjs:37
    for (const e of readdirSync(dir, { withFileTypes: true })) {
  • 读取本地文件
    lib/zip.mjs:55
    const data = readFileSync(f.path)
  • 写入本地文件
    lib/zip.mjs:97
    writeFileSync(zipFile, out)
  • 读取本地文件
    lib/zip.mjs:103
    const buf = readFileSync(zipFile)
  • 写入本地文件
    lib/zip.mjs:128
    mkdirSync(dirname(out), { recursive: true })
  • 写入本地文件
    lib/zip.mjs:129
    writeFileSync(out, data)
  • 读取本地文件
    lib/allinone.js:40
    const st = statSync(p)
  • 读取本地文件
    lib/allinone.js:42
    return readFileSync(p, 'utf8').replace(/^ FEFF/, '')
  • 读取本地文件
    lib/allinone.js:45
    const readJson = (p) => { try { return JSON.parse(readFileSync(p, 'utf8').replace(/^ FEFF/, '')) } catch { return null } }
  • 读取本地文件
    lib/allinone.js:50
    try { list = readdirSync(dir, { withFileTypes: true }) } catch { return out }
  • 读取本地文件
    lib/allinone.js:100
    const dir = [p.dir, p.installedDir].find((d) => d && existsSync(join(d, 'package.json'))) || null
  • 读取本地文件
    lib/allinone.js:176
    const rd = [join(dir, 'README.md'), join(dir, 'readme.md'), join(dir, 'README.MD')].find((f) => existsSync(f))
  • 写入本地文件
    lib/allinone.js:293
    mkdirSync(dirname(historyFile()), { recursive: true })
  • 写入本地文件
    lib/allinone.js:294
    writeFileSync(historyFile(), JSON.stringify({ version: 1, updatedAt: now(), snapshots: snapshots.slice(-60) }, null, 2) + '\n', 'utf8')
  • 写入本地文件
    lib/allinone.js:739
    mkdirSync(root, { recursive: true })
  • 删除本地文件
    lib/allinone.js:744
    try { for (const f of walkFiles(root)) if (/ bak-bundlefield-/.test(f)) rmSync(f, { force: true }) } catch { }
  • 写入本地文件
    lib/allinone.js:779
    mkdirSync(catalogDir, { recursive: true })
  • 写入本地文件
    lib/allinone.js:781
    writeFileSync(join(catalogDir, slugOf(p.name) + '.md'), redact(mdPluginCatalog(p, scan)) + '\n', 'utf8')
  • 写入本地文件
    lib/allinone.js:788
    mkdirSync(kdir, { recursive: true })
  • 删除本地文件
    lib/allinone.js:881
    if (existsSync(target)) rmSync(target, { force: true })
  • 读取本地文件
    lib/fullmigration.js:121
    try { list = readdirSync(dir, { withFileTypes: true }) } catch { return { bytes, files: n } }
  • 读取本地文件
    lib/fullmigration.js:130
    try { bytes += statSync(abs).size; n += 1 } catch { }
  • 读取本地文件
    lib/fullmigration.js:139
    try { list = readdirSync(base, { withFileTypes: true }) } catch { ledger.badDir.push(base); return }
  • 读取本地文件
    lib/fullmigration.js:154
    try { st = statSync(abs) } catch { ledger.badFile.push(rel); continue }
  • 读取本地文件
    lib/fullmigration.js:165
    if (!existsSync(abs)) continue
  • 读取本地文件
    lib/fullmigration.js:169
    try { st = statSync(abs) } catch { continue }
  • 写入本地文件
    lib/fullmigration.js:441
    mkdirSync(root, { recursive: true })
  • 写入本地文件
    lib/fullmigration.js:527
    writeFileSync(join(root, 'MANIFEST.json'), JSON.stringify(manifest, null, 1) + '\n', 'utf8')
  • 写入本地文件
    lib/fullmigration.js:528
    writeFileSync(join(root, 'MANIFEST.sha256'), volHashes.map((v) => `${v.sha256} ${v.file}`).join('\n') + '\n', 'utf8')
  • 写入本地文件
    lib/fullmigration.js:529
    writeFileSync(join(root, 'README-先读我.txt'), mdReadme(ctx) + '\n', 'utf8')
  • 写入本地文件
    lib/fullmigration.js:538
    writeFileSync(join(root, 'PROMPT.md'), mdPrompt(ctx) + '\n', 'utf8')
  • 写入本地文件
    lib/fullmigration.js:545
    writeFileSync(join(root, dst), readFileSync(from))
  • 读取本地文件
    lib/stream-zip.mjs:61
    for await (const chunk of createReadStream(abs)) {
  • 读取本地文件
    lib/stream-zip.mjs:167
    try { st = statSync(e.abs) } catch { skipped.push({ rel: e.rel, reason: '读不到(可能已删除)' }); continue }
  • 读取本地文件
    lib/stream-zip.mjs:181
    buf = readFileSync(e.abs)
  • 读取本地文件
    lib/stream-zip.mjs:205
    for await (const chunk of createReadStream(e.abs)) writeSync(fd, chunk)
  • 读取本地文件
    lib/stream-zip.mjs:230
    const st = statSync(zipFile)
  • 写入本地文件
    lib/stream-zip.mjs:253
    mkdirSync(dirname(target), { recursive: true })
  • 读取本地文件
    install.mjs:39
    if (!existsSync(profilesRoot)) {
  • 读取本地文件
    install.mjs:45
    const available = readdirSync(profilesRoot, { withFileTypes: true })
  • 读取本地文件
    install.mjs:52
    if (!existsSync(profileDir)) {
  • 读取本地文件
    install.mjs:59
    if (!existsSync(pkgJsonPath)) {
  • 读取本地文件
    install.mjs:73
    if (!existsSync(linkPath)) {
  • 写入本地文件
    install.mjs:76
    mkdirSync(scopeDir, { recursive: true })
  • 读取本地文件
    install.mjs:80
    const st = lstatSync(linkPath)
  • 删除本地文件递归
    install.mjs:88
    rmSync(linkPath, { recursive: true, force: true })
  • 写入本地文件
    install.mjs:123
    copyFileSync(pkgJsonPath, bak)
  • 写入本地文件
    install.mjs:124
    writeFileSync(pkgJsonPath, `${JSON.stringify(pkg, null, 2)}\n`, 'utf8')
扫描于 2026/11/3(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

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

社区实装还没有人打卡 · 装过的第一个就是你
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

DSH 插件迁移与备份工具:一键导出、导入插件,跨配置档迁移,打包全量整合包,整机迁移。一键导出、导入、迁移并备份 DSH(DeepSeek Harness)插件,跨机器、跨配置档都行。

README

由 DeepSeek 最新模型翻译生成
Plugin Porter · DSH 插件搬家工具 把 DSH 的插件、配置、记忆、会话,打包带走。 换电脑、换 profile、给别人分享工作环境——一个包搞定。 Plugin Porter 是 DeepSeek Harness (DSH) 的插件迁移 / 备份工具:导出迁移包,在另一台机器导入,把插件复制到别的 profile,或者把整个环境——配置、记忆、会话、附件、插件源码——装进一个带校验和的多卷归档包,一次搬走。跨机器、跨 profile,一条命令搞定。 这东西解决什么问题 装了几十个插件、调了半天配置、攒了几百条记忆——换台电脑全没了。这个插件就是干这个的。 | 你的处境 | 它怎么帮你 | | 买了新电脑,不想重装一遍插件 | 整机迁移:一个包,配置/记忆/会话/插件全带走 | | 只想把某几个插件搬到另一台机器 | 迁移包:勾选 → 导出 → 那边导入 | | 想让同事体验你的插件组合 | 全量整合包:连"怎么装、有什么坑"一起打包,附一段提示词 | | 想试试 headless 模式又不想重装 | 搬到别的 profile:一键复制过去 | 三分钟装好 方式 A:从设置里装(推荐) 1. 打开 DSH → 设置 → 插件 → 添加插件 2. 填这一行:
展开完整文档(README 剩余 1 节)
Plugin Porter · DSH 插件搬家工具

把 DSH 的插件、配置、记忆、会话,打包带走。
换电脑、换 profile、给别人分享工作环境——一个包搞定。

Plugin Porter 是 DeepSeek Harness (DSH) 的插件迁移 / 备份工具:导出迁移包,在另一台机器导入,把插件复制到别的 profile,或者把整个环境——配置、记忆、会话、附件、插件源码——装进一个带校验和的多卷归档包,一次搬走。跨机器、跨 profile,一条命令搞定。

这东西解决什么问题

装了几十个插件、调了半天配置、攒了几百条记忆——换台电脑全没了。这个插件就是干这个的。

| 你的处境 | 它怎么帮你 |
| 买了新电脑,不想重装一遍插件 | 整机迁移:一个包,配置/记忆/会话/插件全带走 |
| 只想把某几个插件搬到另一台机器 | 迁移包:勾选 → 导出 → 那边导入 |
| 想让同事体验你的插件组合 | 全量整合包:连"怎么装、有什么坑"一起打包,附一段提示词 |
| 想试试 headless 模式又不想重装 | 搬到别的 profile:一键复制过去 |

三分钟装好

方式 A:从设置里装(推荐)

1. 打开 DSH → 设置 → 插件 → 添加插件
2. 填这一行:

github:chenzhihan1751-cyber/dsh-plugin-porter

3. 装完重启 DSH(关窗口,再双击图标)
4. 设置里多出一个 「插件迁移」 页

方式 B:下载 zip 手动装

1. 点右上角 Code → Download ZIP
2. 解压到任意目录(比如 D:\plugin-porter)
3. 双击目录里的 install.bat
4. 重启 DSH

装不上?见 FAQ。

五个功能,一眼看懂

打开 设置 → 插件迁移,面板上一排五个区块:

| # | 功能 | 一句话 |
| ① | 导出迁移包 | 勾选插件 → 打包成一个 zip |
| ② | 导入迁移包 | 选包 → 恢复到本机 |
| ③ | 搬到别的 profile | web → headless,插件复制过去 |
| ④ | 全量整合包 | 连"怎么装、有哪些坑"一起打包 |
| ⑤ | 整机迁移 | 配置+记忆+会话+插件,换电脑用一个包 |

① 导出迁移包

什么时候用:只想搬插件,不想搬别的。

1. 左侧列表勾选要带走的插件
2. 右侧选输出目录(点 选择目录… 有可视化浏览,不用手打路径)
3. 点 导出迁移包

产出一个文件夹 + 一个 zip:

plugin-migration-20261018-1430/
├── manifest.json ← 清单:有哪些插件、版本、来源 ├── restore.mjs ← 恢复脚本(包自带,换电脑不用先装本插件) ├── restore.bat ← Windows 双击也能跑 └── plugins/ └── dsh-xxx/ ← 本地插件连源码一起打包

远程插件(从 npm / GitHub 装的)只记版本号,恢复时自动重新拉取,包体很小。

② 导入迁移包

最省事的做法:把整个包拷到新电脑,双击包里的 restore.bat。

想先看看会发生什么(推荐):

node restore.mjs --list

包里 6 个插件: dsh-ai-memory 0.9.2 本地源码 dsh-cost-meter 0.4.1 本地源码 dshmarket 1.66.9 npm ...

预览(不写任何文件):

node restore.mjs --profile web --dry-run

确认没问题再真正恢复:

node restore.mjs --profile web --root D:\我的插件

也可以回到 DSH 界面里做:插件迁移 → ② 导入迁移包 → 选择包…(zip 或文件夹都行)→ 导入。

恢复完必须重启 DSH,插件才会真正加载。

③ 搬到本机另一个 profile

什么时候用:你平时用 web,想再开一个 headless 跑后台任务,插件想复用。

1. 勾选插件
2. 在 ③ 区块填目标 profile(比如 headless)
3. 点 复制到目标 profile

它会做三件事:写依赖声明、建目录链接、迁移 patch 条目(自动按 id 去重,不会造成启动崩溃)。

④ 全量整合包:把"使用经验"也打包

什么时候用:把环境交给一台全新的 DSH,或者分享给别人。

跟 ① 的区别:① 只给"插件本体",对方还得自己摸索怎么装;④ 把踩过的坑、搭建步骤、提示词一起抽出来。

点 ④ 全量整合包 → 生成整合包(后台),跑完得到:

| 文件 | 内容 |
| PROMPT.md | 一段提示词,整段粘给新 DSH 的对话框,它自己照着搭 |
| TRICKS.md | 通用踩坑总集 |
| catalog/插件名.md | 每个插件一页:功能、依赖、装配要点、版本变迁 |
| plugins/ + restore.mjs | 插件本体与恢复脚本 |

用法:新机器上装好 DSH → 开个对话 → 粘贴 PROMPT.md 全文 → 它自己开工。

⑤ 整机迁移:换电脑的终极方案

什么时候用:真的换机器了,想把这一整套环境原样搬过去。

勾选范围(三档):

| 档位 | 包含 | 体积 |
| essential | 配置 + 记忆 + 技能 | 最小,够用 |
| standard | 上面 + 会话 + 附件 + 插件源码 | 日常推荐 |
| everything | 上面 + 整个工作区 | 可能几个 GB |

点 生成整机迁移包,它会:

- 打成分卷(默认每卷 1.8GB,方便网盘/U 盘传)
- 每卷附 sha256 校验清单(传坏了能发现)
- 包内自带 恢复-DSH.bat / restore-dsh.mjs

新电脑上:解压 → 双击 恢复-DSH.bat → 按提示选目标目录 → 完事。

⚠️ 包里含 API 密钥。要传给别人的话,先只选 essential,或者手动删掉密钥段。

迁移包里到底装了什么

manifest.json 清单(版本、来源、校验和) restore.mjs 恢复脚本 —— 纯 Node,不依赖本插件 restore.bat Windows 双击入口 plugins/ 本地插件的源码快照

关键点:恢复脚本跟着包走。所以新电脑上不需要先装 Plugin Porter,直接 node restore.mjs 就行。

安全吗

| 它可能碰到 | 保护措施 |
| profiles/<名字>/package.json | 改之前先存 package.json.bak-时间戳 |
| profiles/<名字>/cordis.patch.yml | 先备份;按 id 去重,防 duplicate loader entry id 启动崩溃 |
| 你的插件源码目录 | 目标已存在就原样保留,要覆盖必须显式加 --force |
| 导出的包 | 只新建目录,不覆盖已有同名目录 |

它不碰 DSH 主程序代码,也不改你的插件源码(导出时只给快照副本补字段)。

启动体检:装完先自检

DSH 新版本对插件有个硬要求:每个插件必须在 package.json 里声明 dsh.bundle.patch,缺了启动直接失败。

面板上的 「启动体检」 按钮 = 用 DSH 自己的加载逻辑先跑一遍,不用重启就知道下次启动会不会挂。

也可以用命令行:

node tools/check-profile-boot.mjs --profile web

退出码 0 = 没问题,非 0 = 启动会失败(会告诉你是哪个插件)。

真出问题了,面板上有 「修复选中:dsh.bundle」,一键补齐并备份原文件。

恢复后怎么生效

重启 DSH。桌面版:关掉窗口,再双击图标。

重启前设置页里只是列表刷新了而已,插件代码还没加载。

FAQ

Q:装完设置里没看到「插件迁移」? 重启 DSH。插件的 UI 是启动时挂载的,热更新不覆盖这一层。

Q:导入后插件列表有了,但功能没生效? 同上,重启。列表刷新 ≠ 插件加载。

Q:恢复脚本报 Cannot find module? Node 版本太低。要求 Node ≥ 22:node -v 看一下。

Q:包传过去 sha256 对不上? 传输过程损坏(网盘/U 盘常见)。重新传那一卷,别硬解压。

Q:会覆盖我现有的插件吗? 不会。目标目录已存在时保留原样;要覆盖得自己加 --force。

Q:能只导出某一个插件吗? 可以,列表里只勾那一个就行。

Q:和「插件市场」有什么区别? 市场负责装新插件,这个负责搬已有的。两者不冲突,可以同时装。

开发者

- 零构建:lib/ 里的 JS 就是源码,改完重启即生效
- 不 spawn 子进程:zip 用自带的 lib/zip.mjs 压缩/解压
- 实现细节、边界、设计取舍 → docs/INTERNALS.md
- Agent 工具:plugin_migrator_list / _export / _import / _copy

git clone https://github.com/chenzhihan1751-cyber/dsh-plugin-porter.git
cd plugin-porter
node install.mjs # 装进本机 DSH

License

BSD-3-Clause
预览分享卡片长什么样 ↓chenzhihan1751-cyber/dsh-plugin-porter
分享 · DeepSeek Harness Hub
chenzhihan1751-cyber/dsh-plugin-porter

打包带走插件配置记忆,换电脑一键还原

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