Claude Code 失忆破解:三文件外置大脑实战指南
2026/9/6 21:43:29 网站建设 项目流程

1. 同事那句灵魂拷问,点破了多少人的隐忧

事情是这样的,上个月我们组里推进一个内部工具的重构,我连着几天把活儿都交给 Claude Code 去干。每次开工前先让它读一遍项目说明,再把当前要改的模块喂给它,它干得倒是又快又利索。结果有位同事在旁边盯了半天,冷不丁问我一句:“这玩意不是经常失忆吗?你让它改这么多轮,不怕它哪次心血来潮把项目搞炸了?”

我当时就乐了,但仔细一想,这确实是所有重度使用者绕不开的痛。

先说结论:Claude Code 确实会“失忆”,或者说,它的记忆机制远没有我们想象的那么智能。它每一次响应都受上下文窗口限制,当对话轮数变多、代码片段变长,早期的关键信息就会像水一样从筛子里漏掉。你对它说过的话、它自己做出的决策,都可能随着对话推进被遗忘。

这种失忆带来最典型的几个现场:

  • 你上午让它确定了项目的目录结构是src/lib,下午再让它新增一个模块,它可能又重新创造出一套lib/src,俩目录并存。
  • 你明确禁止它改动某个配置文件,交代谢过三次了,它在下一次重构中继续踩雷。
  • 你之前让它实现一个工具函数的接口定义,过几轮后它调用的时候连参数名都变了。
  • 它自己写过的常量值、依赖版本、端口号,一翻脸就全都不认识了。

这些问题的本质是什么?不是 Claude Code 不够聪明,而是它默认不维护任何长期记忆。每轮对话虽然能看到历史消息,但当上下文超限后就只能“选择性失明”。指望靠聊天记录来延续项目心智,等同于用便利贴管理一份 10 万行的代码库,翻着翻着就丢页了。

我当时给同事的回答很简单:怕,当然怕。所以我从来不把 Claude Code 当成一个“靠聊天推进项目”的工具,而是让它成为一个“按文档执行项目”的工具。这中间的差别非常关键——聊天会失忆,但文件不会。我给它配了三个 Markdown 文件作为外置大脑,相当于给一个记忆力不稳定的同事准备了一份永远可以翻看的工作手册、项目档案和变更日志。它每次开工前先读这三个文件,干完活就更新这三个文件,循环往复。这样无论对话怎么变、上下文怎么抖、窗口怎么清,核心信息都安全地躺在磁盘上,一次写入,永久有效。

这篇文章我结合自己的实际使用习惯,把整套方案完全拆开来讲。从为什么三个文件、每个文件里写什么、目录怎么组织、怎么最小化 token 开销,到实际跑了一个小项目后的前后对比,都会覆盖到。无论你是已经装了 Claude Code 但总觉得它不好使,还是正准备入坑还没想清楚工程化玩法,这套东西都能直接抄作业。

2. 先摸清楚 Claude Code 的“失忆”到底丢的是哪类记忆

在讲外置大脑之前,有必要先把“失忆”这件事掰开揉碎。很多人以为 Claude Code 失忆是因为“模型不行”,这话对了一半,但更准确的原因是它没有一套结构化记忆管理策略

2.1 上下文窗口不是无穷大的,遗忘是物理规律

每个 Claude Code 会话都有一个上下文窗口,当前模型大约能承载 20 万 token 左右的上下文。听起来很多对吧?但实际用起来完全不够看。一段 1000 行的源代码大概 8000 到 10000 token,一个模块的 README 又要 1000 token,再加上你的指令、它的回复、中间过程的报错信息,几轮对话下来,20 万 token 就见底了。

上下文窗口占满之后会发生什么?Claude Code 的处理机制是:较早的消息会被“挤掉”或者被压缩。也就是说,你在第 3 轮说的“这个项目必须遵守目录结构 A",到了第 20 轮可能已经被挤出视窗,它只记得最近十几轮的对话内容。于是它基于残缺的信息做决策,自然就会产出偏离预期的代码。

这里有个很反直觉的点:很多时候不是 Claude Code 故意犯错,而是它真的“没看见”你以前说过的话。就像一个人走进会议室,手里只有最后 20 分钟的开会记录,前两个小时的结论完全没看过,那你不能怪他把之前敲定的事搞砸了。

2.2 它失忆的往往是“项目级约束”,而不是“对话级内容”

