首页/文章/从 Windows 到 Mac:把 Codex 和 Herm…
实践分享2026年10月19日

从 Windows 到 Mac:把 Codex 和 Hermes 的工作现场一起搬走

一次 Codex 与 Hermes 跨系统迁移记录:从备份、历史恢复到工具链自检,以及我为什么把这些经验整理成两个开源 Skill。

最近换了台 Mac,开始把 Windows 上的工作环境搬过来。

代码仓库相对直接。更让我在意的是 Codex 和 Hermes 里积累的东西:之前讨论过的问题、还没做完的任务、慢慢整理出来的记忆和 Skill,以及散落在工作区里的图片、报告和未提交修改。

我不想换台电脑之后,又从“重新交代一遍背景”开始。

最开始,我以为把几个数据目录复制过来就差不多了。真正恢复时才发现,文件到了、聊天列表出来了、旧会话能读取、实际工作能继续,是四件不同的事。

这篇文章记录这次搬家的过程与几个关键问题。文中的统计是本次检查时点的快照,不代表产品的固定目录结构或通用迁移保证。最后,我也把可复用的方法整理成了两个开源 Skill。

搬的不是两个应用,而是一套工作现场

迁移前,我先把内容分成三层:

层次 需要保留的东西 处理方式
Agent 状态 会话、索引、项目归属、记忆、Skill、任务定义 备份数据,再检查关联关系
工作文件 代码、附件、图片、报告、未提交修改 单独迁移工作区,保留隐藏文件和 Git 信息
机器环境 运行时、CLI、扩展、字体、系统凭证 在 Mac 上重装、检查版本或重新授权

这三层不能互相替代。同一个账号,不代表所有本地状态和文件已经同步;聊天里还能看到一个图片路径,也不代表图片本身已经搬过来了。

数据目录也要现场确认。比如这台 Windows 上,Hermes 真正使用的是 %LOCALAPPDATA%\hermes。用户目录下虽然也有 .hermes,但并不是主要数据来源。如果只照默认路径备份,很可能顺利打包了一个并不完整的目录。

Hermes 先用官方备份,不自己拼一个恢复包

Hermes 提供了 backup 和 import。这次先指定实际数据目录,再导出完整备份:

$env:HERMES_HOME = "$env:LOCALAPPDATA\hermes"
hermes backup -o 'E:\Migration\hermes-full.zip'

输出目录需要提前创建。这次备份包含 2,577 个文件,压缩后约 187.5 MB。除了看到 ZIP 文件,还检查了退出码、压缩包完整性和数据库是否包含在内。

官方备份会使用 SQLite backup API 生成一致的数据库快照,不是简单把运行中的数据库文件复制一份。若有文件未能加入,压缩包仍可能存在,但命令会报告不完整,所以“文件生成了”不能单独作为成功标准。Hermes 备份说明

恢复时,先保护 Mac 已有数据,停止相关会话和服务,再导入并检查:

hermes import /path/to/hermes-full.zip
hermes setup
hermes doctor
hermes sessions list

这里有个必须提前知道的区别:import 是覆盖恢复,不是新旧历史的自动合并。 --force 只是跳过确认,并不会把覆盖变成合并。新机已有重要内容时,要先备份,并在隔离目录或 profile 中验证。Hermes 导入说明

传输本身不复杂,但要把完整性和凭据算进去

这次实际用了同一 Wi-Fi 下的 Windows SMB 共享,Mac 在 Finder 中按 ⌘K 连接。临时传备份包,也可以选择两端支持的 QQ 闪传等方式,没必要为一次搬家搭很复杂的传输系统。

我遇到的阻碍反而是登录:共享目录配置好了,“客人”和原 Windows 账户却都没连上。最后用了一个有密码、带有效期的临时本地账户,只给目标目录读取权限,完成传输。

这个过程让我重新区分了几件事:Windows PIN 不等于账户密码;共享权限中的 Everyone 不等于允许匿名访问。原账户为什么失败没有确认,就不能直接归因于 Microsoft 账户。

传输前后核对 SHA-256,验收后再清理临时账户和共享。备份里可能包含凭据,不应生成公开下载链接,也不能因为换了一种传输方式就省掉完整性检查。

Codex 最先暴露的问题:我一开始就数错了

Codex 这边,Mac 已经产生了新会话,所以目标不是用旧目录盖掉新目录,而是保留新数据,再恢复旧历史。

第一次清点时,旧索引里有 259 个不同的会话 ID,但只找到了 35 个未压缩 JSONL,而且多数还是后台审核子会话。看起来像丢了一大批历史。

后来才发现,统计漏掉了 502 个 .jsonl.zst 压缩文件。

这是第一个很具体的教训:不能只搜 *.jsonl,更不能把文件数、索引 ID 数和界面聊天数直接画等号。 一个长会话可能有多个分卷,后台子会话也不等于独立的用户聊天。

另一个问题是真实缺失:复制过来的目录里没有找到主会话数据库。于是又回到旧 Windows,完全退出相关应用,补充导出了数据库及其旁车文件、会话文件、索引和全局状态。补充包没有带走 auth.json,Mac 保留自己的登录状态。

按这次安装版本的观察,Codex 的恢复对象至少包括会话文件、数据库中的会话及项目关系、部分桌面状态,以及数据目录之外的真实工作区。官方文档可以帮助定位 CODEX_HOME 和会话文件,但不应据此把内部数据库字段当成稳定迁移接口。状态目录说明、会话文件说明

