用Claude Code写代码最难受的是什么?我个人的答案不是模型能力不够,而是它记性太差。每次开新会话,它都不记得我上次让它把目录结构调整成什么样、不记得我反复叮嘱过的测试命令,也不记得我最讨厌在代码里写魔法数字。你只能一遍一遍把项目背景、个人偏好、当前进度重新喂给它,然后祈祷它这次别又把同样的事情搞砸。后来我在一个折腾了很久的仓库里忍无可忍,找到一个叫claude-mem的开源工具,算是把这个“永久失忆症”的问题彻底解决了。
claude-mem说白了,就是给Claude Code装一个外挂的长期记忆层。它通过监听Claude Code的会话事件,自动把对话内容、命令、文件改动等关键信息存到本地SQLite数据库里,下次你再开新会话时,它会主动把相关的历史记忆塞回给Claude,让它“想起来”你是谁、你在干什么、你项目里有哪些约定。这篇文章我会从原理讲到实操,再讲到我踩过的坑,适合那些正在用Claude Code但被“重复交代背景”折磨的开发者,也适合想给AI编码工作流加持久记忆的朋友。
1. 先搞清楚:Claude Code 为什么会“失忆”
1.1 会话隔离与上下文窗口的天然限制
要理解claude-mem做了什么,先得理解AI为什么记不住。Claude本身是一个大语言模型,它没有真正的“记忆”,它只是在每次请求时根据你给它的上下文来生成回复。Claude Code这样的终端编程工具,虽然把多个请求组成了一个看起来连续的会话,但这个会话一旦结束,所有中间状态基本就清零了。你关掉终端、开个新会话,它面对的就是一个全新的“空脑袋”。
这有点像你家里请了一个临时保洁员。你明明上周跟他说过“书架上的书按作者名字排序”,他当时也确实帮你整理好了。但下次来的不是他本人,而是另一个同样专业但完全不知情的保洁员,你只能把同样的要求再原原本本说一遍。不是他笨,是你们之间根本没有一个共用的记事本。Claude Code也是这样,每次会话都像是来一个新保洁员,你之前交代过的所有要求、偏好、项目细节,都留在了上一个会话的“房间”里。
再加上上下文窗口本身是有上限的,就算你把聊天历史一直留着,也不可能把所有旧对话都塞进新的请求里。你更不可能把几百MB的代码仓库历史全部作为提示词喂给模型,那样既不经济,也不现实。所以“会话隔离+上下文受限”这两件事叠加在一起,就是AI编码工具记忆差的根本原因。
1.2 靠“手动喂上下文”有多痛苦
在没有记忆工具之前,我见过几种常见的解决办法,但每一种都让人想骂人。
第一种是最朴素的:每次开工前先复制粘贴一堆背景说明。比如“我们这个项目用的是pnpm workspace,测试统一用vitest,不要用jest;代码风格遵循eslint配置,注释用中文;常见的文件结构是src/components、src/hooks等等”。这些话你可能要在一整天里打好几遍,甚至每次让Claude处理一个模块你就要重申一次,因为会话一换它就忘了。
第二种是写文档,把规则沉淀到AGENTS.md或CLAUDE.md里,让Claude每次自动读取。这个思路没错,但痛点在于这些静态文档只适合放“长期不变”的规则,不适合放“动态变化”的状态。比如“这个PR目前改到哪个文件了”“上个小时我们刚决定把UI组件从旧库迁移到新库”,这些信息你不可能每次手动更新到文档里,太繁琐,而且很容易忘。
第三种是干脆不关终端,靠tmux或screen复用会话,让对话上下文一直活着。这个方法在短时间是有效的,但只要你电脑重启、网络中断、或者不小心关闭窗口,所有“记忆”就灰飞烟灭了。而且长期开着一个巨大的会话,token消耗和响应速度都会变得不可控。说到底,这些都是治标不治本的办法,缺的是一个真正能自动持久化记忆的中间层。
1.3 记忆系统的设计思路
真正解决问题的方案,应该具备三个能力:第一,能自动记录会话过程中产生的重要信息,不需要我手动写笔记;第二,能持久化保存,不受会话结束、终端关闭影响;第三,能在下次会话开始时自动把相关记忆注入给模型,让Claude主动想起来关键词。
claude-mem的出现,恰好就是把这三件事都做了。它的定位不是修改Claude内部机制,而是作为一个外部工具,在Claude Code运行的生命周期里挂上钩子,替你做好“记录-存储-召回”这条链路。这样做的好处是它不依赖任何云端服务,数据都在你自己本地,存储和检索逻辑也透明可查。在我用过的方案里,它是目前操作最简单、侵入感最低的一个。
2. claude-mem 到底是什么:架构与核心机制
2.1 项目定位与实现语言
先给一个一句话定义:claude-mem是一个为Claude Code提供持久化记忆的开源命令行工具。它用Go语言写成,发布时提供各个平台的预编译二进制,所以部署起来非常简单——你不需要先装一套依赖环境,下载下来就能跑。这对用惯了Go工具链的开发者来说很亲切,也保证了它能在不同操作系统上稳定工作。
还要澄清一个常见的误解:claude-mem并不是去“黑”Claude Code的内部记忆,也不是什么模型层面的魔法。它更像一个称职的秘书,站在Claude Code旁边,听到什么重要的就记下来,下一次开会前先把笔记本递给Claude看一眼。它做的事情完全可以被审计、被排除、被遗忘,主动权始终在你手上。
2.2 工作原理:Hooks + SQLite + 检索注入
claude-mem的核心依赖Claude Code提供的hooks机制。简单说,hooks是Claude Code在某些事件发生时允许外部程序介入的钩子。比如用户在终端里输入了一句话、模型给出了最终回复、一个会话被创建或被关闭,这些时刻都可以配置成触发claude-mem的特定命令。claude-mem利用这些钩子,在后台自动把关键内容写入数据库。
存储端用的是SQLite,这一点我非常喜欢。SQLite是单文件数据库,不需要单独起服务,所有记忆就存在于一个文件里。它天然支持结构化查询和全文搜索,对于对话记录这类文本数据来说完全够用。相比于要部署一套向量数据库的方案,claude-mem把“数据”这一层做得极轻。每次会话结束后,Claude Code关闭时会触发一个事件,claude-mem在这个阶段把整个会话的消息列表、执行过的shell命令、创建或修改的文件路径,甚至Git操作摘要一起写入SQLite。
检索注入发生在你打开新会话的时候。claude-mem会读取当前工作目录对应的数据库,根据项目路径、最近活跃时间、消息内容里的关键词,把相关的历史记忆整理成一段“记忆摘要”,再通过Claude Code的会话启动钩子注入到对话上下文中。因为注入的内容不是全量历史,而是经过筛选的摘要,所以不会爆炸式占用上下文窗口。这个“摘要式召回”的思路,和RAG有点像,但它没有引入独立的向量检索服务,而是用SQLite的全文搜索加简单的关键词匹配来完成的。
2.3 它到底记住了什么
那么问题来了,claude-mem实际记住了哪些东西?我观察下来,主要有这么几类:
- 会话消息记录,包括你发给Claude的指令和Claude的回复,但它会做摘要化,不是一字不差全存。
- 你在会话里执行过的shell命令,尤其是那些与文件操作、测试、构建相关的关键命令。
- 文件修改记录,比如你在对话中提到了
src/utils.ts,它会记下这个文件以及相关讨论。 - 项目配置和偏好,当你告诉Claude“提交信息用英文,别用中文”,这类偏好会被记录并在后续会话中注入。
- 你在对话里粘贴的错误日志、报错文本,方便下次遇到类似问题时Claude能快速关联到之前的排查过程。
需要说明的是,默认情况下它不会傻到什么都存。claude-mem内置了一套默认忽略规则,会自动过滤掉看起来像API Key、密码、token的高风险文本。如果你有自己的隐私底线,还可以通过自定义正则把更多内容拉黑,这一点我在后面第4章会细讲。
3. 实操:从安装到让 Claude 记住你的第一次对话
3.1 环境准备与安装方式
安装claude-mem之前,你需要确认两件事:你的电脑上已经装了Claude Code并且能正常使用;另外你有权限安装命令行工具和修改Claude Code的配置。claude-mem是一个独立程序,本身不需要Claude Code的API Key,它只是把Claude Code当成一个“客户端”来配合。
安装方式有几种,按我推荐的顺序来:
首选是用包管理器安装。如果你用macOS且装了Homebrew,可以执行:
brew install claude-memLinux或Windows用户,可以直接从GitHub Releases页面下载对应平台的可执行文件,放到/usr/local/bin或你的PATH目录下。Go语言环境如果已经装好,也可以现场编译:
go install github.com/thedotmack/claude-mem@latest安装完成后,先验证一下版本:
claude-mem --version看到能输出版本号,说明二进制没问题了。如果你的Shell找不到命令,多半是PATH没有包含安装目录,这个排查方法我在第五章再说。
3.2 初始化与接入 Claude Code
命令行的“接入”过程做得相当自动化。在你想启用记忆的目录里,先执行初始化命令:
claude-mem init这一步它会做几件事:创建一个本地的存储目录(默认是在~/.claude-mem/或项目下的.claude-mem/,具体取决于配置),生成一个配置文件,并且自动把hook配置写入到Claude Code的配置文件里。换句话说,你不用手动去编辑JSON去注册钩子,工具自己就完成了接线。
初始化完成后,可以先用状态命令检查一下是否一切正常:
claude-mem status它会显示类似“database healthy”“hooks enabled”这样的信息。如果哪个环节没接上,它会给出提示。这一步非常重要,.nextLine别跳过,我就曾经因为没看status直接开干,结果发现钩子根本没生效。
接好hooks之后,记得重启Claude Code。你在旧会话里安装的hook是不会自动加载的,必须新开一个会话才能触发初始化事件。
3.3 让记忆真正注入
现在来做一个最直观的测试。我打开一个测试项目,在Claude Code里输入:
从今天开始,我们项目里所有测试统一用 pnpm vitest,不要用 jest。代码注释用中文,函数命名用 camelCase。然后继续干了一会儿活,最后正常退出会话。注意,这个退出过程很重要,因为claude-mem是在会话关闭事件触发时做记忆写入的,你如果直接强杀终端进程,可能会丢掉最后一段记忆。
重新打开Claude Code,直接问它:
我之前跟你定过什么项目约定?如果一切正常,它会回答出“测试用pnpm vitest、注释用中文、函数命名用camelCase”这些内容,并且可能还会提到上一个会话里你改过哪些文件。看到这个结果的时候,我真的当场一愣,那种“它居然记得”的感觉,和之前换会话后一切都重来的体验完全不一样。
3.4 常用命令速查
我整理了一份claude-mem的常用命令表,方便你日常使用:
| 命令 | 作用 |
|---|---|
claude-mem init | 初始化数据库和hook配置 |
claude-mem status | 查看数据库和hook运行状态 |
claude-mem sessions | 列出所有记录过的会话,按时间排序 |
claude-mem search <关键词> | 搜索历史记忆中的相关内容 |
claude-mem forget <会话ID> | 删除某个指定会话的记忆 |
claude-mem prune | 按策略清理过期或冗余记忆 |
claude-mem doctor | 体检工具,检查安装和配置问题 |
这些命令都不复杂,但实际操作频率很高。尤其是search,当你怀疑“Claude是不是忘了某个细节”的时候,用它在数据库里直接搜原始记录,要比让Claude自己回忆靠谱得多。
4. 进阶配置与高级玩法
4.1 过滤敏感信息和噪声:黑名单、白名单与模式
记忆工具的第一步是好用,第二步是别乱记。我见过一些人在AI编程工具里直接粘贴生产环境的数据库连接串,如果记忆工具把这些原样保留下来,本地数据库文件又恰好被同步到云端仓库,那乐子就大了。claude-mem默认有一些安全过滤,但默认值不等于为你量身定制。
在配置文件里,你可以自定义patterns规则,用正则表达式把你想屏蔽的内容拉黑。比如我的配置里加了下面这些:
{ "blacklist_patterns": [ "(sk-[A-Za-z0-9]{20,})", "(AKIA[0-9A-Z]{16})", "(-----BEGIN PRIVATE KEY-----)" ] }这样任何匹配这些模式的文本都不会被记录到SQLite。我建议你也手动往里面加几项,最经典的是把形如password=xxx、token=xxx的字符串全部忽略。宁可多过滤,也别事后后悔。
反过来的场景是白名单模式。在某些团队里,你可能希望claude-mem只关注特定目录的文件操作,比如src/和tests/,而忽略dist/、node_modules/这些构建产物目录。通过配置白名单路径或忽略目录,可以让记忆更聚焦,也避免存一堆无关紧要的东西让后续检索变混乱。
4.2 多项目隔离与全局记忆
claude-mem支持按项目隔离记忆,这很关键。你肯定不希望A项目的约定跑进B项目里,导致Claude在B项目里胡说什么“这个项目测试用vitest”,结果B项目实际用Mocha。默认情况下,数据库的存储路径是按项目区分的,如果你在/path/to/project-a里初始化,它就会把记忆存在与该项目绑定的存储位置。
但有时候你确实需要一些跨项目的全局记忆,比如你自己的偏好:“我写代码永远用空格缩进,不用Tab”“提交信息格式用conventional commits”。这些可以放到全局配置里,这样每个新项目都会注入这些通用规则。实际操作中我是这样分配的:项目级记忆放“项目动态约定”,全局记忆放“我的个人编码风格”,两下配合,效果很好。
如果你希望手动控制存储位置,可以设置环境变量:
export CLAUDE_MEM_STORAGE_PATH="/secure/private/chat-history"这样做的好处是你可以把数据库集中放在一个加密磁盘或企业内部NAS里,同时也能让多台机器共享同一份记忆。不过要提醒一句,SQLite本身不擅长多个进程同时高并发写同一个文件,跨机器共享数据库文件这种操作我没试过,我也不推荐,除非你愿意承担并发写冲突的风险。
4.3 结合 Claude Code 自带记忆机制
claude-mem不是孤军奋战,它完全可以和Claude Code自带的指令文件共存。我的建议是形成一个“双轨结构”:静态的、长期不变的规则放到AGENTS.md或者CLAUDE.md里,比如项目的技术栈、目录结构约定、编码规范;动态的、变化频繁的状态则交给claude-mem去记忆,比如当前任务进展、最近决定、临时偏好。
举个实际案例。我在一个前端仓库里,CLAUDE.md里规定“UI组件库使用公司内部封装的组件,不要直接引入第三方组件”,这是一个人人可见、长期有效的规则。而“昨天讨论过要不要把某个旧组件废弃掉”这种瞬息万变的信息,写在文档里很快会过期,但claude-mem可以捕捉到上一次会话的讨论,在新会话里自动提起,帮助Claude延续上下文。两者一个是“宪法”,一个是“工作日志”,各司其职。
4.4 容量管理与遗忘策略
数据库如果只增不减,迟早会变成一个大胖子。SQLite虽然对小数据量很友好,但记忆积累到成千上万条消息后,检索速度和注入效果都会下降。我建议定期做一次记忆瘦身。
一种方式是使用forget针对特定会话做删除。当你完成一个非常细碎的任务,比如“帮我把某个临时脚本里的报错修一下”,这个会话对后续工作基本没有价值,就可以直接忘掉它。另一种方式是使用prune按时间窗口清理,比如只保留最近30天的记忆。我在日常工作中,会每周执行一次“有节制地遗忘”,保留那些涉及架构决策、API设计讨论的重要会话,清掉那些纯粹的琐碎问答。
还有一个被低估的功能是会话摘要。长时间高强度使用后,一个会话里可能有几十轮对话,直接全部记住会占用太多空间,也会让后续注入的信息变得冗长。claude-mem可以把一个会话的关键结论压缩成几条摘要,只存摘要,不存全文。这个功能很像“会议纪要”,对长期记忆质量提升非常明显。
5. 我踩过的坑和排查实录
5.1 hook 不触发或记忆没生效
我第一次安装完,兴冲冲开新会话,跑了一会儿,然后退出,再开新会话,结果Claude对此前讨论一无所知。那时候我第一个反应是“这工具是不是没用”。后来一步步排查才发现,问题出在hook配置没有真正被写入。
最直接的排查方法是运行claude-mem doctor,它会扫描Claude Code的配置文件,检查hooks是否注册成功、数据库路径是否存在、二进制路径是否正确。在我这个案例里,doctor提示hook配置缺失,我重新执行了一次claude-mem init,然后彻底退出终端,重新打开Claude Code,问题就解决了。
另一个很容易忽视的点是:如果你在安装claude-mem之前就已经开着一个Claude Code会话,那么那个会话不会自动挂载新的hook。只有新启动的会话才会执行初始化逻辑。所以任何配置变更后,都要记得“重启会话”,而不是在旧会话里干等。
5.2 命令找不到/二进制路径问题
还有一次升级之后,Claude Code突然报错说找不到claude-mem命令。我检查了一下,发现hook配置里写的是相对路径claude-mem,而Claude Code启动时使用的Shell环境里PATH没有包含我的Go bin目录。这个问题在macOS上特别常见,因为go install默认装到~/go/bin,而这个路径并不在系统的默认PATH里。
解决办法很简单,把hook配置里的命令改成绝对路径,或者把export PATH=$PATH:$HOME/go/bin写进shell的启动文件(比如~/.zshrc)。我倾向于使用绝对路径,因为这样能让Claude Code启动时更稳定,不受我的Shell配置影响。修改完记得重启终端和Claude Code。
5.3 隐私和团队使用担忧
在团队协作中,你不希望自己的本地记忆库内容随着代码仓库被推到远端吧?claude-mem的数据默认存在用户目录下,但如果你把项目级的.claude-mem/放进了Git仓库,那就可能把内部讨论记录、路径信息、甚至敏感配置泄露给协作者。我在任何项目里都会把.claude-mem/写入.gitignore,并且和团队成员约定好,记忆库是个人工具,不做跨人共享。
如果你真的很在意隐私,还可以开启“审查模式”,在本地方查看数据库内容,或者直接用forget删除敏感会话。记住一点:工具自动记的东西,不一定都是你愿意长期留存的,定期“审阅”自己的记忆库,是对自己负责。
5.4 性能与数据库锁问题
还有一个真实踩到的坑:在超大项目里,某些会话结束时claude-mem可能因为数据库写入耗时过长,导致Claude Code退出卡顿几秒钟。原因是会话结束事件触发后,claude-mem需要在同步上下文中写入大量数据。后来我通过给hook配置增加异步执行参数,让写入在后台进行,避免了卡顿出现。另外,SQLite在极端并发场景下会有锁冲突,其实对于个人单用户的场景基本遇不到,但如果你信不过,可以定期执行VACUUM来整理数据库文件。
6. 我的真实体会和后续扩展
这段时间用下来,我最强烈的感受是“它能让我更放心地关掉终端了”。以前我总是不舍得结束长会话,因为害怕Claude忘掉上下文,现在我知道就算我关掉电脑,明天开一个新会话,它仍然能通过claude-mem把我的偏好和项目动态捡起来。这种“记忆可携带”的感觉,一下子把AI编程工具从“临时工”变成了“长期搭档”。
最后再分享一个小技巧。既然claude-mem把所有记忆都存成了SQLite,那它不仅是给Claude用的,也完全可以是给我自己用的。我写了一个简单的定时任务,每周五晚上把当前项目的记忆库导出成一份Markdown周报,看看这周让Claude干了哪些活、重点解决了哪些问题。这样不仅Claude有记忆,我也有了项目的“历史日志”。你如果要扩展这个工具,完全可以往这个方向想:把记忆库变成自己的第二大脑数据源,配合其他脚本做统计、搜索、报告,都是很自然的延伸。
我个人在实际操作中的体会是,工具选型再花哨,也抵不过“接入简单,跑得稳,忘得掉”这三个字。claude-mem最打动我的地方,不是它功能堆得有多炫,而是它真的把记忆这件事想得很清楚:记录容易,关键是检索和遗忘。你对AI的记忆有了掌控权,才会更愿意把复杂任务托付给它。如果你也被Claude Code的“失忆”折磨过,我建议你亲自装上试试,然后从一个小项目开始建立记忆库,用一周时间感受一下变化。