如果把记忆分成两类,一类是会话内短期记忆,一类是跨会话长期记忆,你会发现 Claude Code 真正缺的不是短期记忆,因为它在正常窗口内表现还是不错的;它缺的是对项目约束、全局约定和状态变更的持久化能力。

举个例子,我让它在config.py里添加一个新参数。它如果记得本项目所有配置项都必须放到Config类中且通过环境变量覆盖,那就叫项目级记忆。但现实是,这话你可能只在项目开头说了一次,几轮之后它可能就自己新建一个settings.py,因为它在窗口里再也找不到相关的约定内容了。

再比如接口风格。你定了所有 API 返回格式为{ code: 0, data: ..., msg: "..." },如果这个约束不在“硬盘上的文档”里,而在“对话历史里”,那基本等于没有约束,早晚会被违反。

失忆的坏处不只是“它会写错代码”,更危险的是它会在无意识中破坏之前已经写好的正确代码。因为记不住之前的接口签名,它会用新的方式去调用旧的函数,导致大面积重构错误。这才是同事说“怕它把项目搞炸”背后的真实担忧——不是担心它写不出来新功能,而是担心它忘了旧约定,把原本稳定的部分改得面目全非。

2.3 一个实验:同样一个任务,有无记忆文件的差别有多大

我给自己做了一次小试验。用两个全新的会话,让 Claude Code 完成同一个任务:为一个小型 Python 项目增加一个数据校验模块。

第一个会话没有挂任何记忆文件,我直接说“帮我在项目里加一个数据校验模块”。它很快做完了,模块文件是validators.py,里面实现了一个validate_email()函数,入参是字符串,返回布尔值。

第二个会话我提前在项目根目录放了一个AGENTS.md(这个文件名下文会详细讲),里面写清楚了:本项目所有组件放src/utils目录;模块用名词复数命名;函数返回统一为(success, error_msg, data)三元组;新增代码必须补测试。

同样的指令,“帮我在项目里加一个数据校验模块”,结果它把模块放到了src/utils/validators.py,实现了validate_email()函数,返回的是(True, "", {...})这样的三元组,还顺带写了三个单元测试用例,全部通过。

差别肉眼可见。一个靠猜,一个靠翻阅档案再动手。这不就是真实团队里“老手”和“萌新”的区别吗?萌新凭感觉干活,老手先查规范和文档,再按规律执行。

所以,想让 Claude Code 稳定输出,你要做的不是祈祷它别忘,而是把它从“靠记忆干活”的状态,强行扭转到“靠查阅干活”的状态。外置大脑就是这么个东西——它把“记忆”从易失的对话历史中抽离出来,放进了可靠的持久化存储里。

3. 方案总览:为什么是“三个”文件,而不是一个总控文档

明确了问题根源之后,接下来就是设计解法。很多人在网上搜到过类似的方案,大多数是“用一个 AGENTS.md 文件给 Claude Code 当项目说明”。这个思路是对的,但实操下来我发现只有单个文件远远不够。原因很简单:一个文件承担了太多职责,它会越长越臃肿,最后变得既不适合高频更新,也不适合快速定位,反而成为一个大杂烩。

我的方案是三个 Markdown 文件相互配合,构成一套完整的外置记忆系统。本质上是参考了软件工程里的“关注点分离”思想:不同性质的信息放到不同的存储位置,各司其职,互不干扰。

三个文件的角色如下:

文件核心职责更新频率一句话类比
AGENTS.md全局规则与偏好约定低(偶尔修改)员工手册
PROJECT.md项目专属事实、结构、约束中(随项目演进更新)项目档案
LOG.md操作记录与变更历史高(每次会话结束都更新)工作日志

上面这个表格是快速概览,接下来我把每个文件的设计逻辑和内容模板展开来讲。

3.1 为什么留了 CLAUDE.md 不用,而选择 AGENTS.md

这里有个细节值得先说清楚。现在官方的 Claude Code 实际上支持一个名为CLAUDE.md的项目记忆文件,会自动被加载进每次会话的上下文中。按理说,直接用它不就行了吗?为什么我用的是AGENTS.md

因为我的工作流并不是只在 Claude Code 里玩,我平时会切换不同的 AI 编码工具,比如各种兼容层、其他 CLI 助手、甚至是我自己写的脚本。用AGENTS.md这个文件名,意味着同样一份项目规则可以被更多工具共享,而CLAUDE.md则过于绑定单一产品。

