社区工具 claude-migrate:切换账号后恢复 Claude Code Desktop 会话
Show HN: Recover Claude Code Desktop sessions after switching accounts
非官方社区工具 claude-migrate 可将 Claude Desktop 的 Code 会话侧边栏记录从旧账号迁移到同一台 Mac 上的新账号,切换账号后消失的会话重新出现在侧边栏。
非官方社区工具。与 Anthropic 无关联,也未获其认可。
将你的 Claude Desktop Code 会话迁移到同一台 Mac 上的另一个账户,让侧边栏重新显示它们。
当你切换 Claude 账户(例如从个人版切换到 Team 版)时,Claude Desktop 中的 Code 标签页会变成空的。并没有任何东西被删除:根据在 Claude Desktop(2026 年 10 月)中的观察,它为每个账户和组织各保留一个侧边栏存储,并且只读取你当前登录账户的存储。claude-migrate 会将会话记录从旧账户的存储复制到新账户的存储,保留它们的 ID(因此置顶会一并保留),清除属于旧账户的链接,并且绝不触碰转录内容或现有文件。
工作原理
一个 Desktop Code 会话由两部分组成。其中只有一部分与账户绑定。此处描述的 Desktop 存储基于在 Claude Desktop(2026 年 10 月)中的观察;它没有文档记录,且可能发生变化。
flowchart LR
subgraph shared["Account-independent"]
T["~/.claude/projects/#lt;project#gt;/#lt;session#gt;.jsonl<br/>transcript: the conversation"]
end
subgraph old["Old account store"]
R1["claude-code-sessions/#lt;acct#gt;/#lt;org#gt;/local_#lt;id#gt;.json<br/>sidebar record"]
end
subgraph new["New account store"]
R2["claude-code-sessions/#lt;acct#gt;/#lt;org#gt;/local_#lt;id#gt;.json<br/>sidebar record"]
end
R1 -- "claude-migrate copies<br/>(same file name and ID)" --> R2
R1 -. points to .-> T
R2 -. points to .-> T
加载中
- 转录内容由所有账户共享。无论谁登录,
claude --resume都能看到它。 - 侧边栏记录存放在一个
<account>/<org>文件夹中。这就是切换后“消失”的东西。 claude-migrate只复制记录。转录内容绝不会被读取内容、移动或修改。
功能
- 在账户/组织存储之间复制侧边栏记录,保留每个无需更改字段的 JSON 值,包括未知字段。
- 保留会话 ID,因此置顶会一并保留:根据观察,Desktop 维护一个以会话 ID 为键的全局置顶列表,由所有账户共享。
- 默认试运行。
apply仅做增量添加,绝不覆盖文件。 - 每次写入之前都会先记录到清单中;
undo只删除某次运行所创建的内容,且仅当这些文件未被更改时才会删除。 - 在 Claude Desktop 运行时拒绝写入,并将目标账户与 Desktop 上次使用的账户进行交叉核对。
- 跳过转录内容已丢失的会话(它们打开后会是空的);
--include-orphans仍会复制它们。 - 绝不恢复你在目标账户中删除的会话:根据观察,Desktop 会留下一个
deleted_<id>标记,而在保留 ID 的情况下,该标记指向同一个会话。 - 遇到无法识别的文件夹布局时安全失败。
- 除
version外,每条命令都输出机器可读的--json。仅使用标准库,无网络访问。
安装
Homebrew cask:
brew install --cask onlyilkr/tap/claude-migrate
该二进制文件未签名或未公证,因此 cask 会在安装时移除其 macOS 隔离标志;否则 Gatekeeper 会拒绝运行它。如果你不希望由 cask 来做这件事,请使用 go install(在你的 Mac 上构建,无需变通方法):
go install github.com/onlyilkr/claude-migrate/cmd/claude-migrate@latest
或者从 releases 页面 下载发布版二进制文件(darwin/arm64 或 darwin/amd64),并对照已发布的校验和进行验证:
shasum -a 256 -c --ignore-missing checksums.txt # run next to the downloaded archive快速开始
- 先在 Claude Desktop 中登录新账户一次,使其存储存在。然后用 Cmd+Q 完全退出 Desktop。
- 打开终端并在其中运行该工具。不要从 Desktop 自带的 Code 标签页运行它:退出 Desktop 会结束该会话,而且该工具在 Desktop 运行时拒绝写入。
- Preview. Nothing is written:
claude-migrate # same as: claude-migrate planWith several candidate stores, runclaude-migrate doctorto list them. - Apply, using the command the plan printed:
claude-migrate apply --from 1a2b3c4d/5e6f7a8b
- 打开 Claude Desktop。这些会话会出现在新账户的侧边栏中,已置顶的会话仍然处于置顶状态。
改变主意了?claude-migrate undo 只删除上次运行所创建的文件。
命令
| 命令 | 作用 | 是否写入? |
|---|---|---|
claude-migrate / plan |
显示将复制哪些内容以及哪些需要手动跟进。当只有一个候选来源时会自动为你选择;否则在 TTY 上询问。 | 否 |
apply --from X |
复制记录并将清单写入 ~/.claude-migrate/runs/。--from 为必需项。 |
是 |
undo [manifest] |
删除某次运行创建的文件(默认是最近一次运行),跳过自那以后你改动过的任何文件。不带路径时它会拒绝执行,而不是在较新的运行文件无法读取时去挑一个更早的运行。 | 是(删除) |
pins |
列出正在被复制或已在目标中的固定源会话(被跳过的会话,无论是没有记录、已删除还是名称冲突,都不列出),每个以 pinned in target、copied under a different ID; pin it again in Desktop 或 not migrated yet 表示。 |
否 |
doctor |
Desktop 状态、已登录账户、Desktop 上次是否使用同一账户、存储、cleanupPeriodDays。 |
否 |
version |
打印版本。 | 否 |
| 标志 | 适用于 | 含义 |
|---|---|---|
--from <acct>/<org> |
plan、apply、pins |
源存储。唯一前缀可用(1a2b3c4d/5e6f7a8b)。 |
--to <acct>/<org> |
plan、apply、pins |
目标存储。默认为 Claude Code 已登录的账户(~/.claude.json)。传入它会跳过 Desktop 账户交叉检查。 |
--include-orphans |
plan、apply |
也复制记录缺失的会话。它们在 Desktop 中会以空内容打开。 |
--force |
undo |
也删除自该次运行以来改动过的文件。不绕过其他任何保护。 |
--json |
除 version 外全部 |
机器可读输出。 |
退出码
| 代码 | 含义 |
|---|---|
| 0 | 正常 |
| 1 | 错误(I/O 失败、撤销不完整) |
| 2 | 用法错误:错误的标志、无法解析或有歧义的存储、源等于目标、没有已登录账户、无法读取或解析的 ~/.claude.json、清单路径不存在的 undo、在没有运行或较新的运行文件无法读取时未带路径的 undo,或账户不匹配的 apply(见下文) |
| 3 | Claude Desktop 正在运行,或无法检查(SSH 会话) |
| 4 | 无法识别的 Desktop 文件夹布局,或目标存储不存在 |
复制记录中会改变的内容
| 字段 | 结果 |
|---|---|
bridgeSessionIds |
清空。这些是旧账户的云会话 ID。 |
scheduledTaskId |
移除。它指向旧账户的一个任务。 |
sessionId 和文件名 |
保留。副本与源具有相同的 local_<id>.json 名称。 |
| 其他所有内容 | 值保留:每个字段的原始 JSON 逐字保留(键会重新排序并重新缩进),包括本工具不了解的字段。 |
未知字段绝不会阻止运行;plan 会列出它们以供参考。
安全模型
- 默认试运行。只有
apply和undo会写入。 - 仅追加。副本会写入一个唯一的临时文件,并用
link(2)发布,如果名称已存在则会原子性地失败,因此即使存在竞争也绝不会覆盖。如果写入在其清单条目之后失败,该条目会被撤回,这样undo就不会把该路径上的任何东西当作我们的。如果目标中已存在同名但属于不同会话的文件,或存在同名但不是常规文件的条目(符号链接或文件夹),该记录会被跳过并报告(name_conflicts)。 - 先写清单再写入。每个文件在写入之前都会(连同其 SHA-256)记录并 fsync 到运行日志,因此崩溃不会留下未记录的文件。
- 哈希校验的撤销。
undo只删除清单中列出的、位于目标存储内、且哈希仍然匹配的文件。手工编辑的清单无法让它指向别处。较新的运行再次记录的文件(相同路径、相同保留 ID)属于那次运行:撤销较旧的运行会保留它并报告为superseded(“为较新的运行保留”)。无法读取的较新运行会被列出,因为它们不保护任何东西。 - Desktop 防护。
apply和undo在 Desktop 运行时拒绝执行。该检查会向 Launch Services 询问当前 GUI 登录会话,因此请在 Mac 本机的终端中运行该工具;通过 SSH 时它看不到 Desktop 并会拒绝(退出码 3)。使用--home时,只要目标按文件标识属于你真实主目录下的存储(包括符号链接、.、大小写变体),该防护仍然适用。 - 账户交叉校验。Claude Desktop 会在
config.json中记录它上次使用的账户。如果你不传入--to,而该账户与~/.claude.json中的账户不同,apply会停止(退出码 2),并且plan/pins会在 stderr 上打印警告。传入--to <account>/<org>可显式选择。 - 失败即关闭。陌生的文件夹布局、缺失的目标存储或格式错误的账户 ID 都会让运行停止,而不是进行猜测。该工具从不创建目标存储。
限制
- 仅限 macOS。
- 仅限本地 Desktop Code 会话。云会话、Cowork 会话以及 claude.ai 聊天、Projects、artifacts 和 memory 都位于 Anthropic 的服务器或其他存储中,不在范围内。
- 计划任务只会被报告,不会被移动:请在目标账户中重新创建它们。
- cwd 位于旧账户暂存文件夹内的会话,仅在该文件夹存在时才能继续工作;不要删除它。
- 早于
cleanupPeriodDays(默认 30 天)的对话记录会被 Claude Code 删除。当该设置缺失时,plan会发出警告。 - 它依赖未公开的 Desktop 文件,因此 Desktop 更新可能会使其失效。更新后请运行
doctor,并预期会出现失败即关闭的行为,而不是静默损坏。
故障排除
我在新账户中删除的会话没有被再次复制。这是设计使然:目标的 deleted_<id> 标记会被尊重,计划会将其列为“已在目标中删除”。如果某个会话被旧版工具以不同的 ID 复制,随后又被你删除,则无法通过这种方式匹配,因为其标记指向的是另一个 ID。
账户交叉校验没有发现错误的组织。Desktop 的 config.json 只记录最后一个账户(lastKnownAccountUuid),不记录组织。如果一个账户有多个组织,请检查 plan 的 Target: 行,或传入 --to <account>/<org>。
之后我可以从旧账户中删除这些会话吗?请等到你在新账户中打开过几个已迁移的会话之后再说。两份副本共享相同的会话 ID 和对话记录,而 Desktop 在删除其中一份副本时如何处理共享状态并未公开。
运行 apply 后侧边栏仍然是空的。据观察,Desktop 会在退出时将其内存中的列表写回。请用 Cmd+Q 完全退出(而不只是关闭窗口),重新启动,并确保你已登录到目标账户。
~/.claude.json is signed in to account … but Claude Desktop last used account …。两者对哪个账户是当前账户意见不一致。检查 claude-migrate doctor,然后为你实际想要的存储传入 --to <account>/<org>。
“no transcript (skipped)”并不等于零。这些记录指向的对话记录已不在 ~/.claude/projects 中(通常是被 cleanupPeriodDays 移除的)。在 Desktop 中它们会以空内容打开。可以用 --include-orphans 照常复制它们,或者将它们留下。
固定(pin)是如何工作的?据在 Claude Desktop(2026 年 10 月)中观察,固定项以 local_<id> 值的单一列表形式存储在 claude_desktop_config.json 中,由所有账户共享。由于副本保留其 ID,它一出现就会被固定。该工具会读取该列表(只读)来判断哪些源会话被固定;只有当该列表无法读取时,记录自身的 isStarred 标志才作为回退。claude-migrate pins 会将每个被固定的源会话显示为 pinned in target 或 not migrated yet。如果某个会话被旧版工具以新 ID 复制,而你之后又固定了该副本,则它计为 pinned in target,否则计为 copied under a different ID; pin it again in Desktop;plan 在其固定后续行中只计入后者。
某条记录因名称冲突而被跳过。目标中已存在一个同名文件,但对应的是不同的会话。该文件保持原样,并会在计划中列出。
在副本上试用
要在不触碰真实 Desktop 数据的情况下查看运行效果,请构建一个布局类似主目录的暂存目录,并将 --home 指向它:
SCRATCH=$(mktemp -d) mkdir -p "$SCRATCH/Library/Application Support/Claude" cp -R ~/Library/Application\ Support/Claude/claude-code-sessions "$SCRATCH/Library/Application Support/Claude/" cp ~/Library/Application\ Support/Claude/config.json "$SCRATCH/Library/Application Support/Claude/" # enables the account cross-check # Copy only the pin list (jq ships with macOS 15+): the full claude_desktop_config.json can hold MCP server secrets. jq '{preferences:{epitaxyPrefs:{"starred-local-code-sessions":.preferences.epitaxyPrefs["starred-local-code-sessions"]}}}' \ ~/Library/Application\ Support/Claude/claude_desktop_config.json > "$SCRATCH/Library/Application Support/Claude/claude_desktop_config.json" cp ~/.claude.json "$SCRATCH/" claude-migrate plan --home "$SCRATCH" --include-orphans claude-migrate apply --home "$SCRATCH" --from <old-account>/<old-org> --include-orphans claude-migrate undo --home "$SCRATCH"
对于不属于你的主目录,会跳过 Desktop 检查,并且不会触碰 scratch 目录之外的任何内容。~/.claude/projects 无需复制;--include-orphans 代表你省略的转录记录。完成后删除 scratch 目录:~/.claude.json 的副本包含你的账户详细信息。--home 是一个对 claude-migrate help 隐藏的测试标志。
替代方案
其他涉及同一问题领域的社区项目(均与本项目无关联)。描述概括了各项目截至 2026 年 10 月的 README 内容:
| 工具 | 功能 |
|---|---|
| claude-code-export-import | 在机器、账户和应用构建之间导出和导入 Claude Code 会话;重写转录记录。 |
| transfer-claude-sessions | 通过试运行、备份和撤销,将 Desktop 会话复制到新账户;Windows PowerShell。 |
| claude-session-migrate | Claude Code 技能和脚本,可将 Desktop 侧边栏记录复制到新账户;面向 Windows,先备份 sessions 文件夹。 |
| claude-account-migration | 说明 Desktop 将会话保存在何处以及为何切换会隐藏它们,并附有辅助脚本;macOS 和 Windows。 |
| cowork-migrate | 在 Mac 之间迁移 Cowork 会话。 |
| claude-folder-move | 当项目文件夹移动时,重新定位 Claude Code 会话。 |
开发
make check # test (race), vet, gofmt check, staticcheck make build # bin/claude-migrate make snapshot # local GoReleaser build, nothing published
有关 TDD 工作流和 fixture 规则,请参阅 CONTRIBUTING.md。若要从你自己的存储中添加回归 fixture 而不泄露数据,请使用 go run ./scripts/anonymize -src <store dir> -out <dir>,并用 CONTRIBUTING.md 中描述的隐私 grep 检查输出。
贡献与安全
欢迎贡献;请先阅读 CONTRIBUTING.md。请按 SECURITY.md 中所述私下报告漏洞,不要公开提交 issue。发布说明见 CHANGELOG.md。
许可证
来源:Hacker News · github.com
