ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

claude-mem:给Claude加上跨会话记忆层的实践指南

claude-mem:给Claude加上跨会话记忆层的实践指南 1. 跨会话失忆Claude落地Agent时的第一道坎如果你跟我一样把Claude Code当成日常开发的主力助手迟早会遇到一个很拧巴的场景上个会话里刚讨论完的接口设计、写进代码里的约定、排除过的坑换个新会话再问Claude表现得像个第一次见面的陌生人。这不是它变笨了而是所有大模型对话默认都是无状态的——每次会话开始时模型手里只有System Prompt和上下文窗口里的内容一旦会话结束记忆就清零。很多人第一反应是上下文窗口不是有200K吗够大了吧。窗口大确实能装下更多内容但它解决的是单次会话内信息量的问题不是跨会话连续性的问题。我自己试过把历史对话全文塞进System Prompt效果很差一是Token占用太高一次会话光历史就能吃掉几万Token二是噪音太多真正有用的决策散落在大量闲聊和调试过程里模型反而被无关信息干扰三是成本问题每次请求都要重新计算这些Token的费用和延迟。这套方案的另一个变种是手动保存关键信息——把结论复制到笔记文件里下次再粘给Claude。偶尔用还行一旦项目复杂起来就崩了你会忘记录入、忘了在哪条笔记里、笔记和代码不同步。真正能扛住长期使用的做法是让工具自动完成记忆的“写入—整理—召回”全过程。这就是我搞 claude-mem 的出发点给Claude加一个轻量、可检索、跨会话的记忆层让它在下次见面时还记得你是谁、你做过什么、你有哪些偏好。这个名字没什么玄机就是 Claude memory 的缩写。它不是Claude官方自带的功能而是在Claude API和Claude Code之上搭建的辅助组件。你可以把它理解成一个外挂的“第二大脑”平时聊天过程中它默默记录那些值得留存的判断和偏好新会话开始时它把相关记忆重新放回到Claude的眼前。做这个项目之前我调研过市面上的记忆方案有的太重、依赖外部数据库有的太傻、只做简单的全文存取claude-mem 的设计原则就三条本地优先、结构化存储、按需注入。2. claude-mem的记忆分层会话、档案与检索各司其职2.1 为什么不能只存聊天记录早期版本里我干过一件笨事把所有对话全文写入SQLite等新会话开始时把最近几十条消息全捞出来塞给Claude。结果很快就发现两个问题存储膨胀得厉害一周对话就攒了几十万字召回的“料”太杂有用的事实淹没在废话里。后来我读了一些Agent记忆系统的设计思路才意识到记忆不能是“堆料”必须分层。claude-mem 把记忆分成三层各管各的互不干扰记忆层存什么存储形式谁来触发写入短期会话记忆当前对话上下文、临时状态内存 JSON对话进行中实时写入长期档案记忆用户偏好、项目约定、关键决策SQLite 结构化条目会话结束时总结写入检索记忆历史对话摘要、关键技术片段SQLite 全文索引异步后台处理短期会话记忆解决的是“一次长对话内部的连续性”Claude原生能力已经很强claude-mem 不太插手这一层只在必要时做进度标记。长期档案记忆是核心它保存的是“隔了好几天还能用”的信息。检索记忆则是兜底当档案里没有现成答案时通过全文搜索从历史对话里找线索。2.2 档案条目的最小单位长期档案如果只存一段段的总结文字时间久了还是变成新的大杂烩。所以我把档案拆成最小可检索的记忆条目每条只记录一个独立的事实、偏好或决策结构大概是这样的{ id: mem_8f3a2c, type: preference | decision | fact | todo, content: 用户不接受 YAML 配置复杂嵌套偏好扁平结构, source_session: 2025-06-11-feature-refactor, created_at: 2025-06-11T14:20:00Z, last_accessed: 2025-06-20T09:00:00Z, tags: [config, coding-style], confidence: 0.9, expire_at: null }type字段决定了记忆的优先级和过期策略。比如preference类条目会一直保留直到用户明确推翻todo类条目在确认完成后自动标记失效fact类条目如果跟后续新条目产生冲突系统会留着两条并标记为“待复核”。content的写法也有讲究后面我会专门讲什么样的表述才是好记忆。2.3 为什么不把所有东西都做成向量现在一提记忆就默认要上向量数据库我一开始也踩过这个坑。后来发现对 claude-mem 这种规模来说全文索引 关键词过滤很多时候比向量检索更稳。原因很简单项目里的代码规范、用户偏好这类记忆本质上是精确匹配信息你搜“REPL 风格配置”就得把那条配置找出来语义扩展反而容易带偏。SQLite 自带的 FTS5 全文索引够快零依赖又不用单独起一个服务。向量检索我也保留着但只用在“模糊联想”场景比如用户说“我不喜欢那套复杂的流程”向量检索可以把“流程繁琐、配置多、嵌套深”相关的记忆召回。大部分场景下先做标签过滤 全文检索再补少量向量召回已经比单纯用向量好用得多而且本地跑的延迟基本可以忽略。3. 写入与召回链路一次对话是怎么变成长期记忆的3.1 触发时机总结与归档策略记忆不是鸡毛蒜皮都记也不是等对话结束才一口气处理。我总结了四个写入时机即时写入对话中出现明确的偏好表达、决策结论、用户纠正行为时立刻生成一条档案条目。比如用户说“这个方案太绕了以后接口名直接叫run()”这句话30秒内就该进数据库。分段总结单次会话超过一定轮数我设的是 30 轮后对前面较旧的部分做局部总结释放上下文空间。会话结束归档会话结束后把所有未归档的重要信息汇总成摘要并跟已有档案合并。定期压缩每周对旧记忆做一次“记忆保鲜”检查压缩互相重复的条目失效的标记删除。分段总结这个动作很关键。上下文窗口再大也有上限如果一次会话聊了100轮后面基本是在“边聊边忘前面”。claude-mem 会监控 token 用量超过阈值默认是窗口的 70%就触发一次中间总结把靠前的次要对话压缩成几条摘要然后告诉 Claude“以下是此前的阶段性进展摘要继续当前任务。”实测下来长会话的有效处理能力明显提升不会聊到一半模型开始“失忆”。3.2 召回新会话开场怎么“想”起来新会话建立时claude-mem 做的事情其实是一套“记忆唤起”流程注入用户档案卡片包含姓名/项目角色/核心偏好控制在 300~500 token 内从历史会话摘要里筛选最近活跃的 5~10 条作为“最近在忙什么”的上下文扫描当前开场消息中提到的关键词比如文件名、技术栈、动作指令做一次检索召回把召回结果按相关性和时间排序截断到预设的 token 预算内统一注入 System Prompt。这套流程在 Claude Code 里可以通过 MCP 工具暴露出来让 Claude 自己决定“要不要翻记忆”。我会在下一节详细说接入方式。重要的是注入不是越多越好。Token 预算内放10条强相关记忆效果远好于塞100条弱相关记忆。我给 claude-mem 的默认注入上限是 1500 token超过这个数宁可漏一点也不污染主线。3.3 记忆的置信度与冲突处理写记忆容易改记忆难。假设上周用户说“后端用 Python”这周又说“迁移到 Go”两条记录都在库里新会话召回时模型看到两个相反的结论肯定会懵。claude-mem 的做法是不直接删旧记录而是给每条记忆加confidence和supersedes_id字段。新产生的记忆如果与旧记忆冲突新条目覆盖时会把旧条目标记成superseded但保留历史以便追溯。这点我觉得是记忆系统最容易被忽视的地方。很多人的第一版记忆工具只会“增”不会“改和删”结果用几个月后库里全是过时的垃圾记忆召回质量直线下降。claude-mem 的清理机制我放在最后一节细讲但设计上从第一天起就要把“记忆会过期”当成默认前提。4. 部署与接入把claude-mem挂到Claude Code旁边4.1 环境准备与初始化claude-mem 的部署方式我刻意做得比较轻不依赖 Docker、不依赖云服务本地一个进程就能跑。环境中只需要 Node.js 18 和 SQLiteNode 生态里我直接用的better-sqlite3省去了单独装 SQLite 的麻烦。初始化流程分三步安装依赖、初始化数据库结构、配置 MCP server 地址。数据库文件默认放在项目的.claude-mem/目录下方便跟着项目走如果你有多个项目共用一个记忆库也可以把DATA_DIR指到同一个路径。npm install -g claude-mem claude-mem init --data-dir .claude-mem初始化后会在.claude-mem/下生成几个文件mem.db核心数据库、config.json记忆策略配置、log/运行日志。config.json 里可以调的东西不少我最常用的几个配置项是max_history_retrieve召回的条目数量上限、summary_topic_threshold会话轮数达到多少触发中间总结、token_budget每次注入记忆的 token 预算。4.2 以 MCP Server 方式接入claude-mem 对 Claude Code 的接入走的是 Model Context ProtocolMCP。MCP 可以理解为“给模型外接工具的标准接口”Claude Code 本身就是 MCP 客户端的典型实现。把 claude-mem 变成 MCP server 之后Claude 在对话过程中可以直接调用这几个工具工具名作用何时调用remember主动写入一条记忆Claude 认为用户表达了一个应记住的信息时search_memory检索与当前问题相关的历史记忆新任务开始、用户问题看起来依赖旧上下文时summarize_session对当前会话做一次阶段总结会话接近 token 上限或结束update_memory修改/标记记忆条目用户纠正了过去的结论时MCP server 的注册配置很简单在 Claude Code 的配置文件里加一段{ mcpServers: { claude-mem: { command: claude-mem, args: [serve], env: { DATA_DIR: ./.claude-mem } } } }配置完成重启 Claude Code输入/mcp能看到 claude-mem 在线就可以正常使用了。我建议先用一句话测试“记住我所有测试环境的数据库统一用 test 作密码前缀。”然后新开一个会话问“测试环境数据库密码有什么规范”如果能正确回忆出来链路就是通的。4.3 纯 API 场景的接入方式如果你不是在 Claude Code 里用而是通过 Claude API 搭建自己的应用那 claude-mem 也可以直接作为库来调用不需要 MCP。核心就两个函数写入和检索。from claude_mem import MemoryClient mem MemoryClient(~/.claude-mem/mem.db) # 写入一条记忆 mem.remember( content用户在代码评审中强调函数命名要自解释禁止用单字母变量, typepreference, tags[code-review, naming], ) # 检索与当前任务相关的记忆 hits mem.search( query代码规范 命名 评审, limit5, )这种 API 集成很适合自建 Agent 产品。我在一个内部工具里就是这么做用户每天第一次打开小程序先把记忆库里跟该用户相关的偏好全部捞出来组装成 System Prompt相当于给每个人都配了“专属人设”比每次从零开始的效果强太多。5. 让记忆不变味写入规则、压缩提示与人工复检5.1 值得记忆的其实就四类记忆系统最怕“什么都记”。我对比过几个版本的写入规则最后把“值得记”的信息收敛成四类偏好与风格用户明确说喜欢/不喜欢什么。特征是从句里带“以后”“永远”“都要”这类绝对化表达。决策与结论在多个可选方案里拍板选了一个。特征是提到“决定”“不选”“就用它”。项目事实能减少重复提问的稳定信息比如技术栈、目录约定、部署环境地址。待办与承诺明确说“下一步要做什么”“下周解决什么”。判断要不要写入的简单标准是这句话如果一周后还成立吗如果成立就值得记如果只是当前上下文里的临时信息就不记。“今天先把登录接口写完”是不该记的“用户习惯用 POST 而不是 PUT 来做更新操作”才是该记的。5.2 压缩提示词决定记忆的质claude-mem 依赖一次 Claude 调用来做会话总结和记忆抽取压缩提示词直接决定了产出的记忆质量。我迭代下来的模板核心大概长这样你正在为一个长期使用的记忆系统抽取信息。 请从以下对话中找出值得长期保留的内容并输出为JSON条目 1. preference用户的明确偏好必须带有“喜欢/不喜欢/希望/不接受”等语气 2. decision明确的决策结论带方案对比的更佳 3. fact稳定的项目事实能避免未来重复提问 4. todo明确的后续行动但只保留超过一周时效的 过滤掉问候、客套、调试过程的中间状态、临时的进度信息。 每个条目控制在 30 字以内使用陈述句避免“用户说/用户认为”这类转述前缀。最后一句“避免转述前缀”很关键。如果提炼出来的记忆是“用户说他认为接口应该统一前缀”这句话到了下次调用里就变成一种待确认的八卦信息。应该直接记成“所有内部接口统一使用 /api/internal 前缀”。Claude 能不能正确做出这种改写就看提示词有没有讲清楚“你要写的是结论本身而不是描述谁说了什么”。5.3 定期人工复检记忆库版“断舍离”自动写入再强也得给人留一个检视入口。claude-mem 提供一个简单的审查命令把最近新增的记忆条目按 type 分组列出来claude-mem review --limit 30我自己的习惯是每周花十分钟过一遍。重点看三类条目已经失效的 todo 删掉重复描述的 preference 合并content 写得模棱两可、只有自己看得懂的当场改写成明确陈述句。别小看这十分钟记忆库的长期可用性基本就是靠这种人工复核撑起来的。纯粹依赖自动抽取的库三个月后要么肿胀不堪要么专精度越来越差。6. 实测避坑Token开销、矛盾记忆与数据清洗6.1 Token开销没有想象中大但控不住就麻烦有朋友一听“每次对话都注入记忆”立刻算账1500 token 的注入一天 100 次对话一年下来费用可观。实际用下来开销大头不在注入而在后台总结。每 30 轮触发一次中间总结、每次会话结束再来一次归档总结等于把部分对话内容重新喂给模型处理一遍。claude-mem 里我给两次总结都开了“模型降级”配置优先级高的总结用强模型批量处理、不那么重要的总结用中等模型成本能压掉一半以上。如果你的预算极其敏感还可以把中间总结的触发轮数调高比如 50 轮。会话短就基本不触发真正触发总结的只会是那种聊了几十轮的长对话这类场景多花点钱是值得的。6.2 矛盾记忆的处置不能靠“删旧存新”前文提到 claude-mem 用supersedes_id保留冲突记录。实际用下来这个设计的价值主要体现在“用户自己改主意了”这件事上。用户今天说“不要慢查询优化”下个月可能又说“响应太慢了得优化一下”。如果旧记忆直接删除新召回时没有历史对照模型可能把用户的新需求当成孤立需求来处理反而少了上下文。正确做法是新记忆写入时加上“取代某条旧记忆”的关系但召回模块默认只暴露最新的那版。只有当用户主动追问“我之前说过什么”时才把被取代的旧记忆翻出来。这个“可追溯但不主动打扰”的策略我实测下来体验最好。6.3 数据量上来之后建立索引与淘汰机制记忆库用久了SQLite 里会有几万条记录。不做清理的话FTS5 全文搜索会明显变慢。我的处理策略是三管齐下召回只查last_accessed最近 90 天内的活跃记录冷数据不入常规查询每周定期把已过期 todo 和重复条目物理删除对单条超长内容做切分避免一条记忆占几个 KB、检索和注入都难受。你还可以用一个更狠的淘汰策略把记忆库当成“栈”总量超过 N 条时自动把confidence低且长时间没被访问的记录压缩进归档表主表永远保持轻量。这套淘汰机制配合前面说的人工复检记忆库用上一年也不会有臃肿感。6.4 隐私边界本地优先不是一句空话因为 claude-mem 的所有数据都落在本地 SQLite 文件里我敢在里面记录一些真实偏好和业务决策不会担心数据被拿去训练或泄露。如果你要多人协作或同步可以只把加密后的归档文件推到自己的私有存储里不要让原始记忆库离开本地。接入 Claude API 时会涉及把对话内容发送给模型做总结这一点没办法完全避免毕竟是靠模型提炼记忆。我的建议是敏感项目单独用 claude-mem 配置一个开关可以关闭自动总结改成人工复制重要内容进去手动录入。这个开关大多数情况下用不到但真到了项目敏感度高的时候它会保住你的底线。最后再分享一点个人体会搭 claude-mem 最大的收获不是省了多少 Token而是它逼着我把“什么信息值得让 AI 记住”想清楚了。以前我依赖上下文窗口的无限续杯总觉得自己跟 AI 的每次合作都是“露水情缘”有了记忆层之后同一个项目里 Claude 的产出质量一次比一次贴合我的习惯这种积累感是单靠调 Prompt 换不来的。如果你正在做 Agent 类项目建议从第一天就把记忆层的接口留好——后面数据攒多了再回头补成本和复杂度都会大得多。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进