☰
当Claude Code有了长期记忆:用claude-mem+SQLite+Chroma搭建可检索记忆库,一切都不一样了!
2026/10/1 15:22:20 网站建设 项目流程

1. 跨会话失忆:Claude Code 长期记忆到底卡在哪

如果你用 Claude Code 写过超过两小时的任务,大概率经历过这个瞬间:关掉终端、吃个饭、重新claude进来,问一句「刚才那个数据清洗的边界条件我们怎么定的」,它回你一个礼貌又空洞的「我没有之前的上下文」。这不是模型笨,是会话隔离机制决定的——每个 session 都是干净的上下文窗口,历史只活在当前进程里。

我试过最原始的办法:手动维护一个CLAUDE.md,把项目约定、目录结构、常用命令写进去。这招对静态知识有效,但有个致命缺陷——它记不住「过程」。比如你昨天为了绕开某个 API 的限流,试了三种退避策略,最后选了带抖动的指数退避,还顺手改了一个字段名。这些决策链条不会有人手动写进文档,但它们恰恰是下次开工最需要的东西。

于是问题变成三个具体的技术诉求:第一,会话结束后记忆不能丢,得落到本地持久化存储;第二,新会话开始时能自动把相关记忆召回并注入上下文,而不是靠我复制粘贴;第三,记忆要能检索,不能是一坨流水账,否则注入进去反而污染上下文。

claude-mem这个项目就是冲着这三点来的。它的定位很明确:给 Claude Code 装一套跨 session 的持久化记忆系统。核心机制是在 Claude Code 的生命周期节点上挂 Hook,自动捕获工具调用、决策、报错和解决过程,压缩成语义摘要后写进本地库。存储层用的是 SQLite 加 Chroma 的组合——SQLite 负责结构化数据和 FTS5 全文检索,Chroma 负责向量语义检索,两者配合做混合召回。

这套架构适合谁?我的判断是:长周期项目、多模块反复迭代、需要跨天甚至跨周保持上下文一致性的场景,收益最明显。如果你只是偶尔跑个一次性脚本,短 session 里失忆的代价还能接受,那感知不会太强。但只要你经历过「这个逻辑我当初为什么这么设计」的自我怀疑,就值得往下看。

本文聚焦落地:怎么把会话沉淀进 SQLite,怎么用 Chroma 建向量索引,怎么配置claude-mem让它自动跑起来,以及写入、召回、验证这三步怎么走通。目标很实在——让记忆可查、可迁移、可复现,而不是停留在「装了个插件感觉变聪明了」的模糊体感。

2. TaoToken 前置:给 Claude Code 备好可用的模型通道

在折腾记忆系统之前,得先保证 Claude Code 本身能稳定跑起来。记忆是建立在会话之上的,如果模型通道本身不稳定,Hook 捕获的数据质量也会受影响。这一步不是可选项,是前置条件。

TaoToken 在这里扮演的角色是模型接入通道。官网入口在 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 地址是 https://taotoken.net/api ,注意 API 这个地址不带 UTM 参数,配置的时候别画蛇添足。你需要准备的核心三件套是:Base URL、API Key、Model ID。这三样在后面的settings.json和auth.json里都会用到,缺一不可。

先说 Key 怎么拿。进控制台 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite ,在 API Keys 页面创建一个新 Key。创建的时候建议按用途命名,比如claude-code-mem,方便后面区分。Key 只在创建时完整显示一次,复制下来存好,别等关了页面再找。如果你还没决定用哪个模型,可以先去模型对话 https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_content=models&utm_campaign=rewrite 页面看看当前可用的模型列表,确认你要用的 Model ID 拼写。

然后是接入文档。配置过程中如果对某个字段的含义拿不准,直接翻文档 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite ,里面有 Base URL 的完整写法和常见参数说明。这一步别偷懒,很多 401 报错都是因为 Base URL 少写或多写了路径段。

对于长期跑编码任务和 Agent 场景的用户,Coding Plan 页面 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 值得看一眼,它针对的就是这种持续性的编码工作流。如果你用的是 Claude Code 的 Anthropic 兼容模式,对应的接入说明在 https://taotoken.net/claudecode-anthropic?utm_source=taotoken_aicg_blog_end&utm_content=claudecode-anthropic&utm_campaign=rewrite ,这个页面把 Claude Code 的配置路径讲得比较清楚。

这里要强调一个原则:TaoToken 是模型接入通道,不是编辑器替代品,也不是记忆系统本身。它解决的是「模型能不能稳定调用」的问题,记忆系统解决的是「会话之间能不能记住」的问题,两者是叠加关系,别混为一谈。

配置完成后,先用一个最简单的请求验证通道是否通。可以在终端里用 curl 打一发,确认返回正常再往下走。如果这一步就报错,先解决通道问题,别急着装claude-mem,否则后面排查会分不清是记忆系统的问题还是模型通道的问题。

3. 可复制配置:claude-mem 接入 + SQLite 表结构 + Chroma 索引参数

