Claude Code 持久记忆实战:用 claude-mem 告别每轮对话重来
最近一段时间我几乎每天都在和 Claude Code 打交道。模型本身的写码能力没得说真正让我上火的是它的记性——每次新开一个会话它就完全不记得上一个会话聊了什么。同一个架构决策我上午刚跟它确认过下午换个会话继续写它又能当成一个新问题重新讨论一遍。我试过把背景写进项目说明文件靠手工维护最后还是被一堆过时信息拖垮。后来我把 claude-mem 这个专门给 Claude Code 做持久记忆的工具接进工作流情况才算彻底改观。这篇就聊聊它到底做了什么以及我实际使用中总结下来的细节和坑。1. 先搞懂 Claude Code 为什么永远在“重新认识你”1.1 一个会话等于一次“重启”Claude Code 的会话模型本质上是无状态的。所谓“上下文”指的是当前这轮对话里输入窗口能看到的全部内容。你关掉终端下次再敲claude进入一个新会话系统只会重新加载项目文件、全局配置、模型指示这些静态信息不会自动把上一轮对话的每一句话都带过来。这和你在 IDE 里写代码不一样文件是存在磁盘上的聊天内容默认不会落盘成可复用资产。很多人会把“模型记不住”理解为模型能力问题其实不完全是。Claude 的知识面很广但“我们这个项目里刚刚决定用 Redis 做缓存”这件事不在它的大脑里。它唯一的依据就是当前给它的文本。就算上下文窗口再大你也不能真把所有历史对话全塞进去一方面成本高另一方面大量无关内容会被模型一并纳入考量范围反而干扰它对当前任务的理解。所以问题的核心不是“模型记不住”而是“我们没给它一套能读懂的交接文档”。1.2 手动维护项目说明文件的尴尬大多数用过 Claude Code 的人第一反应都是把关键约定写进项目根目录的说明文件。这个文件会在新会话启动时自动加载相当于给模型配了一份工作手册。思路本身完全正确但维护起来非常痛苦。我踩过的典型场景是我和模型在对话里折腾了一个多小时最终敲定了某个模块的拆分方案。代码改了聊天窗口关了项目说明文件还是两个月前的内容那次讨论的结论只存在于我和它的对话记录里。偶尔想起来该更新文档了可连续几个会话积累了几十条零散结论整理进去要花额外时间还总担心漏掉真正重要的部分。写是写进去了但写得太啰嗦。模型每次启动都要读一大堆陈旧规则甚至被某些过时描述带偏问出来的方案反而不如不写的时候。这些问题的本质都一样人工记忆沉淀的速度跟不上对话产生新信息的速度。你必须在会话结束后有一个环节能把高价值的结论自动捞出来、整理好、放回下一次会话的输入里。这恰恰是 claude-mem 这类工具存在的理由。1.3 claude-mem 的定位不是“存档”而是“记忆助理”有人可能会问Claude Code 本身不是有会话日志吗把日志文件翻出来重新喂进去不就行了这么想就进了误区。claude-mem 不是聊天记录归档工具也不是把 session 文件堆在一起的日志系统。它的定位更像一个贴身助理你在和 Claude Code 开会它在旁边旁听会后自动提炼出“你们今天决定了什么、你更偏好哪种方案、项目里有哪些坑”写成轻量记录下次你再开会它会提前把相关的几张笔记放到你桌上。我用下面这个表说明传统存档和记忆助理的区别对比维度传统会话日志/存档claude-mem 这类记忆层数据形态完整对话流水冗长提炼后的短记忆条目读取方式人工翻找或全量塞给模型按需检索只注入相关内容维护成本基本不可维护定期 review 即可适合场景审计、回溯、取证复用决策、延续上下文这个“旁听、提炼、复述”的链路才是它和存档工具最本质的差别。理解了这一点后面看它的工作原理就不会迷糊。2. claude-mem 的完整工作链路从一段对话到一份可复用记忆2.1 监听阶段后台长驻抓取会话记录claude-mem 要工作第一步是拿到 Claude Code 的会话数据。它会在本地跑一个常驻进程监听 Claude Code 的会话记录目录。你正常用 Claude Code 写代码、聊天、跑命令它就在后台上“看着”。一旦有新的对话记录落盘它立刻做增量处理而不是等会话结束再批量扫一遍。这里有个实现细节值得一提为什么不直接定期扫描整个目录而是要用文件监听因为全量扫描虽然简单但每次都要重新处理已经见过的老数据既慢又容易重复写入。事件驱动的好处是只处理新增内容实时性也更好。你可以把类似 claude-mem watch 的后台进程常驻在终端里或者交给系统服务去管。但有一个经验同一个项目下不要同时跑多个监听进程否则多个进程抢着写同一个索引很容易出现数据库锁冲突或者写入失败。2.2 提炼阶段哪些内容值得被记住拿到会话记录之后关键是提取。这个阶段容易被忽略但不是所有的话都该被记住。模型和你聊“今天天气真不错”或者你在调试时随口说一句“先打个日志看看”这些内容放进长期记忆里只会污染后续的上下文让模型在读记忆的时候分心。claude-mem 会做一次筛选把符合下面特征的信息挑出来你明确表达的偏好的工作方式比如“接口报错统一用同一个错误码格式发给我”。项目里做出的决策和结论比如“这个模块用 Redis不用内存缓存”。事实类信息比如“测试服务跑在 8080 端口本地启动前要先拉起依赖”。已知问题和规避方式比如“不要用某个函数它在并发场景下会死锁”。你的语气越明确工具越容易判断这是一条值得沉淀的记忆。如果你只是随口说“要不再试试看”它多半不会当作高置信度内容记录。这个判断逻辑不是简单规则匹配通常会由大模型做一轮语义抽取再结合置信度决定是否落盘。说得直白一点它在干的是一个“摘要生成”的活而不是关键词匹配。2.3 存储阶段Markdown 文件加索引提炼出来的记忆会被写成本地文件。不同版本细节会有差异但思路是一致的典型的目录结构长这样~/.claude-mem/ ├── config.toml ├── index.sqlite ├── projects/ │ ├── my-service/ │ │ ├── 2025-01-12-decision-use-redis.md │ │ └── 2025-01-13-topic-test-env.md │ └── another-project/ └── global/ └── preferences.md每个记忆文件都是一篇短小的 Markdown里面记录的是事实和结论不是逐字逐句的聊天历史并且通常会带上来源会话 ID、项目名、创建时间这些元信息。SQLite 索引负责快速检索让模型在需要的时候能通过工具接口直接查“和当前任务相关的记忆有哪些”。这里为什么要用 Markdown 文件而不是直接把内容全塞进数据库因为可读性。文件是给人看的方便你定期 review也方便手动改错。如果它只写进数据库你的 Git 版本管理、人工审阅、迁移都会很别扭。把文件和索引分开等于既保留了机器检索的速度又保留了人类可维护性。2.4 注入阶段新会话如何把旧记忆找回来光存下来没有用关键是 Claude Code 新会话开始时怎么读到。claude-mem 是通过 MCPModel Context Protocol模型上下文协议把记忆能力暴露给 Claude Code 的。你可以把它理解成一个工具架Claude Code 在需要的时候可以调用类似 memory_search 的接口去查记忆也可以按配置把最近的相关记忆主动放进上下文。这里有个反直觉的地方按需检索比全量注入更有效。全量注入看起来最省事把记忆文件全部塞进上下文但记忆文件多了以后大量无关内容会稀释模型的注意力甚至让模型把某个陈旧的旧方案当成项目现状反而降低输出质量。按需注入更像检索增强的思路只在当前任务确实需要时拉取与之相关的记忆。另外配置里通常可以设置“必须跟随”的记忆标签。比如项目级的安全规范、你明确说过“以后不要再问我是否要提交代码”这类强约束可以标记成高优先级每次会话都会主动带入。这一手很好地平衡了“上下文压缩”和“关键规则不漏”这两个需求。3. 接入 claude-mem 的实操记录含命令与配置说明3.1 安装与初始化先聊安装。这个工具迭代很快安装方式在不同时期不太一样有通过包管理器安装的有直接在 GitHub Releases 页面发二进制的也有提供一键安装脚本的。我建议直接看项目仓库 README 里当前推荐的安装命令不要死记网上某条旧命令版本一变可能就不适用了。我自己机器上目前是这样一套流程# 安装后先看版本确认命令能跑 claude-mem --version # 初始化配置和存储目录 claude-mem init执行 init 之后它会生成默认配置文件和~/.claude-mem目录。如果你希望记忆跟着项目走而不是全堆在用户目录下也可以在配置里把某个项目的存储根目录指到项目内的.claude-mem/目录下。这样项目拷贝或者团队共享时记忆能跟着代码一起走。3.2 让 Claude Code 通过 MCP 识别记忆安装完只是第一步。要让 Claude Code 在会话里真正用上记忆需要把它注册成 MCP 服务。Claude Code 的 MCP 注册方式一般是claude mcp add。下面的写法是一个典型示例具体子命令名要以你安装的版本实际输出为准claude mcp add claude-mem -- claude-mem mcp注册完以后先看一眼注册列表里有没有它claude mcp list如果列表里能看到 claude-mem 并且状态正常再随便开一个会话问 Claude Code “你现在有哪些记忆相关工具”它应该能描述出 memory_search 之类的工具。要是它说没有先检查 MCP 服务是否启动成功或者注册时填的二进制路径是否正确不要一上来就怀疑模型能力。3.3 配置项怎么调才合理配置这种东西贪多嚼不烂。我建议至少关注这几个维度配置维度作用我的建议存储路径记忆文件写到哪里个人使用放用户目录团队共享放项目目录记忆条数/相关度每次注入多少条、相关度门槛多高先小后大项目大、会话杂时不要全量忽略规则哪些目录、哪些关键词不参与记忆必须配至少忽略 node_modules、dist 等产物目录标签优先级哪些记忆必须每次注入只给安全规范、强偏好这类少量关键内容打高优先级配置修改后一定要重启后台进程或者新开一个会话再验证因为很多配置是在启动时加载的。直接改完不重启表面上没报错实际上新配置根本没生效这是最容易踩的空欢喜。3.4 日常运营查看、清理和 review记忆不是只进不出的。我给自己定了一个小习惯每周抽十分钟打开记忆目录走一圈把明显过期或者写错的记忆文件删掉、改掉。不要把这个目录当成不可动的东西它本质上是模型交接笔记的草稿本。如果你比较在意变更历史可以用 Git 管理记忆目录让每次修改都有 diff 可看。虽然这个方法看起来很原始但它能保证记忆层长期不变质。否则存得越久垃圾就越多早晚有一天模型会被一堆过期记忆带偏到时候你再想清理成本就高了。4. 我踩过的几个坑记忆膨胀、敏感信息与误提取4.1 记忆膨胀会把上下文窗口“吃”掉我第一次接入的时候为了让模型“记得全”什么都让它记结果新会话里它反而变笨了。原因很简单上下文窗口看起来很大但里面塞了一堆低质量记忆之后真正用于当前任务的空间反而被压缩。模型需要花费更多注意力去分辨哪些内容是当前任务相关的输出质量自然下降。解决思路不是“让记忆更多”而是“让记忆更精准”。我把每次注入的条数调低只保留相关度最高的几条对于过时的旧记忆定期清理而不是一直留着。记住这个工具的设计初衷它不是把所有历史都朗读一遍而是挑出最值得参考的几条放在模型面前。4.2 敏感信息混入记忆的教训第二个坑比较严肃。claude-mem 读取的是你真实会话里的全部内容如果对话里出现过 API Key、数据库连接串、内部账号等信息它很可能被当成“项目事实”存进 Markdown。而这堆 Markdown 又很容易被你自己顺手推到 Git 仓库或者同步盘里等于把一个原本只在你机器上有访问权限的数据变成了一个可以被扩散的普通文件。我的做法是几条硬规则。第一机器上不拿生产环境的密钥去和 Claude Code 讨论。第二在忽略规则里把常见的密钥文件、.env、证书文件路径全部排除。第三把记忆目录加进.gitignore除非你是专门做团队记忆共享否则不要让记忆文件默认进版本库。第四如果工具版本支持本地加密存储而你处理的数据又比较敏感优先开启这个能力。密钥这类东西宁可少记一次也不要让它躺在明文的 Markdown 里。4.3 误提取和重复记忆自动化的另一面大模型做记忆抽取准确率远不到百分之百。它会把你一时兴起的想法当成定论也会把同一个决策在好几个会话里用不同措辞各记一遍。我遇到过最典型的场景先是在会话里说“我打算把数据库迁到 PostgreSQL”后来冷静下来决定不迁了但工具已经把“计划迁移 PostgreSQL”记了下来。结果后续会话里模型反复拿着这个过期计划来问我搞得我一度以为它在故意装傻。解决方式还是靠人机结合。自动提取负责提高效率人工 review 负责兜底。重要结论我不指望记忆文件而是固定写进正式文档里claude-mem 只承担“捕获和提醒”角色。工具是好工具但别把所有信任都交给自动化。4.4 同时开多个监听实例的锁冲突还有一个小坑如果你习惯在多个终端里分别启动后台监听进程你会发现偶尔报数据库锁冲突或者写入失败。原因是多个进程同时写同一个索引文件。这类本地工具一般只支持单进程写入。解决办法很干脆全局只保留一个守护进程负责写入其他终端里的会话依靠 MCP 读取就好。一个进程负责写所有会话负责读整个架构就清爽了排查问题也简单得多。5. claude-mem 之外的记忆架构把长期记忆和会话记忆分开管5.1 三层记忆模型用熟了 claude-mem 之后我开始把项目的记忆体系拆成三层。这个模型我现在用下来很顺手层级典型载体更新方式用途全局偏好用户级配置、全局记忆文件手动维护为主所有项目通用的工作习惯、回答风格项目长期记忆项目说明文档、架构文档手动维护重要结论落定后写进文档经得起时间检验的架构决策和项目事实会话中间记忆由 claude-mem 自动提取自动为主定期 review把会话中的决策、偏好快速捕获到位这样分完之后我发现一个很有意思的变化项目说明文档反而越写越短因为不需要再急着记录所有临时讨论了自动记忆层处理了那些“还在变动中”的信息。等某个结论稳定下来我再把它正式写进长期文档相当于多了一个临时记忆缓冲区。5.2 记忆要有时间戳和来源否则就是谣言记忆系统最怕的就是来路不明。一条记忆如果没有创建时间、没有来源会话、没有明确关联的项目那它在模型眼里就和猜测差不多提供不了多少参考价值。所以我在 review 的时候主要看三样东西记录时间还新不新鲜、来源对话是否可靠、它现在还能不能和代码对得上。对不上的直接删掉宁缺毋滥。这条原则在团队里更重要。不同成员和模型聊的内容不一样自动沉淀出来的记忆如果直接共享会变成一个人人都能用、却没人负责的规则堆。我的建议是团队共享记忆必须走版本管理和 review至少要让重要记忆经过人工确认否则某个过时的临时结论很容易被其他成员当成项目规范。5.3 想让记忆真正有用先想清楚谁来消费最后聊一个容易被忽略的问题记忆的消费者是 Claude Code不是人。你会发现有些笔记写得很详细、很完整但丢给模型反而没用。因为模型读取记忆时是带着一个新的任务上下文去读的它需要的是和当前任务高度相关的精简信息而不是一篇完整的项目维基。所以记忆文件能短就短能列表就列表不要把大段背景解释塞进去。我现在的判断标准很简单如果一条记忆能在两句话内讲清楚一件事并且直接指向一个决策或一个事实它就值得留如果它需要三段背景才能读懂说明它应该进入正式文档而不是留在记忆缓冲区。这条体会是我用 claude-mem 最大收获之一。工具可以帮你省下很多手工记录的时间但它不会替你做信息架构的取舍。把什么放进长期记忆、把什么留在会话里、把什么写进正式文档依然是你自己的设计决策。最后再说一个我现在的固定操作每天结束工作前扫一眼当天的记忆文件顺手把和代码现状对不上的删掉把第二天大概率还要用的一两条标注成高优先级。第二天 Claude Code 开新会话的时候基本都知道我在干什么不再需要我从零复述。如果你也被“模型每次都要重新认识我”折腾过可以照这套思路试一试。