当然,如果你只用 Claude Code,直接采用CLAUDE.md也完全没问题。两者语法上都是 Markdown,内容组织方式一模一样。我这里的核心方法论是“外置大脑由三个文件构成”,文件具体叫什么,根据自己的工具链取舍即可。下文为了叙述统一,仍然以AGENTS.md为例展开。

3.2 AGENTS.md:给 Claude Code 配备“员工手册”

第一个文件解决的是行为基准问题。它的作用范围是“无论你在这个项目的任何模块里做什么事,都得遵守这些约定”。

员工手册里写的不是具体怎么完成某一项工作,而是通用的做事原则。所以AGENTS.md里应该放这些内容:

  • 项目的整体技术栈和语言偏好(是 Python 还是 TypeScript?是 ESM 还是 CommonJS?)。
  • 代码风格上的硬性要求(缩进、命名规范、错误处理方式)。
  • 测试要求(新代码要不要强制带测试?测试框架是哪个?)。
  • 提交信息格式、分支命名规则。
  • 一些通用的“不要做”条款,比如“不要修改生成器输出的代码”“不要动migrations/目录下的文件”。

这里的关键是:内容必须精炼,不能写成大而全的百科。因为 AGENTS.md 是每次会话开头都会读一遍的,内容太长会直接拉高每次任务的 token 消耗,而且稀释重点。一个合格的做法是控制在 100 到 200 行之内,只写“涉及整个项目所有改动都必须知道的规则”。

我自己的 AGENTS.md 长这样(这是一段示例,去掉了我项目里真正的敏感细节):

# 项目全局规则 ## 技术栈 - Python 3.11+ - FastAPI + SQLAlchemy 2.x + PostgreSQL - 前端使用 React + TypeScript + Vite ## 代码风格 - Python 代码使用 Black 默认格式,行宽 88 - 类型注解必须完整,禁止使用裸 `dict` 作为函数返回值类型 - 所有 API 返回统一包裹为 `ApiResponse` 模型 ## 测试 - 新增或修改后端逻辑必须补充对应的 pytest 测试 - 测试文件放在 `tests/` 目录下,与被测模块路径对齐 - 涉及数据库的操作一律使用 testcontainers 启动真实 PG,不能 mock ## 约定与红线 - 禁止修改 `alembic/versions/` 下的已发布迁移脚本 - 禁止把密钥、密码硬编码到代码中,环境变量统一由 `pydantic-settings` 管理 - 所有被 `@router.get` 装饰的接口都必须写 OpenAPI 摘要 ## 工作流偏好 - 每次完成一个功能点后,主动运行 `make lint && make test` - 提交信息格式:`<type>(<scope>): <subject>`,例如 `fix(auth): handle token expiry`

这样的文件写完后,基本就不会频繁变。只有当项目发生了技术栈切换、全局规则调整时才需要动它。

3.3 PROJECT.md:让所有项目专属信息活在文档中

第二个文件是项目档案。如果说 AGENTS.md 回答的是“在我们这个团队里一般怎么干活”,那 PROJECT.md 回答的就是“我们这个项目具体长什么样、现在处于什么状态”。

这里放的信息比 AGENTS.md 更具体、更易变,包括:

  • 项目定位与核心功能模块清单。
  • 目录结构说明,特别是哪些目录是可以动的,哪些是生成物不能动。
  • 数据库表清单及关联关系(或至少是 ER 结构的文本描述)。
  • 关键的领域模型:User、Order、Product 这些实体的核心字段和状态机。
  • 外部服务依赖:有没有 Redis、RabbitMQ、S3 之类的中间件。
  • 当前迭代正在做什么、接下来要做什么。

PROJECT.md 的更新频率比 AGENTS.md 高很多,但也不至于每次对话都改。它更像是“项目从一个阶段进入下一个阶段时,你同步更新档案”。比如你新增了一个模块,那就往 PROJECT.md 里面追加一段模块说明;你重构了数据库表结构,那就要同步改掉旧的表关系描述。

实际模板示例:

