如果你用过 Claude Code或者接过 Claude API 自己写过自动化脚本大概率会遇到同一个场景昨天刚跟 AI 对齐的项目背景、技术栈、部署方式今天新开一个会话它又像第一次见面一样问你“这个项目跑在哪个端口”。这不是模型变笨了而是 Claude 的对话本质上有状态但状态只存在于那一次会话里。会话一关它连你叫什么都忘得一干二净。claude-mem 就是冲着这个问题来的。它的定位很简单给 Claude 加一层本地持久记忆。每次对话结束后自动从会话里抽取值得记住的信息结构化存到本地下一次新会话启动前再把相关记忆重新注入给 Claude。用了它之后AI 至少能记得你是谁、手头在做什么项目、哪些技术决策已经敲定不用你再从头讲一遍。适合长期维护同一个项目的开发者、用 Claude API 跑批处理任务的人以及想慢慢积累一个“AI 个人知识库”的玩家。这篇文章我会从设计思路、核心模块、安装配置、踩坑记录到进阶玩法完整拆一遍 claude-mem。里面所有命令和配置我都按实际使用场景写过你可以直接照着复现。1. 为什么需要 claude-memClaude 会话记忆的痛点1.1 你肯定遇到过的“金鱼脑”瞬间先回忆几个高频场景。场景一你在一个 monorepo 仓库里维护微服务A 服务的鉴权逻辑是 JWT 自定义 headerB 服务走的是 OAuth2。第一天你花了半小时跟 Claude 说清楚两套体系的差异让它帮你写跨服务调用代码。第二天早上新开会话它看到代码里有Authorization就默认是 Bearer Token完全忘了你们昨天定的自定义 header 方案。你只能重新贴一遍背景。场景二你用 Claude 批量处理文本比如把所有周报转成固定模板。第一次你给了很详细的输出格式要求AI 生成了完美结果。第二次你只是换了一批输入文本没贴格式说明它就开始自由发挥标题、段落全乱套。场景三你同时跟进两个项目一个用 Python 3.12 FastAPI一个用 Node.js 22 Hono。你不小心在 Node 项目的会话里问了一句“用 Python 写这个脚本”AI 立刻给了 FastAPI 风格的代码你才发现上下文完全串了。这些问题的根源不是 Claude 能力不够而是它没有跨会话记忆。每个会话都是独立的世界你反复提供的背景、偏好、规则对 AI 来说都是第一次见。浪费的时间都花在了重复叙述上。1.2 上下文窗口不是记忆很多人刚开始会把记忆问题和上下文窗口混淆觉得“只要把窗口调大Claude 就能记住更多”。这里需要区分两个概念上下文窗口是临时工作台持久记忆才是长期仓库。Claude API 本身是无状态的。你每次发请求传过去的是一整段历史对话模型对着这段文本生成回答。服务端不会在两次请求之间保存“上一次聊了什么”。会话结束这段历史就清了。Claude Code 这类工具虽然会在本地保留对话记录但那是原始日志不是经过提炼的记忆。上下文窗口还有一个硬约束它装不下所有历史。哪怕你硬把所有日志都塞进去token 成本会暴涨而且大量无关信息会干扰模型输出。这就是为什么需要外部记忆层——把“重要的事实”和“无关的过程”分开只把前者留到下次使用。类比一下上下文窗口像是你在白板上写的临时草稿写完顺手擦掉持久记忆像是一个笔记本你只把最终结论和关键参数记进去。claude-mem 干的就是“做笔记”这件事。1.3 claude-mem 到底解决什么问题市面上其实有不少“给 AI 加记忆”的方案我整理了一个对比看完你就知道 claude-mem 的侧重点在哪。方案做法优点缺点手动改 system prompt每次开会话前把自己写好的背景说明复制进提示词简单、可控全靠自律容易漏而且不会更新记事本 / 备忘录单独开个文件记录需要时自己粘贴灵活检索困难写多了找不到重点自己写脚本存 JSON把对话关键信息抽出来写文件完全自定义并发读写、格式解析、检索都要自己造轮子claude-mem自动抽取、存储、检索、注入全链路打通开箱即用需要一定配置和调教claude-mem 的核心思路不是“什么都记”而是“记该记的”。它会在对话结束后用模型做一次提炼输出结构化记忆并打上项目、标签、重要性等级。下次会话启动时再按照当前项目和关键词只检索最相关的几条记忆注入给 Claude。你不用管文件怎么组织、检索怎么做它就帮你完成了这件事。2. 核心模块拆解记忆从写入到读取的全链路2.1 记忆采集层从对话流里打捞线索claude-mem 要做的第一件事是把对话内容截获下来。如果你在用 Claude Code它会作为插件监听会话事件如果你在用 API它主要通过 stream 回调拿到用户的输入和模型的输出。采集不是简单地把所有对话原文存下来那样只会得到海量噪音。采集层要做的是识别“候选记忆”通常有几类用户明确说过的偏好比如“以后所有代码注释都用中文”。项目关键信息比如“数据库连接字符串在 .env 里”。技术决策比如“我们决定用 Redis 做缓存不用 Memcached”。任务约束比如“上线窗口是每周三凌晨两点”。这个过程可以基于规则也可以让模型参与。实际用下来纯规则提取会漏掉很多隐性信息所以我默认开了模型辅助提取模式。它会先把整段对话压缩成一个摘要再从摘要里抽记忆条目。代价是每次会话结束会额外花一点 token但换来的是记忆质量高很多。2.2 记忆提取层用摘要替代原文而不是复制粘贴很多人会问为什么不直接把对话原文存起来原因有两个。第一原文信息密度太低。十轮对话里可能聊了代码调试的过程、AI 的试错猜测、你的吐槽最后真正管用的结论只有一句。全存等于没存检索的时候噪音太多。第二token 成本不可控。哪怕只存几个小时的对话原文也可能有几千 token。但提炼成记忆之后真正需要保留下来的可能只有三五句话占用空间小一个数量级。所以 claude-mem 的提取层会调用一次模型按照一个固定的 JSON Schema 输出结构化记忆。大致格式类似{ memory: [ { content: 项目使用 Docker Compose 部署服务名 api-gateway暴露端口 8080, scope: project:myapp, tags: [deploy, docker, infra], importance: 0.9 }, { content: 用户偏好代码注释使用中文, scope: global, tags: [preference, style], importance: 0.8 } ] }这里的关键是importance字段。它决定了这条记忆在多大程度上值得保留。阈值太低了会存一堆琐碎内容阈值太高又会丢掉关键信息。默认阈值是 0.6我在长期使用后觉得比较合适。2.3 记忆存储层为什么选了 SQLite记忆提取出来之后需要找一个地方永久落盘。claude-mem 的存储层选的是 SQLite而不是一堆分散的 Markdown 文件或 JSON。当初我考虑过纯文件方案但很快就放弃了原因有三点。第一SQLite 支持原子写。如果程序在写入过程中崩溃不会留下半个文件导致 JSON 解析失败。这个坑在用纯文件方案时非常常见尤其是多个会话同时结束、同时写文件的时候。第二SQLite 自带全文检索。记忆多了之后不可能每次都用模糊匹配去遍历所有内容。SQLite 的 FTS5 扩展可以直接对记忆内容建索引按关键词搜索非常快。第三方便做统计和衰减。比如按标签统计所有记忆条目、按最后访问时间排序、批量删除过期记忆这些用 SQL 都是几行语句的事。核心表结构大致是这样的CREATE TABLE memory_entries ( id INTEGER PRIMARY KEY AUTOINCREMENT, scope TEXT NOT NULL DEFAULT global, content TEXT NOT NULL, tags TEXT NOT NULL DEFAULT [], importance REAL NOT NULL DEFAULT 0.6, source_session TEXT, created_at TEXT NOT NULL DEFAULT (datetime(now)), last_access_at TEXT NOT NULL DEFAULT (datetime(now)), access_count INTEGER NOT NULL DEFAULT 0 ); CREATE VIRTUAL TABLE memory_fts USING fts5( content, contentmemory_entries, content_rowidid );实际使用时你可能还会扩展出project_meta表存放每个项目的名称、根目录、最近活跃时间等。claude-mem 会通过项目根目录自动识别当前项目的project_meta这样不同项目之间就不会串记忆。2.4 记忆检索与注入层不是全部加载而是按需召回存储只是手段真正的核心在“会话开始时召回哪些记忆”。claude-mem 的默认策略是只把最相关、最重要、且仍然“新鲜”的记忆注入给 Claude。具体分三步第一步根据当前工作目录确定 project scope。比如你在/work/myapp下运行 Claude就只检索scopeproject:myapp的记忆再加上少量scopeglobal的全局偏好。第二步根据当前对话里出现的关键词做全文检索。比如你问“数据库连接在哪”它会优先命中内容里包含“数据库”“连接”的记忆条目。如果配置了 embedding 检索还会做语义相似度排序这时即使记忆里没有完全相同的关键词也能根据语义命中。第三步按照相关度、重要性、新鲜度做加权排序。相关度权重最高但太久没用的记忆会被降权避免旧信息污染新会话。最终只取 top-N 条拼接成一段系统提示词跟在原有 system prompt 后面。这里我额外提一个踩坑经验不要把召回数量调得太大。默认是 20 条我试着调到 80 条结果 Claude 的输出明显变保守因为它会把一些过时信息也当成硬约束。控制在 15 到 25 条之间比较合理。3. 安装与快速上手指南3.1 环境要求与安装步骤claude-mem 本质上是命令行工具需要在本地运行。环境要求不复杂Node.js 18 或更高版本我用的是 22 LTS实测没问题Claude CLI 或可用的 Claude API Key如果是 macOS / Linux建议开启一些系统级文件夹权限安装方式用的是 npm 包npm install -g claude-mem安装完可以先检查一下版本claude-mem --version如果没报错说明装好了。老用户升级的话直接跑同一个命令即可它会自动覆盖旧版本记忆数据存在本地不会丢。接下来是初始化。初始化要做两件事创建配置目录以及建立本地 SQLite 数据库文件。claude-mem init初始化完成后配置目录下会有这些文件~/.claude-mem/ ├── config.json ├── memory.db └── logs/如果你是用 Claude API 的开发者还需要在环境变量里配置 API Keyexport ANTHROPIC_API_KEYsk-ant-xxxx3.2 手动写入第一条记忆虽然 claude-mem 主打自动记忆但它也支持手动写入。手动写的好处是你可以在还没开始对话前先给 AI 灌输几条“硬性背景”这些背景不会被自动提取流程漏掉。比如你想让 Claude 以后在某个项目里始终知道你叫“Reno”项目部署方式是什么可以直接执行claude-mem remember 项目 myapp 使用 Docker Compose 部署服务 api-gateway 对外开放端口 8080 --scope project:myapp --tags deploy,docker这会往 SQLite 里写一条结构化记忆。你可以用list命令确认claude-mem list --scope project:myapp输出会类似# project:myapp 下的记忆共 1 条 1. 项目 myapp 使用 Docker Compose 部署服务 api-gateway 对外开放端口 8080 tags: deploy,docker importance: 0.8 created_at: 2025-06-01 10:23:003.3 和 Claude Code 做集成这是我最常用的场景。claude-mem 本身提供了插件配置可以让 Claude Code 在会话开始时自动加载记忆在会话结束时自动抽取新记忆。配置参考{ event_hooks: { SessionStart: [ { command: claude-mem inject --scope project:myapp } ], Stop: [ { command: claude-mem capture --scope project:myapp } ] }, retrieval: { top_n: 20, min_score: 0.4, use_embedding: true } }这里SessionStart阶段的 hook 会在 Claude 启动时执行inject把检索到的记忆写入系统提示词。Stop阶段的 hook 会在对话结束后执行capture拉取本次会话内容提炼记忆并落库。配置好之后你不需要再手动敲任何命令。用 Claude Code 正常对话claude-mem 在背后自动完成记忆读写。3.4 验证记忆是否注入成功集成完不要急着直接开始干活先花一分钟验证。开一个新的 Claude 会话直接问一句请根据你的记忆告诉我项目 myapp 的部署方式是什么如果注入成功Claude 会直接回答 Docker Compose 相关内容而不是一脸茫然。如果它答不上来多半是 hook 没有执行成功可以用诊断命令排查claude-mem doctordoctor会检查配置、数据库连通性、API Key 是否有效、最近一次 capture 是否成功。它给出的提示信息比较直白一般照着改就行。4. 配置技巧让记忆真正贴合你的工作流4.1 记忆粒度不是所有对话都值得记住默认配置下claude-mem 会把所有 importance 大于阈值的对话碎片存下来。但实际使用中你会发现很多对话内容根本不值得长期保存比如“帮我看看这段代码哪里报错”这种临时调试对话。我的建议是打开摘要阈值和活动阈值这两个开关。{ extractor: { min_importance: 0.65, summarize_full_session: true } }min_importance控制抽取的底线。低于这个分数的不写入数据库。summarize_full_session会要求提取层先对整个会话做一遍总结再从总结里抽条目。这样虽然多花一点 token但可以减少碎片化记忆。另外给记忆打标签时最好固定几种类型。我自己的习惯是deploy、code、preference、decision、person。标签越统一后面检索越准确。如果让 AI 自由发挥标签会出现“部署”“deployment”“docker-compose”这种同义标签检索时反而分散。4.2 作用域管理项目记忆、全局记忆和角色记忆我强烈建议不要把所有记忆都扔到 global 里。global 记忆会注入到所有项目中一旦存了项目 A 的专属信息别的项目也会带上极其容易串味。claude-mem 的作用域分三层global用户的通用偏好比如“代码注释用中文”“不要使用 Mongo 作为主存储”。project:xxx某个项目的专属信息比如项目路径、技术栈、部署方式。role:xxx角色级记忆比如“你是一个资深的 Python 后端工程师熟悉 FastAPI 和异步编程”。在项目根目录初始化时claude-mem 会自动识别当前文件夹名作为 project 名称。你也可以手动指定claude-mem remember ...这条记忆属于 myapp... --scope project:myapp如果你同时维护多个项目建议每个项目根目录都放一个.claude-memrc.json文件里面写清楚这个项目的 scope 和默认标签避免手滑写错。4.3 敏感信息保护别把密钥写进记忆这是最容易被忽视的一点。claude-mem 存储的是本地数据不代表你可以肆无忌惮地记敏感信息。我在早期使用时就踩过坑让 Cladue 帮我调试一个连数据库的脚本结果它把数据库密码当成“项目关键信息”提取进了记忆库。后面我做了两个补救措施。第一配置脱敏规则。claude-mem 支持正则替换在提取层写入前先把敏感信息抹掉{ security: { mask_patterns: [ { pattern: (?i)(password|passwd|secret|token)\\s*[:]\\s*\\S, replacement: $1*** } ] } }第二手动删除已经入库的敏感记忆claude-mem forget --scope project:myapp --tags infra注意mask_patterns只是事后补救最稳妥的方式还是不要在对话里贴明文密钥。让 Claude 读.env.example或者环境变量名而不是读真实值。4.4 遗忘策略让记忆保持新鲜记忆库的时间一长会产生两个问题。一是过期信息还在比如数据库地址已经改了旧记忆仍然被检索到Claude 照着旧地址操作就会报错。二是低频记忆积压占用检索空间把真正重要的内容挤掉了。claude-mem 提供两个机制解决这些问题。第一个是访问衰减。每条记忆都有last_access_at和access_count。如果一条记忆很久没用即使内容仍然存在在排序时权重也会越来越低最后不会被召回。配置项{ retrieval: { decay_days: 30, decay_factor: 0.5 } }第二个是主动清理。我会定期跑一次垃圾回收claude-mem gc --older-than 90 --min-importance 0.5这条命令会把 90 天以上没有被访问过、且 importance 低于 0.5 的记忆删掉。定期清一清记忆库整体质量会高很多。5. 实操过程与核心环节实现5.1 一次完整的实测记录下面我用一个真实的模拟过程带你看 claude-mem 从写入到检索的全流程。我准备了一个新目录/tmp/demo-project然后在里面初始化mkdir -p /tmp/demo-project cd /tmp/demo-project claude-mem init --scope project:demo-project接着手动写入两条记忆claude-mem remember 项目 demo-project 使用 Node.js 22 Hono 框架 --scope project:demo-project --tags tech-stack claude-mem remember 所有接口统一返回 { code, data, message } 结构 --scope project:demo-project --tags api现在打开 Claude Code确认它加载了 claude-mem 的 hook然后新开会话问你还记得这个项目的技术栈吗如果没有 claude-mem回答会是类似“抱歉我看不到当前项目的背景”。注入了记忆之后回答变成根据我的记忆当前项目使用 Node.js 22 Hono 框架。这个结果证明记忆注入成功。接下来我故意让对话产生新信息告诉 Claude“接口超时时间改为 30 秒”然后结束会话。claude-mem 在捕获阶段会提取这条新决策并入库。再次新开会话问“接口超时时间是多少”它就能答出 30 秒。整个链路跑通之后你就能感受到一个明显的变化跨会话一致性问题基本消失了。昨天做过的技术决策、强调过的方法论今天都能被继承。5.2 踩过的五个坑坑一记忆膨胀导致上下文污染。最开始我把top_n调到 80结果 Claude 每次都小心翼翼因为它看到了太多互相矛盾的旧记忆。后来我按月跑一次claude-mem gc并且把top_n调回 20情况立刻改善。坑二摘要丢失了关键细节。有一次会话里我详细说明了某个服务的端口映射关系但提取出来的记忆只写了“端口需要映射”没有具体数字。问题出在摘要模式太激进把细节吞掉了。我的解决办法是对于deploy和api这类高重要性标签开启“原文保留模式”即这些内容除了摘要还会额外存一份原始关键句。坑三项目记忆串场。某个项目里存了一条“这个微服务不应该使用共享数据库”但我在另一个项目里会话时它也把这条记忆注入了导致 Claude 一直建议我拆库。问题原因是这两个项目目录结构相似claude-mem 识别 project scope 时发生了偏差。后来我手动在项目根目录放.claude-memrc.json指定name字段串场问题再没出现过。坑四特殊符号导致 JSON 解析失败。如果对话中有大量反引号、换行、非 ASCII 字符提取层返回的 JSON 偶尔会格式错误。修复方式是启动“宽松 JSON 修复模式”它在发现解析失败时会调用二次清洗还不行就自动降级为纯文本存储。坑五并发写锁冲突。开多个 Claude 会话同时结束时两个 capture 进程会同时写 SQLite早期版本会出现database is locked报错。现在的版本已经默认开启 WAL 模式但你最好在配置里显式声明{ storage: { journal_mode: WAL, busy_timeout: 5000 } }5.3 性能观察延迟和 token 开销加了记忆层之后会不会明显拖慢对话我做了实测。inject阶段一次全文检索加排序本地 SQLite 查询通常 10ms 内完成如果开了 embedding首次加载模型文件会久一点后续都在 50ms 左右。capture阶段会话结束触发一次总结抽取。短会话10 轮以下大约 2 秒长会话50 轮以上可能需要 5 到 8 秒。这个过程是异步执行的不会阻塞下一次会话启动。token 开销每次注入大约额外消耗 800 到 1200 token取决于召回的记忆条数和长度。对于几万 token 成本的对话这个开支完全可接受。如果是普通的闲聊不需要加记忆可以直接在配置里关闭 hook。我只在写代码、做项目研究、写文档这类需要承接长期上下文的场景开 claude-mem。6. 常见问题与排查技巧实录这里整理了一份速查表都是我在实际使用中遇到过的按症状、原因、处理方式列举。症状可能原因处理方式新会话里 Claude 回答记忆里的过时信息记忆条目没有衰减旧内容权重仍然很高手动删除旧条目claude-mem forget --content 旧关键字配置更短的decay_days记忆注入不生效SessionStart hook 执行失败运行claude-mem doctor确认 Claude Code 的时间钩子配置正确不同项目记忆互相串扰没有指定项目 scope 或.claude-memrc.json缺失在每个项目根目录配置 scope避免在 global 里存放项目专属信息数据库 locked 报错多个会话同时写入开启 WAL 模式设置 busy_timeout提取出的记忆太碎min_importance 太低调高 extractor.min_importance打开摘要模式记忆内容太笼统细节缺失摘要层过度压缩对重要标签开启原文保留模式敏感信息被写入记忆库没有配置脱敏规则确认 mask_patterns用claude-mem filter扫描库内敏感字段并手动清理capture 阶段报错 JSON 解析失败提取输出的 JSON 不规范开启宽松 JSON 修复模式确认模型版本支持函数调用启动时注入记忆太慢embedding 检索未缓存调低use_embedding频率只对重要会话启用或者使用本地轻量模型做向量化除了表格里的常规排查我单独补一条独家经验如果你的记忆库里已经积累了一堆“看起来很有用但从来没被召回”的条目先别急着删。用claude-mem stats看一下每条记忆的last_access_at。如果一条记忆在 60 天里一次都没被访问说明它不是不重要就是描述方式和你的提问方式差异太大导致语义检索一直碰不到它。这时候最有效的操作不是删掉而是用更贴近你平时提问的关键词重写一遍content并重新入库存。我的记忆召回率写完重构之后提升明显。另外claude-mem list的输出如果出现乱码基本可以确定是终端字符编码问题。把终端环境变量LANG设为C.UTF-8或者en_US.UTF-8再跑一次中文内容就能正常显示。数据库里本身存的是 UTF-8不需要转码。7. 进阶玩法与后续扩展7.1 把记忆库变成个人知识库claude-mem 不只服务 Claude 会话它存下来的记忆本身就是结构化知识条目。我会定期导出所有记忆到 Markdown 文件作为自己的知识库摘要claude-mem export --format markdown --out knowledge-base/导出的文件按 scope 和标签分类之后可以丢进 Obsidian 或 Logseq 里做二次整理。我目前积累了三个月的项目记忆回看时能快速还原当时为了某个技术决策考虑过哪些方案、最后为什么放弃这比翻聊天记录高效得多。7.2 定时任务自动总结会话如果你每天固定时段用 Claude 工作可以配合 cron 做一个定时清理和总结0 18 * * 1-5 claude-mem capture --scope project:myapp --summarize-daily这条命令会在工作日六点把当天的记忆汇总成一条日报写入daily-summary标签下。第二天早上新会话启动时Claude 会自动看到前一天的工作摘要不需要你手动补上下文。对于每天跨会话工作的人这个习惯能省下非常多的重复沟通。7.3 多模型共用一套记忆因为 claude-mem 的记忆存储与模型无关所以你可以让它同时服务 Claude Code、其他模型 API、甚至本地模型。抽取层和检索层都是独立的只要注入层能把记忆文本拼进各自系统提示词即可。我实测过在同样一套记忆的基础上把注入目标切到其他模型由于记忆内容本身是清晰的事实陈述效果差别不大。唯一要留意的是不同模型对 system prompt 的注意力侧重不同必要时需要单独调节top_n参数。最后一个建议不要过度依赖自动抽取。claude-mem 最理想的使用方式是“自动抽取打底手动修正补充”。每天收工前花一分钟跑一次claude-mem flush --scope project:xxx --dry-run看它准备写出哪些记忆。如果发现重要决策漏掉了就手动remember补上如果发现记忆里有冗余或过时内容就顺手删掉。工具能帮你省掉机械劳动但判断什么值得长期记住仍然得靠你自己。用了一两周之后你会明显感觉到AI 不再像一个每次见面都要重新寒暄的陌生人而是一个真正在跟着项目走的搭档。
阅读完成 · 觉得有帮助?