微信扫码
添加专属顾问
我要投稿
轻松解决Claude Code会话迁移难题,一键找回丢失的对话记录!核心内容:1. 开发cc-migrate-session脚本解决会话迁移痛点2. 技能安装与使用方式详解3. 技能开发背后的架构思考与未来规划
本文原先是在 ~/.claude 下基于 cc 写完初稿,接着移动到了个人的 obsidian 知识库下,结果之前的对话记录就没了……
但一点不慌,在新的目录下打开 cc 后输入 /lovstudio-cc-migrate-session 原目录在 ~/.claude,它就整理出了之前的对话记录(一共 14 条)。
我继续说 只要 cc-migrate-session 相关的即可,它通过分析就是最后一条,然后就把它迁移到了本目录。
接着我退出当前 cc,并输入 cc --resume,它顺利显示出了之前的对话记录,选择其中一条后进入,我接着进行下一步的创作。
这就是我今天想给大家介绍的 cc-migrate-session 脚本(并同步提供了skill: npx skills add lovstudio/cc-migrate-session-skill),能帮你免费、精准、按顺序地迁移旧地址的 cc 对话记录,让你不再为移动文件夹而丢失记录而担忧!
值得注意的是,在研究本 skill 时,发现了一些关于 skill 触发的限制,也正暗合我最近对我们 Lovstudio.ai 官网 skills 的一些架构调整思考:
claude code 官网关于 skill 窗口的限制
Lovstudio.ai 计划对 skills 做领域分层
搬家之前、搬家之后、修复之后
你在用 Claude Code 和一个项目聊了一两周,几十小时对话、几百次工具调用、几万字上下文全在里面。某天你觉得这个项目应该归档到别处,或者目录命名该统一一下,或者单纯就想清理一下 ~/ —— 一个 mv 就搬走了。
然后你 cd 到新路径,敲 claude --resume:
No conversations found
claude --resume 无法找到之前的对话
回旧路径(已经是空目录了)—— 也没有。
这是个几乎没人谈、但一旦踩到就很疼的坑。只要你是会整理自己文件系统的那种人(我身边不少知识工作者都是),你迟早会撞进来一次。撞进来的那次通常也不会立刻损失重要数据,只是"哎?我昨天那个会话呢?"然后你就放弃了,另开一个新会话重讲一遍上下文。
但次数多了你会发现:Claude Code 的会话历史,其实是被你随手的文件整理动作慢慢磨掉的一种资产。
所以我把这个问题做成了一个 Claude Code skill,叫 lovstudio:cc-migrate-session。
装上之后你不用再记任何命令 —— 在任何会话里随口说一句 "我把项目搬到了 /new/path"、或者 "本项目之前是在 /old/path"、或者 "claude --resume 找不到历史了",CC 就会自动唤起这个 skill 把会话迁过去,迁完提示你重启到新路径 --resume,上下文立刻续上。
下面讲一下这个 skill 是怎么想的、怎么装、以及中间我踩到的一个所有现有方案都漏掉的细节。
Skill 是 Claude Code 这半年最值得关注的生态扩展方式之一 —— 它比 slash command 更"隐形"、比 plugin 更轻,Anthropic 自己给它的定位就是"让 Claude 在需要的时候自己调用的能力包"。而且它不只能在 CC 里用 —— 龙虾、以及其他兼容 Claude Code skill 规范的客户端都能装,同一个 skill 写一遍,多处生效。
cc-migrate-session skill, at Lovstudio.ai skills
最简单的装法,一条命令:
npx skills add lovstudio/cc-migrate-session
装完重启 CC,随便开一个会话说"我把项目搬到了 /xxx"试试 —— 它会自动触发、先 dry-run preview 给你看、确认后执行。
龙虾用户:直接在 app 里打开 "Manage Skills",搜 cc-migrate-session 一键安装,和 CC 里的体验是对齐的。
或者上 Agentskills.io[1] 搜 cc-migrate-session,网页直接一键装。
agentskills.io 首页
(如果你更喜欢自己手动,clone 仓库再 symlink 到 ~/.claude/skills/ 也行,但 npx skills add 会帮你处理路径和多客户端差异,推荐这个。)
触发方式就是自然语言。我给这个 skill 写的 description 和 when_to_use 里埋了一组中英混合的触发短语:
你不用背,这些只是 LLM 做 skill 匹配时的锚点 —— 你用自然语言描述你在做什么,CC 自己会判断该不该调。
要写这个 skill,第一步是搞清楚 CC 到底把会话存在哪、怎么存。
Git 的决定很直白:每个项目自己的历史放在项目内部的 .git/ 里。搬家的时候整个目录 mv,.git 跟着走,git log 永远能看到所有提交。这是一种项目自包含的世界观。
CC 的决定正好相反:所有项目的会话历史放在全局中心仓库~/.claude/projects/ 里。每个项目按它的绝对路径编码成一个 slug 目录,用这个 slug 去反查。
Git 把历史塞进项目里,CC 把历史存在一个中心仓库,所有项目都指回去
规则非常简单 —— 把绝对路径里每一个不是 [A-Za-z0-9] 的字符替换为 -:
每个 slug 目录下是若干 <session-uuid>.jsonl。打开任意一个,每一行是一个 JSON 事件,字段里都带着一个 cwd,记录当时那条消息发生时的绝对工作目录。
这套存储是典型的 append-only event stream[2] 设计 —— 会话不是可变文档而是事件流,只追加不改写,重启/崩溃/强退都不丢数据。这个决定本身很漂亮。
Milvus 这篇博客把 CC 存储为什么这么稳拆得很清楚
真正让搬家出问题的是另一层 —— 路径就是 ID。CC 把"这是哪个项目的会话"和"这个项目当前在哪个绝对路径"彻底等同了。slug 是路径,jsonl 每一行还在重复确认"我当时在哪个路径"。整个会话身份完全由文件系统位置定义,位置一变,身份就没了。
所以一个最小完备的迁移动作是什么?按上面的存储模型推:
cwd 字段改掉 —— 从旧绝对路径改成新绝对路径(精确匹配 + 前缀匹配,因为子目录 cwd 也可能出现)这两步做完,cd <新路径> && claude --resume 就能看到历史。我的第一版脚本就是这两步,10 行代码,跑起来确实 work。
然后我发出去了。然后我自己真用了一次。然后发现了一个谁都没在文章里提过的坑。
在开自己的 repo 之前我去几个 CC 社群和 GitHub issue tracker 翻过一圈。
结论是:这个问题在过去一年里被独立地、反复地提出过至少七八次,但从没被 Anthropic 正式解决。
最刺眼的一个是 Anthropic 官方仓库的 Issue #34115 — "Folder no longer exists" when project paths change — no recovery path, requires manual binary DB edits[3]。
Issue #34115,报完被关成 duplicate,问题仍然存在
报告人详细罗列了恢复一次会话需要编辑的四处状态:
他的原话:
"This took multiple hours of investigation and several failed attempts to fix for one user. It should not be this hard."
Issue #34115 最后被关成了 duplicate。同样被关掉的还有 #27473[4]、#5768[5]、#3473[6]、#19707[7]、#36937[8]。都是一个意思,都没 fix。
中文社群里也有碎片。一位朋友在群里说:
"有的,之前也遇到了,想直接迁移,结果只能查到索引,原来的对话记录文件直接消失了。"
这位大概率是在 Mac 的 ~/Library/Application Support/claude/ 里动了 LevelDB,所以"索引还在,文件没了"。
也有已经动手写过的。`@curiouslychase` 的 "Rescuing Your Claude Conversations When You Rename Projects"[9] 做了个 claude-mv bash 脚本,`gwpl` 的 gist[10] 也给了几乎一样的手工流程。
curiouslychase 的 "Rescuing Your Claude Conversations"
gwpl 的 gist,同一个解决方案的手工版
逻辑和我第一版一样 —— rename slug 目录 + sed 改 jsonl 的 cwd。
他们漏的那一刀,和我第一版漏的是同一个:文件 mtime。
把 slug 目录 copy 过去、把每个 jsonl 里的 cwd 从旧路径改成新路径 —— 到这里为止,cd <新路径> && claude --resume 确实能看到历史。
但列表乱序。
全部顶在最上面,列表失去意义
迁移过来的会话,不管它实际发生在一周前还是昨天,统统冒到 resume 列表最上面,排在我刚刚才在新路径里开的那个会话前面。列表变得毫无意义。
我一开始以为是 --resume 有什么奇怪的排序逻辑。不是。ls -lt 一看就明白:所有迁移过来的文件的 mtime 都被重置成了复制那一刻。cp / fs.copyFileSync / Python 的 shutil.copy(不是 copy2)—— 大部分拷贝方式默认都把 mtime 设成"现在"。
CC 的 --resume 列表正是按文件 mtime 倒序排的。
所以社区那几个方案 —— mv 目录 + sed 改 cwd —— 在技术上是正确但不完整。mv 本身是保留 mtime 的,所以用 mv 那一派的方案里这个问题被掩盖了;但 mv 在跨分区、跨挂载点、或者你想"copy 而不是 move 留个备份回滚"的时候,会退化为 cp + rm,mtime 就丢了。我自己正是因为想保留旧目录做 backup 才用 copy,撞进来的。
修复很短:拷贝每个 jsonl 后用 utimes 把 atime/mtime 从源文件恢复过去。如果旧 mtime 已经丢了(比如之前已经迁移过一次),还有一个兜底 —— 每条 jsonl 消息里都带 timestamp 字段,读最后一行非空消息的 timestamp 然后 touch -d 回去即可。这是 append-only event stream 设计的一个意外好处:时间信息是冗余的,文件系统层的时间戳丢了还能从数据流里重建。
这一刀的成本是两行代码。但它是"把会话找回来"和"把会话找回来并且仍然好用"之间的差别。我把这个修复从 0.1.0 升到了 0.1.1,也算这个 skill 真正 ready 的标志。
加了 mtime 保留的 0.1.1
做成一个 skill、而不是一个你要记住名字的命令行工具,对我来说是这个项目最重要的决定。
整理磁盘是一个不预设的动作。你不会在 mv 之前先打开某个 README 想"等会我要跑那个迁移工具叫什么名字"。事情是反过来的 —— 你先搬了,搬完发现 --resume 空了,然后才想起来"诶这事应该有工具吧"。
这正是 skill 存在的意义:你不用记它叫什么,CC 自己判断"你现在描述的事情"和"我手上有哪个 skill"匹配不匹配。Skill 把"工具发现"这一层也交给了 LLM。
我给 lovstudio:cc-migrate-session 写的 description 和 when_to_use 就是这个思路 —— 不堆形容词,堆真实用户会说的原话:"本项目之前是在"、"claude --resume 找不到"、"我把项目搬到了"。这些是 CC 在判断"当前情境是否要调这个 skill"时的锚点。
底层其实有一个 npm CLI(`@lovstudio/cc-migrate-session`[11]),skill 只是一个智能封装。但对 99% 的用户来说,知道"装了这个 skill 之后随口说一句话就能用"就够了 —— 那个 npm 包是我自己调试和维护用的,大部分人一辈子不用敲 npx。
这也是我更看好 skill 而不是 plugin 的原因。Plugin 要求用户预先知道它存在、预先去安装、预先去配置;skill 是在用户真正需要它的那一刻才浮出水面。对"整理磁盘"这种半年一次、但每次都痛的场景,这种触发逻辑才是对的。
CC 生态现在有一个有意思的现象 —— Anthropic 把 CLI 内核做得很好,但会话治理这一圈留了大量空白:迁移、导出、归档、跨机检索、GUI 化 —— 每一块都有社区的人在做自己的小工具。
前两天看到 `LKbaba/Claude-code-ChatInWindows`[12] —— 把 Claude Code CLI 包成原生 VS Code GUI,当天就同步了 Opus 4.7 和 xHigh 思考强度。
LKbaba 把 CC CLI 包成了原生 VS Code GUI
龙虾(Lobster)做的是另一个方向 —— 把 skill 生态做成给普通人用的 GUI,不懂命令行的知识工作者也能一键安装。
每个人都在挖自己踩到的坑自己填,而且填的方式越来越"让别人装了就能用" —— 要么是 skill,要么是 GUI app,要么是一键安装市场。我觉得这个趋势是对的:Anthropic 把生态的地基和 CLI 做好,具体的工作流由社区来补,补的形式是对用户来说无需学习成本的 skill 或 app,而不是每人一份藏在 dotfiles 里的 bash 脚本。
写完、发完、回头看,有几个感受值得从这件小事里抽出来:
第一,路径耦合是一种普遍的技术债。 Git 选的是"身份住在项目里",代价是你不能跨项目检索历史;CC 选的是"身份住在全局索引里",代价是搬家就丢历史。两种设计都合理,但后者必须在产品层给出迁移工具,不然用户做的任何整理行为都被偷偷惩罚。Anthropic 在 2026-03 的 Issue #34115 里被直接指出这一点,到现在仍然没动作。
第二,"大多数人没发现"不等于"问题不存在"。 这类问题只有真的在整理自己文件系统的人会撞到,dev 群体里不是多数派,但知识工作者里是。做工具的人要对这种"小众但重要"的场景有敏感度。
第三,Skill 改变了工具分发的默认形态。 过去写一个小工具要想清楚"怎么让用户知道它存在、怎么让用户愿意装、怎么让用户记得用";现在可以只想第一件事,后两件交给 CC 的 skill 匹配机制。这对"低频但刚需"的长尾工具是巨大的解放。我自己接下来做小工具的默认形态都会是 skill 优先。
第四,也是最直接的 —— 别在 Claude Code 跑着的时候 mv 项目目录。 要搬就先 exit、再搬、再让 skill 迁移、再重新开 session。这不是工具能救的,是纪律。
搬家这件事本身不是问题,问题是搬之前没先 exit
这个 skill 目前只针对 Claude Code 的会话存储做适配 —— 因为 CC 的 ~/.claude/projects/<slug>/*.jsonl 结构是我调研清楚、测试充分的部分。
其他 agent runtime(Codex CLI、Cursor Agent、龙虾自己的 agent 模式、以及各种 Claude Agent SDK 包的第三方客户端)各自有不同的会话持久化方式。有的完全不落盘,有的用 sqlite,有的用自家云端 —— 目前不在这个 skill 的范围内。
如果你在其他平台上也遇到"搬家之后上下文找不到"的问题,欢迎评论或在 lovstudio/cc-migrate-session[13] 开 issue 告诉我是哪个工具、大概的存储位置长什么样、你的痛点具体是什么。积累到一两个之后我会考虑把这个 skill 拓成一个更通用的 agent-session-migrator,或者针对每个平台单独做一个 skill。
我对这类"会话治理"的工具感兴趣,也有意愿做 —— 但前提是它确实是大家共同的痛点,而不是我一个人的 edge case。
一条命令装好:
npx skills add lovstudio/cc-migrate-session
龙虾用户也可以直接在 app 里 "Manage Skills" 搜 cc-migrate-session 安装。
装完重启,在任何会话里说一句 "本项目之前在 /old/path" 或 "我把项目搬到了 /new/path" 就行。
已经被 mv 过一次、历史好像丢了的:大概率没丢,只是还躺在旧 slug 目录里:
ls ~/.claude/projects/ | grep <你记得的路径里某个片段>
找到之后直接在会话里说"本项目原来在 <你找到的那个旧路径>",skill 会把它迁过来。
会话的半年记忆,值得比 cp -r 多花十秒。
[1] agentskills.io, https://agentskills.io
[2] append-only event stream, https://milvus.io/blog/why-claude-code-feels-so-stable-a-developers-deep-dive-into-its-local-storage-design.md
[3] Issue #34115 — "Folder no longer exists" when project paths change — no recovery path, requires manual binary DB edits, https://github.com/anthropics/claude-code/issues/34115
[4] #27473, https://github.com/anthropics/claude-code/issues/27473
[5] #5768, https://github.com/anthropics/claude-code/issues/5768
[6] #3473, https://github.com/anthropics/claude-code/issues/3473
[7] #19707, https://github.com/anthropics/claude-code/issues/19707
[8] #36937, https://github.com/anthropics/claude-code/issues/36937
[9] `@curiouslychase` 的 "Rescuing Your Claude Conversations When You Rename Projects", https://curiouslychase.com/posts/rescuing-your-claude-conversations-when-you-rename-projects/
[10] `gwpl` 的 gist, https://gist.github.com/gwpl/e0b78a711b4a6b2fc4b594c9b9fa2c4c
[11] `@lovstudio/cc-migrate-session`, https://www.npmjs.com/package/@lovstudio/cc-migrate-session
[12] `LKbaba/Claude-code-ChatInWindows`, https://github.com/LKbaba/Claude-code-ChatInWindows
[13] lovstudio/cc-migrate-session, https://github.com/lovstudio/cc-migrate-session/issues
53AI,企业落地大模型首选服务商
产品:场景落地咨询+大模型应用平台+行业解决方案
承诺:免费POC验证,效果达标后再合作。零风险落地应用大模型,已交付160+中大型企业
2026-04-18
如何用 Skills,高效完成产品经理的工作?
2026-04-18
ima skill 上新 笔记列表支持排序了
2026-04-17
把工作流都打包成Lovart Skill,现在,我也是设计总监了
2026-04-17
一文讲透:Harness Engineering即控制论!
2026-04-17
用Hermes封装并开源一个重要skill:从飞书文档一键发布到微信公众号
2026-04-17
Skill 和 CLI:经验指导能力,能力丰富经验
2026-04-16
我做了个 Skill:让 AI 帮你生成 Logo 和图标
2026-04-16
Chrome 推出 Skills:让浏览器进化为你的 AI Agent,附完整启动指南。
2026-04-05
2026-03-03
2026-03-04
2026-03-03
2026-03-17
2026-03-10
2026-03-17
2026-03-05
2026-03-26
2026-03-05