# 项目档案 ## 一句话定位 面向公司内部的订单履约中台,负责从下单到出库的全链路状态流转。 ## 目录结构约定 - `src/api/`:HTTP 接口层,只放路由和请求/响应模型 - `src/service/`:业务逻辑层,所有核心流程都在这里 - `src/model/`:SQLAlchemy ORM 模型 - `src/repository/`:数据库查询封装 - `tests/`:pytest 测试 - `docs/`:除了本文件之外的架构文档 注意:`src/model/` 里的类只做数据映射,不允许写业务逻辑。 ## 核心领域模型 ### Order(订单) - 状态机:`PENDING -> PAID -> FULFILLING -> SHIPPED -> COMPLETED` - 取消路径:`PENDING/PAID -> CANCELLED` - 关键字段:`order_no`(唯一订单号), `user_id`, `total_amount`, `status` ### Payment(支付单) - 一个 Order 对应一到多个 Payment(支持部分支付/多次退款) - 关键字段:`payment_no`, `order_id`, `amount`, `paid_at` ## 外部依赖 - PostgreSQL 15(主库),库名 `order_center` - Redis 7(缓存 + 分布式锁),默认 DB 0 - RabbitMQ(事件总线),exchange 类型为 topic ## 当前迭代状态 - 正在做:订单超时自动取消的定时任务 - 最近完成:支付回调接口幂等性改造 - 待办:对账文件生成逻辑

3.4 LOG.md:把每次会话的“前因后果”固化下来

第三个文件是最容易被忽视、但实际价值最高的——变更日志

你可能会想:项目里不是有 Git 吗?Git 提交记录不就是最完整的操作日志吗?为什么还要单独维护一个 LOG.md?

原因很直接:Git 记录的是代码维度的变更,但 Claude Code 需要的是“意图维度的变更”。比如这次重构背后的原因是什么、之前设计某个接口时想到了哪几个替代方案、为什么最终选了这个方案、有哪些隐含约定是代码里看不出来的,这些信息都不会出现在 Git 提交里,但它们恰恰是避免 Claude Code 下次“想当然”做出错误决策的良药。

LOG.md 的更新时机是:每次和 Claude Code 干完一通活之后,把这次会话中产生的重要决策、踩过的坑、遗留的 TODO 都追加进去。

写法上推荐用倒序追加,最新的记录排在最上面,方便下次会话能一眼看到最近发生了什么:

# 变更日志 ## 2025.06.22 - 重构支付回调处理流程 - 背景:支付回调存在重复通知,当前逻辑对重复通知支持不完善 - 改动:在 PaymentService 中增加 `process_notification()`,依赖 `payment_no + event_id` 做幂等 - 决策:使用 Redis Setnx 实现分布式锁,TTL 设为 30s - 原因:数据库唯一索引虽然也能做幂等,但会把“回调处理中”的状态暴露给查询方 - 待办:处理手工补单后台页面,功能接口已完成但前端未对接 - 注意:`process_notification()` 里调用了 `refund_overpaid()`,如果未来改退款逻辑,记得同步这里

这种以“人和 AI 协作”为视角写的日志,比 Git 提交信息要丰富得多。它记录了“为什么这么做”,而这恰恰是所有 AI 编码工具最欠缺也最需要的信息。

3.5 三文件的分工逻辑:拆得越开,维护成本越低

三个文件各司其职,整个记忆系统才不会退化。如果所有东西都堆到一个文档里,会出现什么情况?

每次会话开始都要读一个超长的文档,token 成本先不说,关键是 Claude Code 对文档重点的把握会漂移。可能它今天把你的代码风格规则记住了,明天却被你夹在文档中间的待办列表干扰了注意力。

分开之后,就能在每次开工之前按需加载:

  • AGENTS.md 每次会话都加载,因为全局规则是每个人任何时候都必须知道的。
  • PROJECT.md 每次会话都加载,因为项目当前状态是所有任务的基础。
  • LOG.md 不是每次都要全量加载,往往只需要读最近 20 到 30 行就能了解到最新的变更,历史部分只有在处理具体问题时才回去翻。

这个按需读取的特点正是三个文件方案最有价值的地方。存储(硬盘)是无限的,上下文(窗口)是有限的。把无限的信息放在可无限扩展的文件里,把有限的窗口用来加载最必要的那一部分,这就是外置大脑的本质。

4. 实战配置:目录怎么搭、文件怎么建、加载策略怎么设

方法论讲得再漂亮,最终还是要落地。这一步我直接给出具体做法,包括目录位置、初始化流程和 Claude Code 的加载配置。

4.1 目录结构:所有记忆文件集中在brain/文件夹

