乐于分享
好东西不私藏

让多个AI读懂你的框架,并和代码库协同进化 2

让多个AI读懂你的框架,并和代码库协同进化 2

当团队同时使用多个 AI 编程工具时,如何避免每个工具各写各的,都绕开你精心设计的框架?本文记录了一套从零演进到工程化的解决方案。上一篇,我们通过Skill让Claude实现代码库和AI实现协同进化,这一篇我们进一步讨论,把Claude扩展到多个AI工具。


一、问题背景:框架存在,AI 视而不见

1.1 自研框架的价值与代价

在一个成熟的工程团队里,自研框架是领域知识的结晶。它把反复出现的模式封装成宏,把约定俗成的分层结构固化成接口,让开发者不必每次从零思考。

以本文的案例为例——一个基于 DDD(领域驱动设计)思想的 Rust 框架,已经封装了以下核心模式:

// 聚合根,不需要手动 impl 生命周期管理#[aggregate_root]pubstructOrder { ... }// 值对象,自动派生相等性和不变性保证#[value_object]pubstructMoney { ... }// HTTP handler,自动注册路由、处理序列化#[auto_router]asyncfncreate_order(ctx: Context) -> Result<Response> { ... }// 仓储层,自动生成 CRUD 模板#[repository]pubstructOrderRepository { ... }

每一个宏背后,都是数周的设计与打磨。它们不只是语法糖,更是团队对"正确写法"的共识载体。

1.2 AI 编程助手的引入

当 Claude Code、OpenAI Codex 等 AI 编程工具进入开发流程,效率的确提升了——但随即暴露出一个根本性的问题:

AI 不认识你的框架。

它写出的代码语法正确,编译通过,逻辑合理,但全是原生 Rust 写法。聚合根用手动 impl,值对象不用宏,HTTP handler 直接用 axum 的原始 API。框架形同虚设。

更糟糕的是,团队同时在用 Claude Code 和 Codex——两个工具,各自为政,写出来的代码风格完全不同,既不符合框架规范,彼此之间也缺乏一致性。

1.3 问题的精确定义

在深入分析之前,先精确定义问题的边界。

这不是 AI 能力的问题。Claude 和 Codex 都有足够的能力理解和使用自定义宏,前提是它们能看到足够的上下文。

这是一个知识传递问题,具体表现在三个维度:

  • 时效性:每次对话,AI 都从零开始,没有项目记忆
  • 准确性:告知不足则写错,告知过多则被噪音淹没
  • 一致性:多工具协作时,规范如何保持同一

二、初步尝试:直觉方案的局限

2.1 全量注入的失败

最直觉的方案是把框架文档全部注入给 AI。

这条路走不通,且失败得很有规律。一个完整的框架文档动辄数万字——所有宏的签名、所有工具函数的说明、所有使用禁忌,全塞进去。上下文窗口迅速饱和,AI 的注意力被大量无关信息稀释。更糟的是,当开发者只是在写一个路由 handler,他不需要知道数据库迁移宏的用法,但 AI 已经被这些信息占据了宝贵的推理空间。

全量注入的本质问题:把字典当作工作手册来用。

2.2 按需查询的前提假设

意识到全量注入的问题后,下一个想法是引入 MCP(Model Context Protocol)Server,让 AI 按需查询宏文档。

这个思路方向正确,但隐藏着一个致命的前提假设:AI 必须提前知道宏的名字,才能发起查询。

一个 AI 从未见过 #[aggregate_root],它不会主动去问"这个项目里有没有聚合根宏"。它只会沿用自己训练数据里见过的写法——手动 impl、自己造轮子、绕过框架。MCP 解决的是"如何高效获取知识",但没有解决"如何触发知识需求"。

2.3 单工具方案的天花板

即便为 Claude 单独设计了一套 skill 文档系统,放在 .claude/目录下,并取得了不错的效果,新的问题很快暴露:

当 Codex 也进入工作流,是否要为它再维护一套文档?

这个问题的答案几乎注定是痛苦的。两套文档意味着两倍的维护成本,以及随时间推移不可避免的内容漂移——Claude 文档更新了,Codex 文档忘了同步;框架宏重构了,某一套文档滞后了两个版本。

工具越多,维护负担越重,一致性越难保证。


三、问题的重新定义

经过以上尝试,我们需要退一步,重新定义问题的本质。

3.1 真正需要解决的是什么

将问题拆解之后,核心诉求其实很简单:

无论用什么 AI 工具,写具体代码之前,AI 都能找到并读取当前任务所对应的框架规范。

注意这里的关键词:找到对应。不是全部读完,不是随机读取,而是在正确的时机读到正确的那一份。

3.2 知识库 vs. 工具配置

由此引出一个重要的概念区分:

框架规范是项目级知识,不是工具级配置。

.claude/里的 skill 文档,从属性上讲,不应该是"Claude 的配置文件"。它是"这个项目的开发规范",恰好以 Claude 能读懂的格式写就。当 Codex 也需要这份知识时,本质上是在消费同一份规范——只是入口不同。

这个区分,是整个方案演进的关键转折点。


