十分钟搭建多 Agent 共享记忆:从 Claude 到 Codex 再也不失忆

本段核心问题:当你在 Claude Code 和 Codex 之间频繁切换时,为什么每个 Agent 都像“失忆”了一样,需要你重新交代一遍当前任务和上下文?怎么用一个本地目录解决这个问题?

我一直在用 Claude Code,里面已经慢慢长出了一整套生态:memory、skills、vault、hooks。这堆东西不是一天建成的,是过去几个月边用边搭,一点一点攒起来的。每个会话的偏好、活跃任务、用户画像,Claude 都记得清清楚楚。

但最近 Codex 用得越来越多——有些场景它确实更强。比如某些代码生成速度、特定框架的理解深度,Codex 的表现会让我眼前一亮。

问题来了。

每次从 Claude 切到 Codex,Codex 根本不知道 Claude 刚才做了什么决策、当前有什么活跃任务、用户画像是什么。我每次都要重新交代一遍:“我是谁、我在做什么项目、今天做到哪了、有哪些高优任务没完成……”

同样的故事反过来也一样。Codex 跑完一轮,切回 Claude,Claude 对 Codex 刚刚执行的结果一无所知。

这种“切换失忆”的痛苦,我相信每一个同时用多个 AI 编程 Agent 的人都懂。

解法不是二选一。 不是非要决定“我以后只用 Claude”或者“我彻底迁移到 Codex”。而是在两个 Agent 之间搭一层共享——让它们通过一个中立的本地目录交换信息,彼此知道对方的状态。

这套方案不需要 MCP,不需要 A2A 协议,也不需要任何云端编排服务。文件系统本身就是同步机制。 每次 session 重新读文件,就是最新状态。

下面这七步,十分钟能跑通。


第一步:建目录结构——物理隔离 + 共享边界

本段核心问题:共享目录应该怎么设计,才能既让两个 Agent 交换信息,又防止它们互相污染对方的私有数据?

在 home 目录下建一个 ~/.agents/,作为多 Agent 协作的唯一枢纽。

~/.agents/
    contracts/        # 两边都要读的协议
    shared/           # Claude 投影出的中立数据,Codex 只读
    handoff/          # Codex 写回给 Claude 的交接信息
    manifests/        # 哪些该共享、哪些不该共享的边界定义

这里有一条铁律,我吃过亏才定下来的:

Claude 不碰 .codex/,Codex 不碰 .claude/。所有协作通过 ~/.agents/ 完成。

为什么要这么严格?因为之前我试过让它们直接读对方的目录,结果 Claude 不小心改写了 Codex 的配置文件,Codex 下一次启动直接报错。把私有目录完全隔离开,用目录权限限制边界,是最简单也最不容易出错的方案。

反思:我学到的教训是——不要让 Agent 越界。每个 Agent 的私有目录像它的“家”,共享目录像“会议室”。Agent 可以在会议室讨论,但不会跑到对方家里翻东西。


第二步:写 contracts——两边都读的协议

本段核心问题:怎么保证两个 Agent 对共享规则的理解完全一致?contracts 文件里到底要写什么?

contracts 目录里放两个文件,每个 Agent 启动时都要读。这两个文件定义了“怎么共享”和“怎么交接”。

claude-shared.md(Claude 侧的投影规则)

# Claude → Shared Layer 投影规则

## Session 结束时执行
1. 更新 shared/profile.md(仅当用户画像有变化时)
2. 覆盖写入 shared/tasks.json(活跃任务列表,全量覆盖)
3. 覆盖写入 shared/today-summary.md(当日进展,全量覆盖)

## 投影规则
- shared/ 中的文件是精简版,不是 .claude/ 内部文件的镜像
- 每个 shared 文件有且仅有一个源文件
- 不在投影过程中合成多个来源的数据
- 提取规则用信号词匹配,不用语义摘要

codex-global.md(Codex 侧的启动和交接协议)

# Codex 启动协议

## Session 开始时执行
1. 读 ~/.agents/contracts/codex-global.md
2. 读 ~/.agents/shared/profile.md
3. 读 ~/.agents/shared/tasks.json
4. 读 ~/.agents/shared/today-summary.md
5. 检查 ~/.agents/handoff/latest.md 是否有未处理的交接

## Session 结束时执行
1. 如有需要 Claude 处理的事项,写入 ~/.agents/handoff/latest.md

场景化理解:你可以把 contracts 想象成两个国家之间的“外交协议”。Claude 和 Codex 各有一份,里面写清楚了:什么时候该写什么文件、什么时候该读什么文件、交接的格式是什么。两边都认同一份协议,才不会出现“我说了你不听”的情况。


