用过 Codex 的人都会有个很深的感受:单次会话里它聪明得不像话,可一旦关闭终端、开启新会话,它就像失忆一样,把上次定好的架构决策、接口约定、踩坑结论全部丢掉。我一开始以为这是产品缺陷,后来才意识到,这其实是对话模型的工作机制决定的——它天然只活在“当前上下文”里。直到我把 Hindsight 接进 Codex 的记忆流程,这个问题才算真正解决。
这篇内容我会从“为什么需要记忆”讲起,给出 Hindsight 的安装、MCP 注册、日常使用、排错方法和记忆卫生建议,面向的是已经用过 Codex、但对“外部记忆”这个概念还比较模糊的开发者。不管你是想给 Codex 配一个长期记忆,还是想用它跨会话追踪项目决策,这篇文章都能给你一套可直接落地的方案。
1. 先搞清楚:Codex 的“失忆体质”和 Hindsight 的定位
1.1 为什么 Codex 会话不会自动保留经验
很多人第一次接触 Codex 时,会误以为它和 IDE 里的代码补全一样,天然知道你昨天写了什么。实际上,Codex 每次会话都是从一个固定的基础模型出发,加上你当前对话里提供的上下文来生成输出。它没有“读磁盘”的能力,也不会主动翻你之前的聊天记录。模型参数在训练完成后就固定了,权重里存的是互联网级别的通用知识,而不是你项目里的专属记忆。
这带来一个很实际的矛盾:你在项目里积累的很多东西,恰恰是通用知识之外的部分。比如“支付回调为什么不用数据库事务而用消息队列”“查询接口统一走 CQRS 还是直接查表”“缓存更新策略选 Cache Aside 还是 Write Through”。这些决策一旦散落在不同会话里,下次接着做时,Codex 就完全不认识它们,甚至会给出和你当时结论相反的方案。
如果你只是拿 Codex 写写一次性脚本,失忆问题影响不大。但一旦进入真实项目开发,需要跨多天的迭代、跨模块的协作,没有记忆就等于每次都在和同一个聪明但健忘的新同事合作。
1.2 Hindsight 做的事:给 Codex 装一个“外置后视镜”
Hindsight 这个名字很有画面感——hindsight 就是“事后回看”的意思。它扮演的不是让 Codex 变聪明的角色,而是让 Codex“想起来”的角色。技术上它属于外部记忆层(external memory),核心思路是把会话中值得保留的信息,按结构化的方式存下来,在需要时检索并塞回 Codex 的上下文。
我把它理解成一个知识存取服务:你可以主动告诉它“记住某件事”,也可以让它自动从对话中抽取出关键信息;当新会话开始时,Codex 通过工具调用向它提问,它把最相关内容返回,再由 Codex 整合进回答里。
Hindsight 不像 LangChain 里的 ConversationBufferMemory 那样只是把聊天记录原样拼接,而是更接近“可检索的长期记忆仓库”:自带向量索引、支持语义召回、区分记忆作用域(个人级、项目级、会话级)。这意味着你可以在一周后问它“我们当时为什么选了 Nuxt 而不是 Next”,它能在自己库里找到对应的片段,而不需要你把整段旧对话贴回去。
2. 接入前的准备:环境、存储目录与模型供应商配置
2.1 三样东西先备齐
正式接入前,先把这三样准备好,后面会省掉很多麻烦。
- Python 环境。Hindsight 的 CLI 和 MCP 服务都是 Python 包,需要 Python 3.10 及以上,建议用
python3 -m venv建一个独立虚拟环境,不污染系统 Python。 - Node.js 环境(可选)。Codex 配置解析本身不依赖 Node,但某些版本的工具发现机制会用到,装了更稳妥。
- 一个可用的 Codex 版本。最好升级到比较新的稳定版,旧版本对 MCP 的支持不完整,后面很多功能会踩到“配置了但工具不出现”的坑。
另外要提前规划好 Hindsight 的存储目录。我习惯放在~/.hindsight/store,然后把整个目录纳入 gitignore。如果你的项目里有敏感文档,也可以把存储目录放到项目外部,避免被误提交。
2.2 Codex 的模型供应商配置:以 OpenAI 和 DeepSeek 为例
Codex 默认使用 OpenAI 的模型,但它的配置体系允许你通过model_providers接入其他兼容服务。Hindsight 本身不依赖具体模型供应商,但 Codex 侧需要明确到底走哪个接入点。下面是一段典型的~/.codex/config.toml:
model = "gpt-5" model_provider = "openai" [model_providers.openai] name = "OpenAI" base_url = "https://api.openai.com/v1" env_key = "OPENAI_API_KEY" [model_providers.deepseek] name = "DeepSeek" base_url = "https://api.deepseek.com/v1" env_key = "DEEPSEEK_API_KEY"注意两点。第一,base_url一定不要带/chat/completions这类路径后缀,Codex 会在后面自动拼接responses或chat/completions,你多写或少写都会报 endpoint 处理错误。第二,env_key对应的环境变量要在当前 shell 里提前导出,比如export DEEPSEEK_API_KEY=sk-xxx,Codex 不会帮你做任何密钥管理。
如果你切换了模型供应商,第一件事就是看会话里能否正常发起请求。先跑一句最简单的“你好”,确认连通性正常,再继续接 Hindsight。不要一次引入太多变量,否则后面出错你根本分不清是模型接入问题还是记忆服务问题。
3. 把 Hindsight 作为记忆服务挂进 Codex:安装与 MCP 注册
3.1 安装 Hindsight 并初始化存储
Hindsight 建议以 MCP(Model Context Protocol)服务器的方式接入 Codex。MCP 属于一种标准化的工具协议,让模型可以在对话中调用外部工具。Codex 通过 stdio 通道启动一个子进程,Hindsight 在这个进程里提供remember、recall、forget等工具。
先安装:
pip install hindsight-mcp然后初始化存储目录:
hindsight init --store ~/.hindsight/store --scope project--scope参数控制记忆的作用域,可选值有personal、project、global。我强烈建议日常开发用project,范围既不会太宽导致检索噪声大,也不会太窄导致信息割裂。初始化命令会在存储目录下创建索引文件、配置文件和日志目录。完成后你可以用hindsight status看一眼当前作用域、存储位置和索引数量。
3.2 在 Codex 配置里注册 MCP 服务
打开~/.codex/config.toml,追加如下内容:
[mcp_servers.hindsight] command = "uvx" args = ["hindsight-mcp", "--store", "~/.hindsight/store", "--scope", "project"]这里我推荐用uvx启动,而不是直接写 Python 解释器路径。uvx会帮你管理依赖环境和版本,避免出现“明明装了hindsight-mcp但 MCP 服务启动时找不到模块”的问题。如果你的环境里没有uvx,也可以改用:
[mcp_servers.hindsight] command = "/path/to/venv/bin/hindsight-mcp" args = ["--store", "~/.hindsight/store", "--scope", "project"]注册完成后,重启 Codex 会话。如果 Codex 支持codex mcp list命令,可以在终端里直接验证工具注册情况。这一步是很多人最容易忽略的——改完配置不重启,辛辛苦苦配的东西根本没加载。
3.3 验证工具是否进入 Codex 会话
重启会话后,直接对 Codex 说:“列出你当前可用的工具,并且告诉我 Hindsight 相关工具怎么用。”正常情况下,Codex 会列出类似hs_remember、hs_recall、hs_forget的工具。如果你看到“没有可用工具”“Hindsight 未注册”之类的答复,基本可以断定 MCP 服务没有成功启动。
我自己的验证习惯是分三层:先看进程有没有起来,再查codex mcp list,最后在对话里强制调用一次hs_recall。进程起来了只说明启动参数没报错,工具进了列表只说明注册成功,真正能不能调通,必须以对话里的实际调用结果为准。这三层缺一不可。
4. 记忆流程的日常操作:记录、检索、遗忘与管理
4.1 给 Hindsight 喂记忆的三种方式
接入之后,最核心的问题是怎么“喂”记忆。Hindsight 支持三种方式,我按推荐程度排序:
- 主动记录。在 Codex 会话里,当模型给出了一个关键结论、或者你做出一个重要决策时,直接发一句:“调用
hs_remember,记住:订单表主键统一用雪花 ID,不用自增。”这是精度最高的方式,因为它只存你真正关心的内容。 - CLI 手动追加。不开 Codex 的时候,也可以直接在终端执行:
hindsight add "支付回调幂等方案:Redis SETNX 加本地去重表"这种方式很适合在你通勤、整理思路时把碎片想法丢进去,不必打开对话界面。
- 自动抽取。Hindsight 可以配置成从 Codex 会话记录里自动抽取“决策类”“变更类”信息。但我要提醒一句:自动抽取是便利和噪声并存的。它经常会收录一堆临时调试信息、无意义的试探性讨论,反而拉低后续检索的准确度。我只建议在长期稳定项目里开自动抽取,并且设置一个关键词过滤规则,比如只抽取包含“决定”“改为了”“原因”“不建议”等词的句子。
4.2 检索记忆的正确姿势
检索是另一个需要练习的动作。很多人用了 Hindsight 之后觉得“没用”,原因是他们不知道该怎么问。直接说“帮我找订单相关记忆”会得到大而全的结果,里面一半是无关内容。更有效的提问方式是带约束的,比如:“调用hs_recall查询:订单模块幂等方案,只要 2024 年之后的记录,输出控制在 200 字以内。”
为什么这个细节关键?因为 Hindsight 召回的是一条条独立记忆片段,Codex 拿到结果后还要再做一遍筛选和重组。你给的条件越具体,Codex 做筛选时就越轻松,最后落在回答里的信息也就越精准。实测下来,带时间范围和主题范围的问题,召回准确率比裸提问高出不少。
4.3 遗忘机制与多项目隔离
记忆不是只进不出。Hindsight 提供了forget工具和定时清理策略。你可以让 Codex 调用hs_forget,按记忆 ID 精确删除;也可以用类似下面的命令按条件清理:
hindsight clean --scope project --older-than 90d我建议每周花两分钟看一眼记忆列表,把已失效的信息删掉。比如某个模块已经重构、某个决策已经被推翻,这些旧记忆如果不删,会和新增记忆打架,让模型给出自相矛盾的答案。
多项目隔离方面,Hindsight 的作用域设计就是为此存在的。两个不同项目都应该用各自的project作用域存储,避免 A 项目的缓存策略被 B 项目的会话错误地召回。如果你一个人维护多个仓库,建议在config.toml里为每个项目单独注册一个 MCP 服务,指向不同的存储目录。
5. 排错实录:连接失败、工具失效、模型不支持怎么处理
5.1 MCP 服务启动失败或工具列表为空
这是接入 Hindsight 最常见的坑,表现是:配置写了、版本也新、会话重启了,但模型就是看不到hs_开头的工具。我的排查链路是这样的:
先跑一条命令看 MCP 服务自身:
echo "" | hindsight-mcp --store ~/.hindsight/store --scope project正常情况下 Hindsight 会进入等待输入的状态,因为 stdio 通道已经在监听。如果这里直接报错,比如提示找不到模块、存储目录无权限,问题出在 Hindsight 侧,优先检查虚拟环境和目录权限。如果命令挂住了没有报错,但 Codex 里工具仍然不可见,问题大概率出在 Codex 对 MCP 的注册解析上。这时检查config.toml里的[mcp_servers.hindsight]表名是否拼错,TOML 的层级中括号是否配对,以及command是否能在 Codex 的运行环境里被解析到。
还有一个容易被忽略的点:如果你在config.toml里同时配置了多个 MCP 服务器,某一个启动失败可能会导致整个 MCP 注册流程中断。我碰到过一次,一个旧的 MCP 服务报错,连累后面的 Hindsight 根本没走到注册阶段。处理方法是把不用的 MCP 配置先注释掉,只保留 Hindsight,再逐步把其他服务加回来。
5.2 请求提示模型不支持或模型 ID 未识别
有些接入方会碰到类似“模型不支持”“模型 ID 不存在”的错误。常见原因是config.toml里model字段指定了一个当前接入点不支持的模型名。比如某些兼容服务并不提供最新的模型,而你写死了最新的模型 ID。这时候不要怀疑 Hindsight,它是纯工具层,不参与模型选择。你应该做的是把model调整为接入方实际支持的模型名,或者干脆把model_provider切回 OpenAI 官方,确认 Hindsight 能正常工作后再切回原供应商。
另外,我发现很多人在配置里填了model_provider但忘了给对应的环境变量赋值,导致绕了一圈又退回默认供应商。系统提示“认证失败”“无法获取 API 密钥”时,先检查env变量名和config.toml里的env_key是否完全一致。多一个下划线、大小写不同都不会被识别。
5.3 工具调用超时或反馈慢
Hindsight 的工具调用本身很快,但你会在两种场景里感受到明显的慢。第一种是本地向量索引没有预热,首次检索需要载入嵌入模型;第二种是存储目录里积累了海量碎片,检索排序的耗时随数据量线性增长。前者可以通过启动时预加载索引缓解,后者只能靠定期清理记忆来解决。
我建议给 Hindsight 存储目录设置一个告警阈值,比如超过 500MB 就提醒自己跑一次清理。记忆这玩意儿和现实中的收纳一样,真正有价值的永远是少数,其余都是干扰。
5.4 配置项提示无法识别
如果你在终端看到类似“ignoring 1 unrecognized configuration setting”的提示,说明config.toml里出现了当前 Codex 版本不认识的关键字。这多半是文档版本和实际安装版本不同步导致的,比如新版本文档里的配置项,在旧版本里压根不存在。不要硬删配置,先用codex --version确认版本,再查当前版本支持的完整配置字段。如果某字段确定不支持,就把它注释掉,不要留着一个不会生效的配置项在那里误导排错。
6. 从“能跑”到“好用”:记忆的卫生与工作流设计
6.1 记忆不是越大越好
把 Hindsight 接到 Codex 之后,最常犯的错就是“什么都记”。恨不得把每次会话的聊天记录都灌进去,最后发现检索结果越来越像搜索引擎的垃圾页面,什么都有,什么都不可信。
我自己的记忆卫生规则很简单:每条记忆必须满足“未来还会用得上”和“无法从代码里直接看出来”至少一条。像“新建了 src/utils/date.ts”这种,代码里一眼就能看到,不需要记;“支付回调用 Redis SETNX 做幂等,因为数据库唯一索引在大量并发下会有热点问题”这种,代码里看不出来,必须记。按这个标准,一个中型项目运行三个月,有效记忆可能也就是两三百条,这个量级对检索效率和准确率都是最友好的。
6.2 适合接入记忆流的场景
复盘过自己过去一个月的使用记录,Hindsight 价值最大的场景有三个。
第一是架构决策追踪。Codex 连续多天帮你迭代一个模块时,它会因为有了记忆而不需要你反复重申“不要引入新的状态管理库”“数据库直连只允许写在 repository 层”这类规矩。第二是跨会话问题修复。线上出了 bug,一天前你刚处理过类似问题,新会话里 Codex 能直接召回当时的根因分析,省掉大量重复诊断。第三是技术方案对比。你犹豫两个方案时,可以直接让 Codex 从记忆里找出之前讨论过的候选方案和否决理由,再结合当前情况做决策,而不是无中生有地编一份理由。
6.3 多智能体共享记忆与后续扩展
Hindsight 的存储格式是结构化的,作用域隔离做得不错,所以我后来还做了一件事:把 Hindsight 的存储目录同时暴露给其他工具使用,实现多个智能体共享一套项目记忆。比如我有时候用 Codex 写代码,用另一个终端工具做代码审查,两者的记忆基础是同一套。审查工具看到“订单模块主键用雪花 ID”的决策,就不会在审查时提出“为什么不用 UUID”这种问题。
如果你还想进一步发展,可以给 Hindsight 加一层定期的“记忆总结”逻辑——每隔一段时间,把星期内零散的记忆归拢成几条更抽象的结论。旧记忆归档,新记忆轻装上路。这套思路和团队里做知识库运营没什么两样,区别只是执行者从人换成了程序。
接入 Hindsight 之后,Codex 才真正从“一次性对话工具”变成了“带长期记忆的开发伙伴”。我的真实体会是:刚开始会不习惯,总忘记主动记录,检索也问不到点上;等跑过两三个项目,把记忆卫生养成习惯,你会明显感觉到 Codex 的答案质量稳定了一大截。最后分享一个小技巧:把每天都在用的几个 Hindsight 操作做成一两条 shell 别名,一是方便随手记,二是不容易忘记这个系统的存在。记忆这东西,最怕的就是你忘记你还有记忆。