关于文件放哪里,我试过放在项目根目录,也试过放在docs/下面,最终采用的是在项目根目录创建独立brain/文件夹的做法。

好处有两个:

第一,一目了然brain/文件夹一看就知道是给 AI 用的记忆仓库,不同于面向人类阅读的docs/。团队成员看到也不会混淆。

第二,便于按需加载和备份。我可以把整个brain/看作一个整体,需要迁移项目时直接把这个文件夹拷走,三文件的结构不会散落各处。

结构如下:

your-project/ ├── brain/ │ ├── AGENTS.md # 员工手册:全局规则 │ ├── PROJECT.md # 项目档案:结构、模型、依赖 │ └── LOG.md # 变更日志:按时间倒序追加 ├── src/ ├── tests/ └── ...其他项目文件

每个文件开头我还要加一段约 500 字节的“自描述头”,告诉 Claude Code 这个文件是什么、什么时候该读、什么时候该更新。这听起来有点像给文件写说明书,但实测下来非常有效,它能让 Claude Code 在没有额外指令的情况下自己判断“该不该更新这个文件”。

比如AGENTS.md的开头:

# AGENTS.md > 本文件是项目的全局员工手册。你在开始任何任务前必须阅读本文件。 > 当你发现项目技术栈、代码风格、测试要求等全局规则发生变化时,必须更新本文件。 > 本文件不记录具体模块的细节,那些内容属于 PROJECT.md。

PROJECT.md的开头类似:

# PROJECT.md > 本文件是项目档案。每次任务开始前必须阅读本文件。 > 当新增、删除、重构了核心模块或领域模型时,必须同步更新本文件。 > 本文件记录“项目当前是什么状态”,不记录“做过的操作历史”,那些内容属于 LOG.md。

LOG.md的开头:

# LOG.md > 本文件是变更日志。每次与 AI 协作完成一批改动后,必须在本文件最上方追加一条记录。 > 记录内容包括:本次改了什么、为什么这样改、留下了哪些待办、有什么坑需要下次注意。 > 本文件按时间倒序排列,最新的记录在最上方。

加上这段“文件用途说明”,Claude Code 即使在上下文窗口已经滚动了很多轮之后,看到这个文件也能立刻明白它的角色。

4.2 初始化的 30 分钟:一次性写好种子内容

初始化这套外置大脑,我的建议是不要偷懒,第一次的种子内容尽量人工写,质量直接决定后面用起来顺不顺手。这 30 分钟花得非常值。

步骤大致如下:

  1. 先想清楚项目的技术栈和编码习惯。不要急着写,先把团队实际开发中最常被触犯的几条规则列出来。找一下你的历史代码,看看是否存在反复出现的风格偏差,那些就是最该写进 AGENTS.md 的红线。
  2. 把项目的目录结构和核心模型过一遍。这一步不需要写得非常详细,先搭骨架,后面每次遇到新增模块再补。
  3. 写一篇 LOG.md 的“第 0 条记录”。记录一下这个项目当前的起点状态,比如“完成了脚手架搭建,登录/注册功能可用,支付流程还未联调”。这就给 Claude Code 建立了“项目时间线”的起点。

种子的目的在于,让 Claude Code 第一次打开项目时就有东西可读,而不是面对一个空文件夹。

4.3 Claude Code 的加载配置:不用做太多额外的事

Claude Code 本身有自动读取约定文件的能力,如果你的文件名直接用AGENTS.md,放到项目根目录或brain/目录下,它一般能自己发现并加载。

但为了稳妥,我通常会明确告诉它在每个会话里先去读这三个文件。有两种做法:

方法一,在每次会话开头说一句:

Read brain/AGENTS.md, brain/PROJECT.md, brain/LOG.md first, and comply with all the rules in them.

方法二,利用 Claude Code 的预置指令功能,把这句话写进全局配置里,这样每次启动新会话时,它会自动执行这个“预读动作”。具体配置方式不展开,不同版本的入口可能略有差异,但核心思路是在全局指令里加入类似“开工前先读 brain 目录下三个文件”的句子。

这里我想强调一个技巧:让 Claude Code 自己“上报”它读了什么、准备怎么做,比让它“默默读”效果更好。比如你可以要求它:

After reading the brain files, list the top 5 constraints you are going to follow in this session, based on those files.