更麻烦的不是盘符,而是历史里的关联关系

最容易想到的是路径映射:

C:\Users\旧用户名\Documents\Codex → /Users/新用户名/Documents/Codex
D:\Codes\VibeProject              → /Users/新用户名/codes/VibeProject

但项目不一定还在原来的相对位置。有些已经放进 hold,有些属于另一组源码目录。最后需要逐个核对真实目录,而不是只替换一遍盘符。

这次只修改确认过的结构化路径,例如工作目录、项目根目录和图片保存位置。历史消息里的命令、代码和用户原话保留原样,不能为了“看起来全是 Mac 路径”,把过去发生过的内容也改写掉。

长会话还带来一个更隐蔽的问题:有些分卷引用记录了前一份文件的读取截止位置。转换路径、重写 JSON 后,文件字节长度变了,旧位置可能失效:

cutoff byte offset is past the source rollout

所以,这次除了映射路径,还重新计算了受影响的分卷引用位置和相关历史位置。部分图片历史中的 Windows 路径,也需要修正才能在 Mac 上解析。

数据库完整性检查通过,只能说明数据库结构没有明显损坏,不代表应用已经能读懂里面的历史。 这种版本相关的修复适合针对副本准备方案,不适合写成一条让所有人直接执行的 SQL。

恢复成功,要分阶段说清楚

这次先在副本中保留 Mac 原有数据,再导入旧记录,使用当前应用自带的会话服务做读取验证。

记录中的结果是:列出并读取了 94 个普通及归档会话,其中包含 Mac 已有的新会话;完成 96 次历史分页读取,读到 25,409 条历史内容,错误为零。数据库完整性、外键和重复合并检查也通过。

之后才完全退出应用,由离线脚本再次备份目标状态、合并最新数据并写入。执行记录确认导入了 10 个项目和 533 条旧会话记录;后续检查,新机共有 535 条会话记录。这里包含后台子会话,不能写成“535 个聊天窗口”。

这些结果让我能说:主要历史已完成恢复,副本中的应用读取也通过了验证。但还不能说所有东西都已经恢复到原来的工作状态。

所有项目的依赖、每个历史会话的续聊和全部自动化,并没有逐一验收。3 个旧 Codex 提醒也没有直接启用。旧任务恢复出来,不代表它可以立刻恢复发送、发布或其他外部动作。

Hermes 的第二场搬家:把工具链重新接上

Hermes 初期自检记录统计到 270 个会话、12,977 条消息和 108 个 Skill。这说明大量状态已经回来,但不代表原来的工作流自然就能继续。

真正容易断的,是机器相关的部分:

问题 这次的处理方式
CLI 不在 PATH 中 重装并检查实际命令位置和版本
授权状态不适用 重新检查对应工具的登录和资源权限
字体写死 Windows 路径 改为探测当前系统可用字体
Python 环境不一致 确认实际调用的解释器与依赖环境
Skill 保留旧路径 更新有效路径,给平台专属经验补限定
定时任务没有运行 区分暂停、定义缺失和运行失败

例如,飞书某次调用需要 user 身份与相应权限,换成 bot 身份并不能绕过授权问题。这是具体 API 与资源权限的要求,不能概括成“bot 都不能写”。

另一个坑是小红书图片上传。最初很容易怀疑跨系统兼容性,但自检记录显示,新机安装的是比旧机更新的 opencli 与扩展组合。后来通过核对上游修复、更换官方扩展解决;中途直接修改商店扩展文件,反而触发了 Chrome 完整性校验。

这让我记住一个排查顺序:先看原始报错和新旧版本,再判断是不是系统差异。 换机时顺手升级引入的问题,靠替换 Windows 路径解决不了。具体修复版本仍应现场查看上游 issue、PR 和 release,而不是永久记住某个旧版本号。

最后,把搬家经验拆成两个开源 Skill

做完之后,我把可复用的部分放到了 GitHub:

  • migrate-codex:面向本地会话、项目和工作区恢复,先清点压缩会话、数据库与实际文件,再处理路径映射、合并和分卷关系,最后验证应用读取。
  • migrate-hermes:从有效 home 和 profile 开始,优先使用官方备份与导入,再核对会话、记忆、Skill、cron、gateway 和外部工具环境。

两个 Skill 都带了只读清点脚本。脚本不读取凭据内容或输出消息正文,也不替用户执行任务;但运行中数据库的清点只是初步证据,不能代替一致性备份和恢复验收。

我没有把这次的盘符、数据库编号和离线合并脚本包装成“万能一键迁移”。真正值得保留的是顺序和判断:先清点,保护目标已有数据,在副本中验证,确认能回滚,再写入和验收。

这也接着我之前写的从提示词到工作方法。一次复杂任务结束后,聊天记录保存了发生过什么;Skill 应该留下下一次怎样少走弯路,以及哪些地方不能照搬。

如果再搬一次,我会先列清数据、工作区和依赖,传输后核对完整性,再分别验收历史读取、项目访问和实际业务。旧机与中转目录留到确认没有唯一文件、符号链接或 Git 历史依赖后,再考虑清理。

换机没有让我换掉之前积累的工作方式,但它让我看清了这些积累到底落在哪里。以后判断一次 Agent 搬家是否完成,我会多问一句:不只是“过去的东西还在不在”,还有“接下来那一步,能不能继续做”。