第三步:写 manifest——定义共享边界

本段核心问题:哪些信息应该共享,哪些信息绝对不能共享?怎么定义一个清晰的边界,让以后新增共享内容时不出错?

manifests/must-share.json 的作用很简单:定义什么该共享,什么不该共享。

{
  "shared": [
    {
      "file": "profile.md",
      "source": ".claude/memory/working-with-me.md",
      "update": "on-change",
      "description": "用户画像,稳定信息"
    },
    {
      "file": "tasks.json",
      "source": ".claude/memory/active-tasks.json",
      "update": "every-session-end",
      "description": "活跃任务,热数据"
    },
    {
      "file": "today-summary.md",
      "source": ".claude/memory/today.md",
      "update": "every-session-end",
      "description": "当日进展,每次覆盖"
    }
  ],
  "private": [
    ".claude/memory/personal-notes.md",
    ".claude/memory/private/",
    ".codex/sessions/"
  ]
}

以后如果加了新的共享文件,就在这里加一条,两个 Agent 都认。如果一个文件不应该被对方看到,就明确写进 private

为什么需要 manifest? 因为我发现如果不显式定义边界,随着时间推移,很容易“顺手”把不该共享的东西放进 shared 目录。比如有一次我不小心把个人笔记也投影出去了,虽然 Codex 不会主动读它,但这个行为本身就是风险。manifest 就像一份“海关清单”,每次加新文件都要过一遍清单,该放行的放行,该拦截的拦截。

日常维护:每周花五分钟看一眼 must-share.json——有没有新的共享需求冒出来?有没有不该共享的东西混进去了?其他部分基本都是自动的。


第四步:搭 shared 层——Claude 投影出中立数据

本段核心问题:shared 目录里到底要放什么格式的文件?怎么保证这些文件是“精简、稳定、可被另一个 Agent 直接理解”的?

shared 目录里放三个文件。只有 Claude 写,Codex 只读。

shared/profile.md(用户画像)

# 用户画像

## 身份
[角色、所做的工作]

## 长期偏好
- 写代码优先简洁,不提前优化
- 做设计时先定义边界,再展开
- 判断大于信息整理

## 知识领域
[擅长什么、不擅长什么]

## 当前项目
[项目名 + 一句话目标]

这份文件只在用户画像真正发生变化时才更新。不是每次 session 结束都写——因为没必要。Profile 是相对稳定的信息,频繁覆盖反而增加了 noise。

shared/tasks.json(活跃任务)

{
  "updated": "2026-05-27T18:30:00+08:00",
  "tasks": [
    {
      "id": "1",
      "title": "双 Agent 协作层搭建",
      "status": "in-progress",
      "priority": "high",
      "deadline": "2026-05-30",
      "notes": "~/.agents/ 目录已建,contracts 写完,shared 层进行中"
    }
  ]
}

每次 Claude session 结束时全量覆盖。注意一个细节:deadline 只在源数据有明确日期格式时才写入。比如“2026-05-30”或“4/24”可以写,但“月底”“下周”这种不确定日期,不写。为什么?因为 Codex 读到不确定日期时可能会做错误推断,与其让它猜,不如不提供。

shared/today-summary.md(当日进展)

# 当日进展 — 2026-05-27

## 已完成
- shared 层目录结构搭建完成
- contracts 两个文件写完

## 需关注
- manifests/must-share.json 下周需要 review 一次字段是否够用

## 下一步
- 在 Codex 的 codex-global.md 里加 shared 层读取逻辑

每次 Claude session 结束全量覆盖。提取“需关注”时只用信号词匹配:“结论 / 确认 / 里程碑 / 通过 / 决定 / 阻塞 / 推迟”

不做语义摘要。因为这层不是为了聪明,而是为了稳定。

这是我踩过的一个坑:一开始我尝试让 Claude 用自然语言写“需关注”,结果它写了一堆模棱两可的话,Codex 根本 parse 不了。后来改成纯粹的信号词匹配——只有出现这些关键词才写进去。虽然“笨”了一点,但 Codex 每次都能稳定读到有效信息。

场景化案例:假设我下午用 Claude 修复了一个复杂的 bug,Claude 在 today-summary.md 的“已完成”里写上了这条记录。晚上我切到 Codex 想继续做另一个任务,Codex 读到“已完成”列表,就知道不用再碰那个 bug 了。同时,如果我在 Claude 里标记了一个“阻塞”项,Codex 读到后会主动避开被阻塞的任务,先去处理其他高优任务。


第五步:让两个 Agent 读共享层——注入启动指令