这会促使它真的去读,而不是假装读了。而且,它列出的约束方便你在会话开头快速校验它有没有理解偏差。如果它列的东西和你的关键项目事实有出入,你可以马上纠正,而不是等到它写了一段不符合预期的代码之后才发现问题。

5. 三个文件在手,具体工作流怎么跑起来

机制搭好了,接下来是这件事情最迷人的部分——状态机的设计。

我把一次“人机协作开发”分成四个阶段:预读、执行、沉淀、收尾。这四个阶段在每个会话中循环,外置大脑就是整个循环里的“常量存储”。

5.1 预读阶段:让 Claude Code 带着“记忆”进入工作状态

每次新开一个会话,我不会直接甩给它一个任务,而是先用一段 Prompt 让它完成“预读”动作。这段 Prompt 我现在的写法已经基本固定:

你是一个经验丰富的开发者,现在要进入项目工作。开始之前,请先完成以下步骤: 1. 阅读 brain/AGENTS.md,总结本项目最核心的 5 条全局规则,并复述一遍。 2. 阅读 brain/PROJECT.md,说明当前项目的架构和核心领域模型,特别指出你这轮任务可能涉及的部分。 3. 阅读 brain/LOG.md 的最新 3 条记录,简要概括最近发生了什么。 4. 基于以上信息,列出你本次会话打算如何执行我给你的任务。 现在,我给你的任务是:[具体的任务描述]

这一套步骤下来,不夸张地说,Collude Code 的回答质量会有一个肉眼可见的提升。它脑子里在回答你任务之前,先灌入了一套项目语境:我是谁、我在哪、周围发生了什么。就像你叫一个同事干活,他会问“这个项目现在处在什么阶段?”“有什么我需要注意的吗?”,这种背景信息直接影响他干活的质量。

5.2 执行阶段:边界声明与“禁止修改”清单

执行阶段的核心是利用外置大脑来划边界

在任务描述中,可以要求 Claude Code 在动手之前先检查它的改动范围是否触碰了 AGENTS.md 和 PROJECT.md 中定义的“不可变区域”。比如,我的一些项目里会有很多自动生成的代码,Claude Code 经常会在重构时把生成文件也改了,然后用看似合理的方式告诉你“顺手优化了一下”。这是我最不能忍的行为。

所以我在 AGENTS.md 里专门加了这么一段:

## 修改边界 - `src/generated/` 下的所有文件均由代码生成器产出,禁止手动修改。 - 如需变更生成逻辑,请修改 `scripts/generate.py` 后重新生成。 - 对上述文件的任何非生成操作都会被视作严重错误。

有了这种硬性声明,Claude Code 在越界时会更容易“刹车”。当然它不是每次都能 100% 遵守,但至少违反的概率从“经常”降到了“偶发”。

另一个有用的小技巧是:在执行完一段时间后,主动让它报告“本次改动了哪些文件”,你只需要把这份报告和实际 git diff 对照一眼,就能把风险扼杀在摇篮里。

5.3 沉淀阶段:一次成功的对话,必须转化为可复用的资产

这是整套方案里最关键的一步,也是大多数教程不会强调的一步:每次会话结束,强制 Claude Code 更新 LOG.md。

我每次让 Claude Code 完成一批改动之后,会追加这样一段要求:

现在,请将这次会话的完整结果更新到 brain/LOG.md 中。记录以下内容: - 本次改动涉及的功能/模块 - 做出的关键设计决策以及原因 - 遗留的 TODO 或已知问题 - 下次会话需要特别注意的点 格式参考已有历史记录。

这段要求看起来简单,但坚持做下来价值非常大。只要 LOG.md 更新及时,哪怕你隔了一个月再回到一个项目,让 Claude Code 读一遍 LOG.md,它就相当于和“一个月前的自己”无缝接上了。它清楚记得上次做到哪儿、有什么坑、下一步怎么走。

我把这个过程形容为:每次会话都在“落地成文”,而不是聊完即焚。工作不是从聊天记录里传承的,而是从 LOG.md 里传承的。

5.4 收尾阶段:用“三查”确认这次协作没有留下暗坑

我是个比较谨慎的人,每次和 Claude Code 协作完,在结束会话之前我习惯做三个检查:

  • 查运行:跑一遍测试和静态检查。这是最基本的,相当于面试时的笔试环节。
  • 查边界:对照 AGENTS.md 里的修改边界,确认没有动到不该动的区域。我一般用git status看一遍变更文件列表,看到有不该出现的文件就立即处理。
  • 查沉淀:确认 LOG.md 已经更新,关键决策有没有遗漏,待办事项清不清楚。