四、核心方案:项目级 AI 知识库

4.1 设计原则

基于以上认识,最终方案遵循三条原则:

原则一:单一事实来源(Single Source of Truth)框架规范只维护一份,任何 AI 工具都从同一个地方读取,不允许为不同工具维护平行文档。

原则二:工具无关的知识层规范存放在中立目录,不绑定任何具体 AI 工具。工具可以换,规范不需要随之迁移。

原则三:入口与内容分离各 AI 工具只需要维护自己的"入口"——告诉工具去哪里找规范,入口本身不包含规范内容。

4.2 目录结构

最终方案的文件结构如下:

project-root/├── CLAUDE.md                          # Claude 入口├── AGENTS.md                          # Codex 入口├── .ai/                               # 唯一共享知识库│   ├── routing.md                     # 路由表(意图→文档映射)│   ├── domain.md                      # 领域层规范│   ├── repository.md                  # 仓储层规范│   ├── web.md                         # Web 层规范│   ├── transaction.md                 # 事务规范│   ├── error.md                       # 错误处理规范│   ├── migration.md                   # 迁移规范│   ├── config.md                      # 配置规范│   ├── utils.md                       # 工具函数规范│   └── testing.md                     # 测试规范├── .claude/│   ├── settings.json                  # Claude 运行时配置│   └── hooks/│       └── update-skill.sh            # 框架变更时自动更新文档的 hook└── .codex/    └── skills/        └── my-rust-ddd/            └── SKILL.md               # Codex skill 入口

每个目录的职责边界非常清晰,不存在模糊地带。

4.3 各层详细设计

知识层:.ai/目录

.ai/是整个系统的核心,也是唯一需要深度维护的地方。

其中 routing.md是整个系统的枢纽,它维护一张意图关键词到领域文档的映射表:

# AI 路由表写 Rust 代码前,先根据任务意图在下表中找到对应文档并读取。| 任务意图 / 关键词                      | 读取文档              ||--------------------------------------|----------------------|| 聚合根、实体、值对象、领域事件          | .ai/domain.md        || Repository、仓储、数据库查询、持久化   | .ai/repository.md    || HTTP handler、路由、接口、Controller  | .ai/web.md           || 事务、Transaction、跨聚合操作          | .ai/transaction.md   || Error、错误处理、Result、异常          | .ai/error.md         || 测试、Test、mock、断言                 | .ai/testing.md       || 数据库迁移、schema 变更                | .ai/migration.md     |规则:1. 一个任务可能匹配多个意图,对应文档都要读2. 不确定时,先读 domain.md3. 不允许凭记忆写框架代码

路由表本身只有约 1-2KB,是整个系统中唯一需要"常驻上下文"的内容,其余文档均按需加载。

各领域文档遵循统一格式:

# [Domain] 规范## 适用场景(明确描述何时需要读这份文档)## 核心宏速查### `#[macro_name]`**作用**:一句话说清楚**签名**:完整函数/宏签名**示例**:来自项目真实代码的可运行示例## ✅ 正确写法(DO)(来自项目 examples/ 或 tests/ 的真实代码)## ❌ 禁止写法(DON'T)(框架希望替代的原生写法,明确列出)## 完整示例(覆盖该领域 80% 场景的完整可运行代码)

DO/DON'T 并列的设计是关键。只有正确示例,AI 在"看起来也行"的原生写法和框架写法之间会摇摆。明确的禁止模式才能斩断这条退路。

Claude 入口:CLAUDE.md

CLAUDE.md是 Claude Code 每次对话必然加载的文件,但它不再承载规范内容——它只负责两件事:项目背景说明,以及指向 .ai/routing.md的强制跳转。

# 项目说明这是一个自研 DDD Rust 框架项目。框架通过宏封装了大量领域模式。## ⚠️ 写 Rust 代码前的强制步骤1. 读 `.ai/routing.md`2. 根据当前任务匹配对应领域文档3. 读完对应文档后再写代码不允许绕过框架宏使用原生写法。

整个文件不超过 20 行。轻量是刻意为之:CLAUDE.md 必然被加载,因此它越小,对上下文的"占用税"越低。

Codex 入口:AGENTS.md与 Codex Skill

Codex 有两个入口,各有分工。

AGENTS.md是项目级的 Codex 配置文件,类比 CLAUDE.md,承担同等职责:

# Project: [项目名]## 框架说明这是一个自研 DDD Rust 框架。所有领域模型、仓储、Web handler 都有对应的框架宏。## 写 Rust 代码前必须执行1. 读 `.ai/routing.md`2. 按任务意图加载对应领域文档3. 严格遵守 DO/DON'T 规范

.codex/skills/my-rust-ddd/SKILL.md是更精细的触发器,负责在 Codex 识别到 Rust 相关任务时自动激活:

# my-rust-ddd Skill## 触发条件涉及以下任意内容时激活:创建或修改 Rust 源文件定义领域模型、仓储、Web 接口、测试## 激活后必须执行1. 读 `.ai/routing.md`2. 根据任务加载对应 .ai/*.md3. 按规范写代码,不允许绕过框架宏

