大型代码库策略:monorepo 与跨仓协调的现实边界
- 理解为什么大型代码库会让 AI 的效果大幅下降,以及背后的根本原因
- 掌握"只喂相关模块"的分治策略,让 AI 在大库里保持高质量输出
- 学会在 monorepo 里把 AI 的注意力锁定到单个包,避免跨包乱改
- 判断哪类决策必须人来拍板,AI 不该越俎代庖
AI 在小项目里如鱼得水,你让它加个功能、写个测试、重构一段逻辑,几乎手到擒来。但同样的用法换到几十万行的大库,或者一个有二三十个包的 monorepo,效果会急剧下滑——回答开始泛泛,修改开始乱打,有时候改了一个文件,另外几个地方莫名其妙也动了。
这不是 AI 能力不够,是你用它的方式没跟上库的规模。
为什么大库会让 AI 吃力
根本原因只有一个:上下文窗口是有限的。
你跟 AI 的每一次对话都有一个"窗口",它能同时看到的内容是有上限的。小项目文件少,它能把关键代码全装进去,理解完整,给出的答案自然准确。大库不行——光是把所有文件列一遍就能把窗口撑满,真正的代码还没读。
具体来说:
读不完。一个成熟的前后端 monorepo,代码量动辄几十万行、几千个文件。就算你用 /tools/claude-code/ 这类工具让 AI 自己探索文件系统,它也只能"抽样",不可能全局理解。它看到的始终是冰山一角。
上下文塞不下。就算你手动把相关代码贴给它,大库里的一个功能往往牵涉多个层:API 层、业务逻辑层、数据层、类型定义、测试。把这些全贴进去,很快就触顶。触顶之后,早期内容开始被"遗忘",输出质量下滑。关于如何管理上下文不漂移,可以参考 上下文工程:管住 token 防漂移。
改动波及广。大库里的代码耦合度通常比小项目高——一个公共 util 函数可能被一百个地方调用,改一个接口签名要同步修改散落在各处的调用方。AI 在没有全局视野的情况下做这类改动,很容易改了源头,却漏掉下游。
怎么帮 AI 聚焦:分治喂法
解法不是找一个"更强的 AI",而是改变你给 AI 的工作方式。核心思路:不让 AI 试图理解整个库,而是每次只给它处理一个小切片。
策略一:只喂相关模块
在开始一个任务前,先自己搞清楚这个任务的边界在哪——涉及哪些文件、哪些函数、哪些接口。然后只把这些内容喂给 AI,不要一股脑把整个目录扔给它。
实际操作:
# 不要这样——把整个 src 丢给它
claude "帮我重构 src/ 目录下的用户模块"
# 这样更好——圈定范围
claude "帮我重构 src/modules/user/ 下的这三个文件:
- user.service.ts(核心逻辑)
- user.repository.ts(数据访问)
- user.types.ts(类型定义)
目标:把 findById 和 findByEmail 的逻辑合并,减少重复查询"
任务越具体,AI 的输出越靠谱。"帮我优化用户模块"这种话它不知道从哪下手;"把这两个函数合并,保留原有的错误处理逻辑"它能做得很好。
策略二:用索引文件当导航
大库通常有索引文件(index.ts、barrel.ts、ARCHITECTURE.md、CODEOWNERS 等),这些文件用很少的篇幅描述了整体结构。把这类文件优先喂给 AI,让它建立一个"地图",再深入具体文件。
# 先让它读架构文档,再讨论具体修改
claude "先读 docs/ARCHITECTURE.md 和 src/modules/index.ts,
然后告诉我如果要加一个 notification 模块,应该放在哪里、
需要实现哪些接口"
策略三:分而治之,不要一次性任务
把一个大需求拆成几个独立的小任务,每个任务单独跑一次对话,每次只做一件事。比如:
- 第一次:只改接口定义(
user.types.ts) - 第二次:根据新接口改实现(
user.service.ts) - 第三次:更新测试(
user.service.test.ts) - 第四次:更新调用方(用 grep 找到所有调用点,一个一个过)
每次结束后 commit,下一次带着已有的改动继续。这样每步的上下文都是干净的,不会因为累积了太多内容而漂移。
Monorepo 里的策略:让 AI 只关注一个包
Monorepo 的特殊挑战在于:所有包共享一个 git 仓库,但每个包逻辑上是独立的。AI 启动时会扫描整个仓库,很容易"越界"——你让它改 packages/ui 里的组件,它跑去动了 packages/core 里的类型定义。
在正确的目录启动
最简单的隔离方式:把工作目录切到具体的包目录,而不是 monorepo 根目录。
# 在 monorepo 根目录启动——AI 会看到所有包
cd ~/projects/my-monorepo
claude
# 切到具体包目录启动——AI 的视野被限制在这个包
cd ~/projects/my-monorepo/packages/ui
claude
在包目录启动后,它读到的文件、解析到的 package.json、引用的依赖都是这个包的,跨包乱改的概率大幅降低。
用 CLAUDE.md 标注边界
在每个包目录下放一个 CLAUDE.md,告诉 AI 这个包的职责范围、不能动哪些东西、依赖关系是什么:
# packages/ui — CLAUDE.md
这是纯 UI 组件库,只包含展示型组件。
**不要改以下内容:**
- packages/core 里的任何文件(它有独立维护者)
- 根目录的 tsconfig.base.json(跨包共享配置)
**这个包的依赖:**
- 只依赖 packages/tokens(设计 token)
- 不依赖任何业务逻辑包
AI 会读取当前目录和父目录的 CLAUDE.md,这些说明会进入它的上下文,约束它的行为。
用 git worktree 隔离并发任务
如果你同时要处理两个包的改动,用 git worktree 给每个包开一个独立工作区,避免相互干扰。这个在 git worktree 让多 Agent 并行不打架 里有详细讲。
跨仓改动怎么协调
比 monorepo 更麻烦的是真正的多仓场景:一个接口定义在 api-repo,消费方在 frontend-repo 和 mobile-repo,改一次要同步三个仓库。AI 在这里能帮上忙,但有个前提:你得给它一个清晰的协调顺序。
原则:先在一个仓验证,再推广
不要同时让 AI 在三个仓库里做修改。正确做法:
- 先改 api-repo,在这里把接口变更跑通(包括单测、类型检查、文档)。
- 验证无误后,把新接口的定义(通常是类型文件或 OpenAPI 文档)导出,作为其他仓库的"合同"。
- 分别切到 frontend-repo 和 mobile-repo,每次只处理一个,把合同导入、按新接口改调用方。
这样做的好处是:每个仓库的修改都有一个已经验证的"参照物",AI 改调用方时有具体的类型定义可以对照,不是在猜。
用文档做跨仓桥梁
让 AI 在完成第一个仓库的修改后,生成一份"迁移指南":
> 把这次接口变更写成一份迁移文档,说明:
> 1. 旧接口签名 vs 新接口签名
> 2. 调用方需要改什么
> 3. 需要注意的 breaking change
这份文档喂给处理下一个仓库的会话,效果远比"你去看 api-repo 的改动"好,因为它是紧凑的、直接可用的上下文。关于如何拆解多仓库并行任务,可以参考 子代理自动拆火并行隔离。
什么时候得人来定架构
有些决策不能让 AI 做,或者说,你不应该把这类决策外包给它:
包的拆分和边界划定。"这个功能应该放在 packages/core 还是新建一个 packages/feature-x"——这个问题牵涉到整个团队的代码组织哲学、未来的发展方向、现有的所有权划分。AI 能给出几个选项,但拍板必须是真正了解全局的人来做。
跨多个仓库的 breaking change 时序。"先改哪个仓库、旧版本接口兼容多久"——这不只是技术问题,是工程协调和发布节奏的问题,AI 没有业务上下文。
性能瓶颈的根因定位。当性能问题出现在大库的某个深处,可能是 N+1 查询、可能是不合理的模块依赖导致的打包体积、可能是服务间的级联调用。AI 能分析你给它看的那部分,但全链路的根因判断,通常需要人结合监控数据和对系统架构的整体理解。
安全相关的架构决策。权限模型怎么设计、敏感数据的流向、依赖的第三方库是否可信——这些不能"问 AI 怎么说"就算审核。
简单说:AI 是你的执行者,不是决策者。把"如何实现"交给它,把"做什么"留给自己。
大库里用 AI 的分治策略清单
把以下这些当成检查表,每次在大库里开始一个 AI 辅助任务前过一遍:
任务定义阶段
- 已经确认这个任务的文件边界(涉及哪些文件,不超过 10-15 个)
- 已经把大任务拆成多个独立的小步骤,每步有明确的完成标准
- 清楚这次改动的"合同"——调用方和实现方的接口是什么
上下文准备阶段
- 只把相关文件的内容准备好,不把整个目录扔给 AI
- 如果有架构文档或 CLAUDE.md,优先喂进去建立地图
- 上一步的改动已经 commit,新会话从干净状态开始
执行阶段
- 在正确的目录(包目录而不是 monorepo 根目录)启动 AI
- 每个小步骤结束后验证(跑测试、类型检查),不攒着最后一起验
- AI 改完后用
git diff确认改动范围,没有意外的跨包修改
跨仓场景额外检查
- 已确定改动顺序,从"被依赖方"开始,向"依赖方"推进
- 第一个仓库改完并通过验证后,再开始下一个
- 跨仓变更有文档化的"迁移指南",不靠口头传达
常见问题
Q:AI 理解了整个大库的架构,是不是就没这些问题了?
短期内不会。当前的 AI 工具受限于上下文窗口,真正的全库理解需要持续的索引和检索机制,现有工具在这方面还在进化中。更务实的态度是:不要等 AI 变得足够强,先把分治策略用起来,今天就能提高效率。
Q:monorepo 里每个包都建一个 CLAUDE.md 太麻烦了,有没有更省力的方式?
可以只在根目录和最频繁修改的几个核心包里建。CLAUDE.md 的作用是边际递减的——核心包写得详细,边缘包简单描述一下职责也够用。不需要追求全覆盖,先建最容易出问题的那几个。
Q:我让 AI 帮我重构,它改了很多文件,我怎么确认没有漏改的地方?
两步:一是 git diff --stat 看改了哪些文件;二是运行全量类型检查(tsc --noEmit)和测试。类型错误往往会暴露漏改的调用方。不要只相信 AI 说的"改完了",让工具链帮你做最终确认。
Q:大库里的新功能开发,AI 能帮上忙吗,还是只适合改已有代码?
新功能开发完全可以,但要用"先定接口,再写实现"的方式。先让 AI 帮你设计新功能的接口(类型定义、API 签名),你和团队对着接口评审通过后,再让它填实现。这样边界清晰,不会一上来就陷入实现细节。
Q:用了这些策略之后,AI 对大库的帮助还剩多少?
会比小项目低,但仍然有实质价值。大库里 AI 最擅长的事:在圈定范围内的代码生成、测试补全、重构执行(按你给的方向改)、解释某一段代码的逻辑。最不擅长的:全局重构、跨多个系统的设计决策、没有明确边界的"优化"任务。用在擅长的地方,避开不擅长的,整体仍然值得用。
👉 看看我们的 AI 编程实战体系课,或逛 AI 编程教程大全 把基本功打扎实。