如果这三个检查都通过了,我才会踏实结束这次会话,不管是关掉终端还是切换去干别的。这套流程内化之后,成了一种肌肉记忆,也让我对 Claude Code 的信任度提升了好几个档次。

6. 实测记录:一个小项目从“野生生长”到“按图施工”

光说不练假把式。上周末我拿一个之前练手用的项目做了一次完整测试,记录一下实测中的前后差异,供大家参考。

6.1 测试项目背景

项目是一个简单的个人博客后端,FastAPI + SQLite + JWT 认证,大概两千行代码,七八个业务模块。之前是我手动写的,一直没敢拿给 Claude Code 折腾,就是担心它把已有功能弄坏。

这次测试的任务是:新增文章标签功能,允许一篇文章挂多个标签,并支持按标签筛选文章列表。

6.2 没有外置大脑之前的表现

先回顾一下没配外置大脑时,这类任务的表现(这也可以说是大部分人现有的体验):

第一,它会自己决定 Article 和 Tag 的关系表怎么建。它可能会创建一个article_tags表,也可能直接在articles表里加一个tag_ids字段存逗号分隔的 ID。这两种方案它都可能出,完全取决于它在当前窗口里“灵光一现”时的想法。

第二,它的命名不统一。比如已有的接口路径是/api/v1/posts/{id},但历史项目里根本没有这个路径,而是/api/articles/{id}。它会按照新上下文重新发明一套接口路径,和现有路由风格割裂。

第三,它不会自动补测试。如果我不明确要求,它基本不会主动写测试文件,因为它不知道这个项目的质量红线。

这三点叠加,导致用 Claude Code 维护一个“野生项目”时,每次改动都像在玩地雷阵。

6.3 有了外置大脑之后的表现

这次我提前把三个文件写好放在了brain/目录。AGENTS.md 里面写了 API 路由格式需要用复数名词、所有新增功能必须补测试、ORM 模型必须放在src/model/下。PROJECT.md 里写清楚了现有的文章模型字段、接口列表、认证方式。LOG.md 里记录了上次会话停在哪里,以及之前定下的技术选型。

同一句话:“新增文章标签功能,允许一篇文章挂多个标签,并支持按标签筛选文章列表。” 它这次的表现完全不一样:

  • 它主动说:根据项目管理规范,新建 Tag 模型并放在src/model/tag.py,同时创建article_tag关联表,放在同一个文件里。
  • 它在 API 层新增了/api/v1/articles/{article_id}/tags,/api/v1/tags/{tag_id}/articles这两个路由,完全贴合已有路由风格。
  • 它在领域模型中加了Article.tags关系字段,格式和已有Category关系字段保持一致。
  • 它自动为这次新增功能写了三个 pytest 测试文件,分别测试标签创建、文章挂标签、按标签筛选文章。
  • 整个过程中,它没有动任何一个已有模型字段,没有改接口返回值结构。

做完任务后,我让它自己总结变更并追加到 LOG.md,它的记录措辞合理,大型决策备注清晰:

## 2025.06.23 - 新增文章标签功能 - 背景:博客系统需要支持一篇文章多个标签,并支持按标签筛选 - 改动:新增 Tag 模型及 article_tag 关联表;新增标签相关的 3 个 API - 决策:使用关联表方案而非 JSON 字段,理由:标签需要独立维护和统计 - 待办:标签热度统计接口尚未实现,计划下个迭代完成 - 注意:Article.tags 关系加载使用了 lazy="selectin",避免后续查询 N+1

这次的输出质量已经接近一个熟练工程师写出的水准了。当然这不是因为 Claude Code 变聪明了,而是因为它在动手之前看到了“这个项目是怎么运转的”

6.4 实验结果小结

行为维度无外置大脑有外置大脑
表结构设计不确定,随上下文飘移稳定,参照已有模型
API 风格经常自创对齐已有路由约定
测试覆盖率基本不写自动补齐
改动边界可能误伤已有代码基本不越界
结果可追溯性事后难复原决策原因LOG.md 有完整记录

数据不说谎,一次实测试下来,无须多言。

7. 进阶玩法:外置大脑的扩展与微调

基础三件套稳定后,还可以继续加料。这部分属于锦上添花,但如果你经常用 Claude Code,也值得尝试。