本段核心问题:具体要在 Claude 和 Codex 的配置文件里加什么代码,才能让它们在启动时自动读取共享层?

Claude 侧:在 CLAUDE.md 加两段

## Session Start
Read ~/.agents/contracts/claude-shared.md
Check ~/.agents/handoff/latest.md — 如果有新的交接信息,先处理再开始

## Session End
按 ~/.agents/contracts/claude-shared.md 投影规则更新 shared/

Codex 侧:在 CODEX.mdcodex-global.md

## Session Start
Read ~/.agents/contracts/codex-global.md
Read ~/.agents/shared/profile.md
Read ~/.agents/shared/tasks.json
Read ~/.agents/shared/today-summary.md
Check ~/.agents/handoff/ — 如果有未处理的交接文件,先读

## Session End
如有 Claude 需知晓的事项 → 写入 ~/.agents/handoff/latest.md

双保险:Codex 的 config.toml 里可以再加一段 model_instructions_file。这样即使 CODEX.md 没被读到,启动时也会加载共享层指令。

为什么需要显式写在 Session Start 里? 因为我发现如果不写在启动阶段,Agent 在对话过程中很容易“忘记”去读共享文件。把它固化在启动流程里,就像每天早上刷牙一样——变成一个自动执行的惯性动作。


第六步:搭 handoff——Codex 写回给 Claude 的交接

本段核心问题:Codex 跑完任务后,怎么把需要 Claude 关注的信息“递”回去?handoff 目录的格式和生命周期是什么?

Codex 跑完之后,如果有需要让 Claude 知道的事,就写到 handoff 目录。

handoff/latest.md

# Codex → Claude 交接 — 2026-05-27

## 已完成
- 修复 shared/tasks.json 中 deadline 字段的空值问题
- 更新 codex-global.md 的启动读取逻辑

## 需要 Claude 关注
- shared/tasks.json 新增了一条来自 Codex 执行结果的任务,请确认是否纳入活跃列表

## 阻塞项
-