两个入口互为补充:AGENTS.md 是项目级的全局约束,SKILL.md 是任务级的精确触发。

运维层:Claude Hooks

.claude/目录保留,但职责收窄为运行时配置和自动化钩子,不再存放规范内容。

其中最重要的是 update-skill.sh,通过 Claude 的 PostToolUse Hook 在框架源文件被修改后自动触发:

#!/bin/bash# 检测被修改的文件路径MODIFIED_FILE="$1"# 判断是否属于框架核心目录ifecho"$MODIFIED_FILE" | grep -qE "core-(common|errors)-macro/"then# 通过 additionalContext 注入更新指令echo"检测到框架宏变更:$MODIFIED_FILE"echo"请立即检查并更新 .ai/ 下对应的文档,确保示例代码与当前宏签名一致。"fi

这个 Hook 解决了文档腐烂问题——框架变更和文档更新之间的延迟,从"等开发者记起来"缩短到"当次提交内自动完成"。


五、系统演进路径

理解了最终结构之后,回顾整个演进路径有助于理解每一个设计决策的动机。

阶段一:无结构AI 完全依赖训练数据,原生写法,框架形同虚设阶段二:全量注入把所有文档塞进系统提示,上下文爆满,噪音过大阶段三:Claude 专属 skill(.claude/*.md)按需加载,效果改善;但绑定单一工具,无法扩展阶段四:共享知识库(.ai/)+ 多工具入口工具无关,单一事实来源,支持 Claude / Codex / 未来工具

每一次演进都是在解决上一阶段暴露的新矛盾。关键的认知跃迁发生在阶段三到阶段四:从"给工具配置文档"变成"为项目建立知识库"。


六、可扩展性分析

这套方案的设计中,可扩展性是一等公民。

6.1 接入新 AI 工具

当 Cursor、Windsurf、Aider 或任何新工具进入工作流,所需的工作量极小:

  1. 了解该工具的"项目入口文件"规范(类似 CLAUDE.md 或 AGENTS.md)
  2. 创建该入口文件,内容只写:去读 .ai/routing.md
  3. 如果该工具支持 skill/rule,创建对应的轻量触发器

.ai/中的规范内容完全不需要改动。

6.2 框架规范演进

框架宏新增、重构或废弃时,只需要更新 .ai/下对应的文档。所有 AI 工具在下次任务中自然读到最新版本。Claude 的 Hook 机制进一步将这个更新动作从"手动记得做"变成"框架变更时自动提醒"。

6.3 团队协作

这套文档放在项目仓库中,随代码一起版本管理。每个团队成员、每次 CI 流水线、每个 AI 工具读到的都是同一份规范。新成员加入时,.ai/目录同时是他们了解框架的学习材料。


七、设计决策对照表

以下表格记录了方案中的关键决策及其背后的工程动机:

决策
原因
规范放在 .ai/而非 .claude/
目录名决定心智模型;中立名称强制团队意识到这是项目资产,不是工具配置
入口文件只写"去哪读",不复制规范
消灭内容重复,从根本上防止不一致;入口文件可以有多份,规范只有一份
路由表常驻,领域文档按需
路由表是索引,必须始终可见;领域文档是内容,只在相关任务时加载
DO/DON'T 并列而非只写 DO
AI 会在"可行"的写法中选择最熟悉的;禁止模式明确切断原生写法的退路
示例来自项目真实代码
框架宏的语义只有在真实业务上下文中才完整;通用示例会产生幻觉
Hook 用独立 .sh脚本
JSON 内联命令有转义噩梦;脚本可单独测试、可复用、可演进
CLAUDE.md 保持极短
该文件必然加载,每字节都是税;职责单一则体积可控

八、结论

回顾整个方案的演进,核心洞察可以浓缩为一句话:

框架规范是项目的一等公民,不是 AI 工具的二等配置。

当我们把文档从 .claude/迁移到 .ai/,变化的不只是目录名,而是整个心智模型——从"给 Claude 配置 skill"变成"为项目建立 AI 知识库"。后者天然支持多工具,天然要求单一来源,天然被纳入版本管理。

具体来说,这套方案实现了以下目标:

零重复维护:规范只在 .ai/里写一次,所有工具读同一份。

工具无关:接入新 AI 工具的成本是一个入口文件,而不是一套新文档。

自动更新:框架变更通过 Hook 触发文档更新提醒,文档腐烂的速度大幅降低。

符合工程直觉:AI 规范像代码规范一样存在于仓库中,被版本管理,被 code review,被所有人共享。

最终目标从未是让 AI 记住所有规则——那不现实,也不必要。真正的目标是:让 AI 每次写代码之前,都能找到正确的规则。这套系统正是为此而设计的。


本文方案基于 Claude Code 的 CLAUDE.md 机制、Hook 系统与 OpenAI Codex 的 AGENTS.md 及 skill 机制实现。核心思路(单一事实来源 + 工具无关知识层 + 轻量入口)对所有支持自定义上下文的 AI 编程工具均适用。 未完待续!

上一篇内容:让 AI 真正读懂你的框架:一套三层强制机制的设计与实践