---
title: 'Cookbook解读｜大型代码库里，先别让 Agent 读完整个仓库'
description: '带读 Claude Code 的大型代码库指南：从一个找错登录链路的任务出发，理解目录规则、受限读取、代码智能与跨包计划如何让 Agent 看见恰好够用的代码。'
pubDate: 2026-08-06
updatedDate: 2026-08-10
slug: large-codebase-context-scope
tags: [agent, ClaudeCode, context-engineering, Cookbook解读]
lang: zh-CN
draft: false
---

让 Agent 修复登录失败，它却先读了 `dist/`、十年前的 `legacy/`，又翻到了另一个团队的前端约定。等它真的找到 `AuthService`，上下文里已经塞满了和这次故障无关的东西。

这不是模型“不够聪明”的一个好例子。更像是让一个刚入职的同事拿着整层楼的门禁卡查线上问题：门都能进，反而不知道应该先敲哪一扇。

这篇文章带读的原始材料不是 OpenAI Cookbook，而是 Anthropic 的 [Claude Code《Set up Claude Code in a monorepo or large codebase》](https://code.claude.com/docs/en/large-codebases)。它被放进本博客的「Cookbook 解读」系列，是因为它同样提供了一套可以照着落地的工程做法。

先说结论：**大仓库里最有用的不是“把更多代码塞进 Agent”，而是让任务决定它从哪里开始、哪些规则随身带着、哪些文件根本不该打开；当任务真的跨出边界时，再显式扩大范围并把关键决定写下来。**

> **数据快照**
>
> - 最后核验：2026-08-10
> - 原始材料：[Claude Code：Set up Claude Code in a monorepo or large codebase](https://code.claude.com/docs/en/large-codebases)
> - 文章边界：本文解释该指南公开的配置与工作流，不比较模型能力、上下文窗口大小或不同产品的质量与成本。

## 原文先解决什么问题：不是仓库太大，而是注意力被用错了

假设一个电商 monorepo 有订单、支付、优惠券和后台管理四个包。登录出错只发生在 API，可 Agent 一上来从根目录扫完整个仓库。它当然可能最终找到答案，但每一次无关读取都会让真正的证据变得更难辨认。

**原文引用｜指南对大仓库问题的定义**

> unrelated to the task, costing tokens and degrading Claude’s performance.

原文说明的是：随着代码库长大，为小项目设计的默认行为会让无关指令和文件读取填满上下文，从而增加 token 成本、降低表现。[这段原文](https://code.claude.com/docs/en/large-codebases)能证明官方把“任务无关的读取”当作问题；它不能证明某一种配置会自动理解业务，也没有给出不同设置的质量排名。

所以这份指南的核心不是一条“让 Agent 先探索”的抽象口号，而是把探索拆成几道能实际配置的边界。它们可以叠加，也不要求每个仓库一次性全上。

**原文引用｜各项设置之间的关系**

> They layer rather than replace each other.

这句话解释了为什么不能只加一份巨型 `CLAUDE.md` 就宣布完成 Context Engineering。启动目录、目录规则、读取权限、语言服务、worktree 和 Skill 分别管不同的事情；它们是工具箱，不是一道必答题。[原文的设置总览](https://code.claude.com/docs/en/large-codebases#settings-on-this-page)列出了每个工具试图解决的具体问题。

## 第一层：先决定从哪扇门进，而不是从大厅喊“我来了”

在大型仓库里，`claude` 从哪里启动，决定了默认能访问哪些文件、启动时会带上哪些 `CLAUDE.md`，以及哪一份项目设置生效。[原文的启动位置对照](https://code.claude.com/docs/en/large-codebases#choose-where-to-start-claude)给出了两个很不一样的入口：

- 从仓库根目录启动，适合要同时改多个 package 的任务；
- 从 `packages/api/` 启动，适合只影响 API 的任务，默认视野先收在这个子树中。

这不是“目录越深越好”。如果登录改动还要更新 `packages/shared/` 的 Session 类型，把 Agent 困在 `packages/api/` 只会让它在发现依赖后再次申请访问。正确的判断是：**先按已知影响面给一个默认范围，新的证据出现后再扩大。**

### 原文的做法：把规则放在代码附近

**原文方案引用｜官方示例中的分层目录结构（节选）**

```text
monorepo/
  CLAUDE.md
  packages/
    api/
      CLAUDE.md
      .claude/skills/
    web/
      CLAUDE.md
```

上面的结构来自[官方示例 monorepo](https://code.claude.com/docs/en/large-codebases#the-example-monorepo)。根目录保存全局布局、提交约定等通用信息；`api/` 目录保存 API 的测试、迁移和框架约束；读取更深目录时，再按需加载那里自己的说明。

把它想成医院的导诊：大厅只告诉你楼层和总规则；真的走到放射科，才需要知道那里的预约流程。把所有科室的细节印进同一张大厅海报，只会让病人和导诊护士一起看花眼。

**本文解读**：`CLAUDE.md` 更像“这一片代码的使用说明”，不该是百科全书。根目录放所有人、所有任务都需要的约定；某个 package 的测试命令和禁忌，就留给这个 package 的 owner 维护。原文也提醒，短期只想专注一个目录时，优先从该目录启动，而不是频繁修改 `claudeMdExcludes` 这类长期排除策略。

## 第二层：挡住不该读的文件，再让工具找到该读的符号

规则只解决“该带什么说明”；Agent 真正消耗上下文的大头，通常还是文件内容。

### 生成物不是证据，除非任务正是在查生成物

`node_modules/`、构建产物、提交进仓库的 vendor SDK，常常会在搜索结果中显得很热闹，却很少能解释业务故障。官方指南区分了两种情况：已在 `.gitignore` 中的常见目录通常不会进入内容搜索；对已提交的生成代码或 vendor 依赖，则可以用 `permissions.deny` 的 `Read` 规则阻止打开。[原文关于受限读取的说明](https://code.claude.com/docs/en/large-codebases#block-reads-of-generated-and-vendored-code)还特别限定：这类规则并不会过滤递归搜索的输出，也不能管住任意子进程。

**原文方案引用｜阻止读取构建产物与 vendor 代码（节选）**

```json
{
  "permissions": {
    "deny": ["Read(./**/dist/**)", "Read(./vendor/**)"]
  }
}
```

这段配置来自[官方的 `permissions.deny` 示例](https://code.claude.com/docs/en/large-codebases#block-reads-of-generated-and-vendored-code)。它证明的是“打开文件时可以设定边界”，不代表这些目录永远无用；排查打包产物或第三方补丁时，反而可能需要临时把它们放回视野。

### 不要让 `grep` 承担语言服务的工作

现在回到“登录失败”。如果问题是“`Session` 类型在哪定义、谁在调用它”，全仓搜索关键词会得到一大堆同名命中。官方建议接入 code intelligence plugin，让语言服务器回答定义、引用和类型错误，把文件扫描换成符号级定位。[原文对 code intelligence 的说明](https://code.claude.com/docs/en/large-codebases#reduce-file-reads-with-code-intelligence)把它和排除规则放在同一节，原因很直白：前者移走噪声，后者在剩下的代码里更快找路。

不过，LSP 不是业务分析师。它能画出 `RefundCreated` 的调用关系，却不能告诉你退款后是否必须返还优惠券、优惠券是否有冻结期、幂等键放在哪。这些仍然要靠领域文档、测试和任务的验收条件。**缩小检索范围，不等于省掉业务判断。**

## 第三层：跨包时扩大世界，但别丢掉已经做出的决定

设想登录问题最后被定位到共享类型：`packages/api/` 需要修改接口，`packages/shared/` 需要改类型，`packages/web/` 还要改一个调用点。这时“只看 API”已经不成立。

**图 1：本文解读｜登录任务的范围如何随着证据扩大；图中示例是分析性场景，不是官方实测流程**

```mermaid
flowchart LR
  S([开始：收到登录失败任务]) --> A[从 API 目录启动]
  A --> B[加载根目录与 API 规则]
  B --> C[跳过生成物与 vendor]
  C --> D[用语言服务定位 Session 引用]
  D --> E{发现 shared 类型？}
  E -- 否 --> F[修改 API 并运行对应测试]
  E -- 是 --> G[显式纳入 shared 与调用点]
  G --> H[写下变更计划与验证项]
  H --> I[同一任务中完成一致改动]
  F --> Z([结束：交付可验证改动])
  I --> Z
```

图里最重要的转折在 `shared`：它不是“越界失败”，而是要扩大范围的证据。官方指南给出两类工具：`additionalDirectories` 或 `--add-dir` 处理当前 session 对兄弟 package/其他仓库的访问；`worktree.sparsePaths` 让 worktree 只检出任务需要的目录。[原文的跨目录访问说明](https://code.claude.com/docs/en/large-codebases#grant-access-across-packages-or-repositories)与[稀疏 worktree 说明](https://code.claude.com/docs/en/large-codebases#check-out-only-the-directories-you-need)分别覆盖这两层边界。

**原文引用｜跨 package 变更的一条建议**

> Save the plan to a file before editing.

原文建议在编辑前把计划写入仓库，因为较长 session 可能压缩上下文，而文件中的计划能留下已确认的决定。[原文的跨包 scope 与 plan 建议](https://code.claude.com/docs/en/large-codebases#scope-and-plan-changes-that-span-packages)能证明“计划文件可跨压缩保留”；它不代表每一个两行改动都必须新建一份计划。

这一点也解释了多 Agent 的边界。只读探索适合独立出去：把大量目录遍历、搜索命中留在子任务中，主任务只拿回文件位置、证据和未解项。但“要不要改共享类型”“哪个回归测试算完成”必须由同一个变更保持一致；把这些决定拆成几段互不相通的对话，才是真的让 Agent 迷路。

## 把原文的工具箱换成一次可执行的判断

下面这张表不是官方的质量对比，而是基于上述指南整理的选择入口。

**表 1：本文解读｜按任务信号选择范围控制工具；结论基于 2026-08-10 核验的官方指南，不是性能测量**

| 看到的信号                              | 先做什么                                                      | 不要误解成                              |
| --------------------------------------- | ------------------------------------------------------------- | --------------------------------------- |
| 任务只改一个 package                    | 从该子目录启动，加载根目录与本地规则                          | 永远不能读兄弟 package                  |
| 根规则越来越长、越来越像项目百科        | 将局部测试/框架规则放入目录级 `CLAUDE.md` 或 path-scoped rule | 每个目录都必须复制一份总规则            |
| 搜索不断命中构建产物、生成代码或 vendor | 用 `.gitignore` 与 `Read` deny 缩小读取面                     | 从此不可能调试这些目录                  |
| 问题是“定义或调用者在哪里”              | 用 code intelligence 查符号                                   | LSP 已经理解业务语义                    |
| 任务涉及共享类型和多个调用点            | 显式增加目录，先记录计划再改                                  | 把每个 package 交给互不共享决定的 Agent |

如果团队反复在同一目录做同类操作，原文还建议把局部流程做成按需加载的 Skill；如果分散的 `CLAUDE.md` 已经难以治理，再考虑由平台团队维护 plugin 或 MCP。[目录级 Skill](https://code.claude.com/docs/en/large-codebases#add-per-directory-skills)和[集中治理建议](https://code.claude.com/docs/en/large-codebases#centralize-conventions-when-layering-stops-scaling)回答的是“规则如何长期维护”，不是一次登录故障的即时修复方案。

## 总结：先把问题缩到可解释，再把范围扩大到足够完成

大型代码库并不要求 Agent 永远待在一个小盒子里。更好的策略是：起步时只带与任务有关的规则和文件；用符号工具减少盲目翻找；当共享类型、调用点或测试给出新证据时，再把世界扩大一圈，并把已经做出的决定写进计划。

下次让 Agent 改一项跨包功能时，可以先问四个问题：任务最初影响哪个目录？哪些说明必须加载？哪些文件只会制造噪声？一旦发现跨包依赖，哪些决定必须和计划一起保留？

能回答这四个问题，Agent 就不必先读完整个仓库，才有机会把真正需要读的那部分读明白。

## 参考资料

- [Claude Code：Set up Claude Code in a monorepo or large codebase](https://code.claude.com/docs/en/large-codebases)，2026-08-10 核验