7.1 增加“决策记录库”,专记已经拍板过的方案

团队里常有一种文件叫 ADR(Architecture Decision Records),记录每个技术决策的背景、选择和代价。类似的思路也可以应用到外置大脑中。

我有时候会额外加一个brain/DECISIONS.md,专门记那些“已经和 Claude Code 讨论过并最终拍板”的决策。

比如之前有一次,我纠结某个模块是用状态机实现还是手动 if-else。当时和 Claude Code 聊了很多轮,最终决定用状态机。如果这个结论不记录下来,下次遇到类似模块,它可能又会推荐 if-else,白白浪费一轮讨论。DECISIONS.md 就是为了避免这种重复决策。

模板可以是这样:

# 决策记录 ## 2025.06.20 - 订单状态流转用状态机 - 背景:订单模块状态逻辑较复杂,涉及取消、退款、超时 - 备选方案:A. 手动 if-else;B. 使用 transitions 库的状态机 - 决策:方案 B,使用 `transitions` 库 - 原因:状态转移路径清晰、扩展新状态成本低、避免隐藏分支 - 代价:引入一个第三方库依赖,需要额外维护状态图描述

7.2 给 Claude Code 定制“任务前检查清单”

另一个有效的扩展是:在 AGENTS.md 里面加一个“任务前检查清单”,让 Claude Code 在每次执行任务前都默认走一遍。典型清单如下:

## 任务前检查清单 在开始具体编码之前,你要确认以下几项: 1. 我已经阅读了 brain/ 下所有相关文件 2. 我了解本次改动影响到的模块和接口 3. 我检查了 PROJECT.md 中的领域模型,确认新改动的字段/方法不会与现有结构冲突 4. 我了解项目的测试要求,并会在完成后补上对应测试 5. 若有修改公共接口或数据库结构,我会在完成后更新 PROJECT.md

有了这个清单,即使是新手用户第一次用 Claude Code,也不会在项目里乱打乱撞。

7.3 接入自动化流程:让更新外置大脑成为提交前的一环

我目前还没有做到完全自动化,但我见过一个很合理的做法:用 git pre-commit 钩子检查AGENTS.mdPROJECT.md是否有未提交的改动,若有改动,则提示用户“是否确认这些记忆文件已更新”。这能在协作层面堵住“脑子里改了但没记到文件里”的漏洞。

如果项目已经接了 CI,还可以加一步文档一致性检查,比如用脚本对比代码里新增的模块和 PROJECT.md 中的模块列表,不一致就报警告。这些属于工程化做法,视项目复杂度取舍即可。

8. 最后碎碎念:为什么这套方案能治“失忆”却不麻烦

可能有人会担心:三个文件听起来不错,但维护成本是不是太高了?每次都要更新这些文件,不烦吗?

我的真实感受是:在一开始的一两天会比较烦,但过了“建立初始档案”的阵痛期,后面几乎是无感的。理由有两个。

第一,大部分更新是让 Claude Code 自己干的。它改完代码后,你只需要说一句“把本次变更记进 LOG.md”,剩下的活它会自己完成。你检查一下措辞和关键信息就好,基本不用从头开始写。

第二,这套机制解决的不只是 Claude Code 的记忆问题,它其实在逼你把项目的隐性知识显性化。过去很多信息只存在于你自己的脑子里,比如“为什么支付回调要加事务”“为什么这个接口返回结构不能乱改”,这些逻辑在人员流动、项目交接时全部面临丢失风险。现在它们都成了文件里的白纸黑字。即使某天你自己忘了,翻一翻这些档案也能重新找到上下文。

再说回同事那句“不怕它把项目搞炸”。怕,但怕没用,得解决问题。项目搞炸往往不是因为 Claude Code 能力不够,而是因为你没有给它一个可靠的项目认知框架。当我把它从一个“靠会话记忆干活的新人”变成“每次开工前先查员工手册和老同事留下的工作日志”的成熟协作伙伴之后,它的输出稳定性和可靠性提升非常明显。

这套方案不依赖任何特定模型,也不绑定特定工具,Markdown 文件是所有文本工具都能读懂的通用格式。哪怕未来某天我换了工具,这些记忆资产依然能原封不动地迁移到新的 AI 开发环境里去。从这个角度讲,这三份文件可能才是项目里最保值的那部分资产。

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

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

立即咨询