交接的生命周期

  1. Codex session 结束时写入 handoff/latest.md
  2. Claude 下次启动时读到这个文件
  3. Claude 处理完之后,把它移到 handoff/archive/,文件名加日期(如 2026-05-27-latest.md
  4. Codex 下次检查 handoff/ 目录为空,就知道上一次交接已经被处理

场景化理解:handoff 就像两个人交接班时写的一张便条。Codex 值完夜班,把“今晚发生了什么、明天早上需要注意什么”写在便条上贴在白板。Claude 早上来上班,第一件事就是看白板上的便条,处理完就把便条收进抽屉。下一晚 Codex 来值班,看到白板是空的,就知道没有未处理的交接。

反思:我最初的设计是让两个 Agent 直接写对方的私有目录,结果经常出现“写进去但对方没读到”的情况——因为读取时机不对。后来改成 handoff 目录 + 显式的“移动归档”机制,问题就解决了。关键是要让“已处理”这个状态有明确的物理表示(文件被移走)。


第七步:验证——三个测试确保跑通

本段核心问题:我怎么确认这套共享层真正在工作?应该做哪几个测试来验证每个环节都没问题?

测试一:Codex 读共享层

在 home 目录启动 Codex,确认它读到了:


  • ~/.agents/contracts/codex-global.md

  • ~/.agents/shared/profile.md

  • ~/.agents/shared/tasks.json

  • ~/.agents/shared/today-summary.md

哪个文件没读到,就检查路径是否正确。

测试二:Claude 读 handoff

在 vault 目录启动 Claude,确认它读到了 handoff/latest.md。如果 Codex 上次留了东西但 Claude 没检测到,就检查 CLAUDE.md 里的 session start 指令是否写对了位置。

测试三:完整闭环

完整走一圈:

  1. Claude 写 shared(profile、tasks、today-summary)
  2. Codex 读 shared 执行任务
  3. Codex 写 handoff(latest.md)
  4. Claude 下次启动读 handoff 处理交接
  5. Claude 把 handoff 文件移到 archive

这一圈通了,共享层就跑起来了。


日常使用流程——切换 Agent 变成自动的

本段核心问题:这套系统在日常工作中具体怎么用?从 Claude 切到 Codex 和从 Codex 切回 Claude 分别是什么体验?

从 Claude 切到 Codex

  1. Codex 启动时读 shared/profile.md——知道你是谁、你的长期偏好、你的知识领域
  2. shared/tasks.json——知道当前有哪些活跃任务、优先级、截止日期
  3. shared/today-summary.md——知道今天做到哪了、有哪些需关注的点

实际体验:你不需要再跟 Codex 说“我是一个写后端 Go 的开发者,偏好简洁代码,当前在做订单系统重构,今天已经完成了数据库迁移,接下来需要写 API 层”。这些信息 Codex 自己就读到了。

从 Codex 切回 Claude

  1. Claude 启动时读 handoff/latest.md
  2. 知道 Codex 做了什么、需要关注什么
  3. 处理完,把 handoff 文件移走

实际体验:Claude 会主动告诉你“Codex 刚才修复了 tasks.json 里的 deadline 空值问题,并新增了一条任务等待你确认”。你不需要再手动同步这些信息。


最后说一下——这套方案跟云端多 Agent 编排不是一回事

本段核心问题:这套本地目录方案和那些云端多 Agent 编排框架(如 AutoGen、CrewAI)有什么区别?它适合什么场景、不适合什么场景?

它不处理并发。不处理分布式状态。不需要 MCP,也不需要 A2A 协议。

文件系统本身就是同步机制。 每次 session 重新读文件,就是最新状态。

这意味着:


  • 如果你需要两个 Agent 同时 写同一个文件,这套方案不适用

  • 如果你需要毫秒级的状态同步,这套方案不适用

  • 如果你需要一个中心化的 orchestrator 来调度任务,这套方案不适用

但它非常适合:


  • 你一个人在用多个 Agent,不同时间切换

  • 你希望保持简单的、可审计的、文件级别的状态共享

  • 你不想引入额外的依赖和服务

反思:我最初也尝试过用 Redis 或者 SQLite 来做共享存储,但发现杀鸡用牛刀。文件系统已经提供了足够的原子性(写一个文件是原子的),而且任何人都能直接 cat 查看状态,调试极其方便。


一页速览:操作清单

步骤 做什么 关键文件 一句话说明
1 建目录 ~/.agents/ 共享目录总入口
2 写协议 contracts/claude-shared.md
contracts/codex-global.md
定义投影和交接规则
3 定边界 manifests/must-share.json 明确什么共享、什么私有
4 搭共享层 shared/profile.md
shared/tasks.json
shared/today-summary.md
Claude 投影,Codex 只读
5 注入启动指令 CLAUDE.md
CODEX.md
让两个 Agent 在 session 首尾自动读写
6 搭交接 handoff/latest.md Codex 写回给 Claude
7 验证 三个测试 确保闭环跑通

常见问答(FAQ)

Q1:Claude 和 Codex 的私有目录具体在哪里?

Claude 的私有目录通常是项目目录下的 .claude/,Codex 的私有目录是 .codex/。你的 home 目录下的 ~/.agents/ 是独立的共享层。

Q2:Claude session 结束时不更新 profile.md 可以吗?

可以。must-share.json 里定义 profile.md 的更新策略是 "on-change",只有在用户画像真正变化时才更新。不是每次 session 结束都写。

Q3:Codex 读到 handoff 目录非空时,应该先读哪一个?

按文件名排序,最新的优先。latest.md 就是约定的最新交接文件。处理完后把它移到 archive/

Q4:如果两个 Agent 同时写同一个 shared 文件怎么办?

这套方案不设计并发写入。它假设你是串行使用——同一时间只有一个 Agent 在活跃。如果你需要并发,这套方案不适合你。

Q5:信号词匹配具体怎么做?能举个例子吗?

Claude 在生成 today-summary.md 的“需关注”部分时,只扫描 .claude/memory/today.md 中出现了“阻塞”“决定”“里程碑”等关键词的句子,直接复制过来,不做任何总结或改写。

Q6:我用的不是 Claude Code 和 Codex,是其他 Agent,能套用吗?

可以。这套方案的核心理念是“共享目录 + 启动协议 + 交接文件 + 边界清单”,只要你的 Agent 支持在 session start/end 时执行自定义指令(读文件、写文件),就能迁移。

Q7:这套方案会泄露我的隐私信息吗?

manifests/must-share.json 里的 private 列表明确列出了不共享的目录和文件。只要你不把私有文件路径加入 shared 列表,就不会泄露。


实用摘要


  • ~/.agents/ 作为多 Agent 共享目录

  • contracts/ 定义投影和交接协议,双方都读

  • manifests/ 定义共享边界,新增文件时维护

  • shared/ 放 Claude 投影的精简数据,Codex 只读

  • handoff/ 放 Codex 写回给 Claude 的交接信息

  • CLAUDE.mdCODEX.md 的 session start/end 注入读写指令

  • 三个测试验证闭环:Codex 读共享 → Codex 写 handoff → Claude 读 handoff

  • 文件系统就是同步机制,不依赖任何云端编排框架