WorkBuddy 无感换机迁移
把一台机器上的 WorkBuddy 完整搬到另一台,登录后看不出差别:定时任务、历史会话、工作区、自建技能、连接器配置、长期记忆全部在位。
何时使用
- 换新电脑 / 重装系统后恢复 WorkBuddy
- 只在旧机上跑过的工作流(自建技能、MCP、定时任务)需要原样复现
- 用户问「重装会不会丢东西」「WorkBuddy 数据在哪,怎么备份」
- 要给同事复制一套同样配置的 WorkBuddy 环境
核心认知(先讲给用户听)
~/.workbuddy 通常 3–5 GB,但其中大半是重建成本很低的垃圾:
| 类别 | 典型占比 | 处理 |
|---|---|---|
binaries/ app/ logs/ traces/ cache/ |
约 40–50% | 不迁,新机首次启动自动重建 |
workspace/sessions/(文件回滚快照) |
最高可占 40% | 不迁,只影响撤销历史 |
workbuddy.db |
几 MB | 必迁,定时任务 / 会话索引 / 工作区索引全在这 |
skills/ plugins/ projects/ blobs/ |
几百 MB | 必迁,自建技能、连接器插件、对话正文 |
user-*-personal/ MEMORY.md |
几十 KB | 必迁,长期记忆与身份档案 |
程序安装目录(如 D:\workbuddy) |
— | 不要拷,装新版客户端 |
实测案例:4.4 GB 的 .workbuddy 蒸馏出 1.7 GB 有效数据,压缩后 1.09 GB —— 迁移体积降到 1/4,22,815 个文件一次搬完。
执行流程
第一步:体检(先给事实,别急着搬)
python scripts/workbuddy_migrate.py inspect
输出:数据根目录、各子目录体积排序、定时任务 / 会话 / 工作区数量、可迁移体积预估。
把「带走 / 不带 / 手工补」三类讲清楚,再问用户是否开始打包。
第二步:打包
# 完整包(含插件缓存与项目工作区,默认推荐)
python scripts/workbuddy_migrate.py pack --out D:\WB迁移包
# 瘦身包(只带灵魂数据,工作区另外取)
python scripts/workbuddy_migrate.py pack --out D:\WB迁移包 --no-workspaces --no-plugins
# 增量包(只带上次打包后动过的文件,几秒到几十秒)
python scripts/workbuddy_migrate.py pack --out D:\WB迁移包 --incremental
python scripts/workbuddy_migrate.py pack --out D:\WB迁移包 --incremental --base D:\WB迁移包\wb-migrate-20261026-0902
产物:
<out>/wb-migrate-YYYYMMDD-HHMM/
├── data/.workbuddy/... # 覆盖到新机 %USERPROFILE%\.workbuddy
├── data/WorkBuddy/... # 覆盖到新机 %USERPROFILE%\WorkBuddy
├── manifest.json # 来源机器、来源路径、各类体积
├── file-index.json # 文件索引(大小+mtime),给下一次 --incremental 当基线
├── 恢复说明.md # 分步说明 + 验收清单
└── restore.cmd # 双击即解包覆盖(纯 ASCII,不乱码不闪退)
<out>/wb-migrate-YYYYMMDD-HHMM.zip
打包期间不必关闭 WorkBuddy:脚本对 sqlite 走在线备份 API,热拷同样一致。
增量打包的语义(重要):--incremental 只把变过的文件放进新包,所以它是个"叠加包",
新机上必须先还原基线包、再叠加增量包,单独还原会缺一大半文件。基线默认取 --out 下最新的包,
也可以用 --base 指定;找不到基线就自动退化为完整包(会明说),--base 明确指定却读不到则直接报错。
数据库与配置文件(workbuddy.db、MEMORY.md、settings.json)永远全量带走 —— 体积小、天天变,增量没意义。
源端已删的文件只会被统计并写进 manifest,不会代删(还原是覆盖语义)。
第三步:新机还原
- 装新版客户端,先不启动、不登录(别拷旧安装目录)
- 运行
restore.cmd,或手动覆盖上面两个目录(用了增量包就先还原基线包,再覆盖增量包) - 用户名 / 盘符与旧机不同 → 再跑
fixpaths:
python scripts/workbuddy_migrate.py fixpaths --src <包目录>
它做三件事:改配置里的旧绝对路径、重命名 projects/ 下的工作区键、批量修正数据库里的路径字段。
同名用户可跳过。
- 启动 → 登录同账号 → 等运行时自动装完
- 逐个重连连接器(授权绑设备,本地拷不回来)
- 确认定时任务未被清空、不会双发后再放行
第四步:验收
python scripts/workbuddy_migrate.py verify
对照 assets/验收清单.md 逐项确认,重点看会话数、任务数、技能数是否与旧机一致。
第五步:旧机退场(新机验收通过后再做)
# 1) 先预演:只校验包 + 存档快照,不动进程、不关机
python scripts/workbuddy_migrate.py retire --src <包目录>
# 2) 确认无误后真退场:优雅退出 + 5 分钟倒计时关机
python scripts/workbuddy_migrate.py retire --src <包目录> --yes
# 3) 反悔(倒计时内有效)
python scripts/workbuddy_migrate.py retire --abort
它按顺序做四件事:
- 校验迁移包:
data/与manifest.json在、包内workbuddy.db能过quick_check、
任务/会话数不为空包(低于 2 视为空包)、restore.cmd与恢复说明.md齐全 —— 任一项不过直接拒绝,不关机。 - 存档体检快照:在包同级写
退场记录/退场记录-<时间>.md,记录任务/会话/工作区/技能数与数据体积,退场后仍能跟新机对账。 - 优雅退出 WorkBuddy:只发退出请求(
taskkill不带/F,失败再用/T),等最多 20 秒;
退不掉就停手并提示手动关闭,绝不强杀(强杀会写坏workbuddy.db)。 - 延时关机:默认
--delay 300(5 分钟撤销窗口),命令为shutdown /s /t 300,
并明确告知撤销方式shutdown /a或retire --abort。
默认就是预演,必须显式 --yes 才真执行;--dry-run 优先级高于 --yes。
retire 只在 Windows 生效(macOS/Linux 只提示手动退出)。
硬规则(违背必出事)
- 迁移期新旧机不能同时登录 → 定时任务双发(同步 / 推送类任务尤其致命)。
- 连接器授权不会跟着文件走,飞书、金山、企业微信、腾讯文档等须在 UI 重新授权。提前告知用户,别让他误判成迁移失败。
mcp.json里写死的解释器绝对路径要在新机校验,verify会列出失效项。- 旧机
.workbuddy至少保留到新机验收通过,这是唯一回滚手段。 - 长路径:Windows 260 字符上限会让
zipfile和资源管理器复制直接报错(典型元凶是buddy-snapshots/下的技能快照),打包时跳过并计数,不要硬刚重试。 - 别用
rm -rf清理几十万文件的半成品包,会触发安全删除拦截或耗时极长;用脚本内shutil.rmtree。 retire的顺序不能颠倒:必须「新机验收通过 → 包校验通过 → 才关机」。旧机关机前先确认包里
任务数与旧机一致;关机后旧机workbuddy.db仍在盘上,是最后一道现场,别顺手删。- 增量包不能单独用:它只含变更文件,必须先还原基线包再叠加;
retire遇到"同级找不到基线包"
的增量包会直接拒绝,别绕过 —— 那是唯一能证明数据完整的依据。
逐目录取舍依据见 references/migration-matrix.md,踩坑复现与解法见 references/pitfalls.md。
输出给用户的东西
- 迁移包(文件夹 + zip)+ 包内
恢复说明.md - 一份 HTML 方案页:结论、三类数据分层、五步操作、坑位、验收清单。
用assets/report-template.html填占位符生成,体积与路径必须取自inspect/pack的真实输出,不要编数字。