这一节是全文的技术核心,所有片段都可以直接复制。我按「安装 → 配置 → 存储层」的顺序来,每一步都给出完整内容。

3.1 安装 claude-mem

最省事的方式是一行命令:

npx claude-mem install

如果你更习惯在 Claude Code 内部操作,用插件市场的方式:

/plugin marketplace add thedotmack/claude-mem /plugin install claude-mem

装完之后重启 Claude Code,它会开始默默工作。第一次启动时它会尝试自动安装 Bun(JavaScript 运行时)和 uv(Python 包管理器),这一步在网络环境一般的情况下可能会卡。如果卡住,手动装好这两个再重启即可,不是大问题。

3.2 settings.json 配置片段

Claude Code 的配置文件通常放在~/.claude/settings.json。下面这段是接入 TaoToken 通道并开启中文记忆模式的完整配置,路径和字段名保持原样:

{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_API_KEY": "sk-你的TaoToken密钥", "ANTHROPIC_MODEL": "claude-sonnet-4-20250514", "CLAUDE_MEM_MODE": "code--zh" }, "plugins": { "claude-mem": { "enabled": true, "workerPort": 37777, "storage": { "sqlitePath": "~/.claude-mem/memory.db", "chromaPath": "~/.claude-mem/chroma" } } } }

三个关键点:ANTHROPIC_BASE_URL必须是https://taotoken.net/api,不要带 UTM;ANTHROPIC_API_KEY填你在控制台创建的 Key;CLAUDE_MEM_MODE设为code--zh后,生成的记忆摘要直接是中文,读起来省事。

3.3 auth.json 配置(Codex 兼容场景)

如果你同时用 Codex 风格的认证文件,~/.codex/auth.json里对应写:

{ "base_url": "https://taotoken.net/api", "api_key": "sk-你的TaoToken密钥", "model": "claude-sonnet-4-20250514" }

Base URL、Key、Model ID 这三件套在任何接入方式里都是绑定的,换一个地方就要同步改,别只改一半。

3.4 SQLite 表结构

claude-mem会在~/.claude-mem/memory.db里建表。核心表结构大致如下,你可以用sqlite3打开确认:

CREATE TABLE IF NOT EXISTS observations ( id INTEGER PRIMARY KEY AUTOINCREMENT, session_id TEXT NOT NULL, project_path TEXT, tool_name TEXT, decision TEXT, problem TEXT, solution TEXT, summary TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE VIRTUAL TABLE IF NOT EXISTS observations_fts USING fts5( summary, decision, problem, solution, content='observations', content_rowid='id' ); CREATE INDEX IF NOT EXISTS idx_observations_session ON observations(session_id); CREATE INDEX IF NOT EXISTS idx_observations_project ON observations(project_path);

observations存结构化字段,observations_fts是 FTS5 全文检索虚拟表,content='observations'表示它跟主表联动。两个索引分别按 session 和项目路径加速查询。这套结构的好处是:关键词精确匹配走 FTS5,语义相似走 Chroma,两边结果再合并排序。

3.5 Chroma 索引参数

Chroma 的集合配置在~/.claude-mem/chroma目录下。创建集合时的关键参数:

import chromadb client = chromadb.PersistentClient(path="~/.claude-mem/chroma") collection = client.get_or_create_collection( name="claude_mem_observations", metadata={ "hnsw:space": "cosine", "hnsw:construction_ef": 200, "hnsw:M": 16 } )

hnsw:space设为cosine是因为语义相似度用余弦距离更稳;construction_ef控制建索引时的搜索广度,200 是精度和速度的平衡点;M是每个节点的连接数,16 对中小规模记忆库够用。如果你的记忆条目超过十万级,可以把M提到 32,但内存占用会上去。

写入时带上元数据,方便后面按项目过滤:

collection.add( ids=[f"obs_{obs_id}"], documents=[summary_text], metadatas=[{ "session_id": session_id, "project_path": project_path, "tool_name": tool_name }] )

到这里,存储层就搭好了。SQLite 管结构化,Chroma 管语义,两边用obs_id关联。

4. 写入-召回-验证:三步走通记忆闭环

配置写完不算完,得实际跑一遍确认记忆真的能存进去、能捞出来。这一节按写入、召回、验证三步来,每步都有可观察的结果。

4.1 写入:让会话沉淀下来

启动 Claude Code,随便做一个小任务,比如让它读一个文件并总结。任务结束后,claude-mem的 Hook 会在SessionEnd节点触发,把这次会话的观测压缩成摘要写进 SQLite 和 Chroma。

验证写入是否成功,直接查库:

sqlite3 ~/.claude-mem/memory.db \ "SELECT id, session_id, tool_name, summary, created_at FROM observations ORDER BY id DESC LIMIT 5;"

如果能看到刚才那次会话的记录,说明写入链路通了。如果表是空的,先检查 Worker 服务是否在跑:

curl http://localhost:37777/health

返回正常说明 Worker 活着。Worker 是个跑在 37777 端口的 HTTP 服务,提供搜索接口,还有个 Web Viewer 可以实时看记忆流,浏览器打开http://localhost:37777就能看到。

4.2 召回:新会话自动注入

关掉当前 Claude Code,重新开一个 session。SessionStartHook 会触发,Worker 根据当前项目路径去 SQLite 和 Chroma 里召回相关记忆,注入到上下文。

召回效果怎么确认?在新 session 里问一个跟上次任务相关的问题,比如「上次那个数据清洗的边界条件是怎么处理的」。如果它能答上来,说明召回生效了。

手动测试召回接口也可以:

curl -X POST http://localhost:37777/search \ -H "Content-Type: application/json" \ -d '{"query": "数据清洗 边界条件", "limit": 5}'

这个接口会同时走 FTS5 和 Chroma,返回合并后的结果。注意claude-mem的搜索设计是三层工作流:先用search拿精简索引(每条 50-100 token),再用timeline看某个观测点前后的时间线,最后才用get_observations拿完整详情。这个「先筛选再全量」的思路省 token,跟数据库查询优化是一个道理。

4.3 验证:确认记忆可迁移可复现

最后一步是验证记忆的可迁移性。把~/.claude-mem/整个目录复制到另一台机器,配置好同样的settings.json,启动后记忆应该能直接召回。这一步验证的是存储层的独立性——记忆不绑定在某个进程里,而是落在本地文件上。

复现性验证:用同一个session_id查 SQLite,确认记录完整;再用同样的 query 打搜索接口,确认返回结果一致。如果两次结果差异很大,检查 Chroma 的hnsw:space是否被改过。

三步走完,记忆闭环就通了。写入有记录、召回有响应、迁移可复现,这才算真正落地。

5. 常见报错排查:401、local proxy failed、reading choices、OAuth

配置和运行过程中,报错基本集中在四类。我按实际遇到的顺序列出来,每条给出原因和修法。

5.1 401 Unauthorized

最常见。原因通常是 API Key 错了、过期了,或者 Base URL 写错导致请求打到了错误的端点。先确认settings.json里的ANTHROPIC_BASE_URL是https://taotoken.net/api,注意结尾没有多余的斜杠或路径段。然后确认 Key 是从控制台新创建的、没有多余空格。如果还报 401,去控制台重新生成一个 Key 替换。

5.2 local proxy failed

这个报错通常出现在 Worker 服务启动失败或端口被占用时。claude-mem的 Worker 跑在 37777 端口,如果这个端口被别的进程占了,就会报 local proxy failed。检查端口占用:

lsof -i :37777

如果有进程占用,要么杀掉它,要么在settings.json里把workerPort改成别的值,比如 37778。改完重启 Claude Code。

5.3 reading choices 相关报错

这类报错一般出现在模型返回格式不符合预期时,根源往往是 Model ID 写错了,或者通道返回的不是标准 Anthropic 格式。确认ANTHROPIC_MODEL字段拼写正确,跟模型对话页面里列出的 ID 完全一致。如果 Model ID 没问题,检查是不是 Base URL 带上了多余的路径,导致请求被路由到了非兼容端点。

5.4 OAuth 相关报错

如果你之前用 OAuth 方式登录过 Claude Code,配置文件里可能残留了 OAuth 相关的字段,跟 API Key 方式冲突。解决办法是清理~/.claude/下的认证缓存,只保留settings.json里的 API Key 配置。具体来说,检查有没有~/.claude/credentials.json之类的文件,有的话先备份再移除,然后重启。

排查顺序建议:先确认通道通(curl 打一发),再确认 Worker 活(health 接口),最后确认存储层可写(查 SQLite)。三层依次排查,比一上来就翻日志高效得多。

6. 长期编码场景:把记忆接进 Coding Plan 工作流

记忆系统搭好之后,真正的价值在长期编码场景里才体现出来。如果你跑的是跨周甚至跨月的项目,建议把claude-mem跟 Coding Plan 配合用。Coding Plan 页面在 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite ,它针对的就是这种持续性编码工作流,跟记忆系统的定位是互补的——一个保证模型通道稳定,一个保证上下文连续。

实际用下来,有几个技巧值得分享。第一,项目路径要保持一致,claude-mem是按project_path做召回过滤的,如果你在不同目录下开 session,记忆会被切碎。第二,定期清理低价值记忆,SQLite 里可以按时间或 session 批量删,Chroma 里对应删掉,避免召回时被噪音干扰。第三,<private>标签该用就用,敏感内容标记后不会被记录,这个设计对数据隐私要求高的场景很实用。

如果你在配置过程中卡在某个报错,优先去接入文档 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite 对照字段说明,大部分问题都是路径或参数拼写导致的。Key 的管理在 API Keys 页面 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite ,需要轮换或新增的时候直接在那里操作。想先验证模型通道是否正常,模型对话页面 https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_content=models&utm_campaign=rewrite 可以快速试。

最后说个我踩过的坑:一开始我把sqlitePath和chromaPath配到了项目目录下,结果每次git clean都把记忆库删了。后来改到~/.claude-mem/下才稳定。记忆库是长期资产,别放在会被清理的路径里。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询