在 monorepo 和大型代码库里配置
用分层 CLAUDE.md、claudeMdExcludes、Read 拒绝规则、代码智能、稀疏 worktree、additionalDirectories、分目录 Skill 和集中化约定,让 Claude 在大型代码库里只聚焦相关代码。
大型代码库可以是一个有数百万行的仓库,也可以是有许多包的 monorepo。Claude Code 在任何规模下都能工作,但随着代码库增长,为较小项目调优的默认值会让上下文窗口塞满与任务无关的指令和文件读取,既耗 token,又拖累 Claude 的表现。
本指南面向个人开发者和工程团队,说明如何把 Claude 限定在任务涉及的那部分代码库。每一节都会注明某个设置是你机器上的个人设置,还是提交到仓库的设置。
本指南涵盖什么
本页的设置
下面每个设置都是独立的,它们是叠加而不是替换的关系,所以按你的仓库适用的来用。「选择从哪里启动 Claude」决定你的设置文件放在哪,所以请先读它;「整合起来」展示它们的组合。
| 我想要 | 使用 |
|---|---|
| 只加载你所接触代码的约定,而不是一个覆盖所有子系统的根文件 | 分目录的 CLAUDE.md 文件 |
| 排除你从不涉足的包的 CLAUDE.md 文件 | claudeMdExcludes |
| 阻止 Claude 打开构建产物、生成代码和第三方依赖 | permissions.deny 里的 Read 拒绝规则 |
| 通过语言服务器而不是扫描文件来查找符号的定义或调用方 | 代码智能插件 |
| Claude 创建 worktree 时只检出任务需要的目录 | worktree.sparsePaths |
| 在同一会话里读写兄弟包或另一个仓库 | --add-dir 或 additionalDirectories |
| 给 Claude 某个区域专属、仅在相关时才加载的流程 | 分目录的 skills |
| 用大家都安装的一套约定取代许多分目录的 CLAUDE.md | 内部市场里的插件 |
提示:任何仓库里保持上下文精简的工作流技巧(例如把探索放在子智能体里运行,让文件读取不进主对话)见最佳实践页;要给组织里每个开发者推行一套基线配置,见「为你的组织设置 Claude Code」。
示例 monorepo
本页的例子都指向一个有三个包的 monorepo。同样的模式也适用于大型单树代码库:例子里用 packages/api/ 的地方,换成你自己的子系统目录,如 src/backend/ 或 lib/core/。
monorepo/
CLAUDE.md # 根指令
packages/
api/
CLAUDE.md # API 专属指令
.claude/skills/
src/
web/
CLAUDE.md # 前端专属指令
.claude/skills/
src/
shared/
CLAUDE.md # 共享库指令
src/选择从哪里启动 Claude
你在哪里启动 claude 决定:Claude 无需额外权限授予就能读写哪些文件、启动时有哪些 CLAUDE.md 文件加载进上下文,以及哪些项目设置适用。
| 从哪里启动 | 文件访问 | 启动时加载的 CLAUDE.md | 何时使用 |
|---|---|---|---|
| 仓库根目录 | 每个文件 | 只加载根文件;子目录的文件在 Claude 读取那里时按需加载 | 任务跨越多个包或子系统 |
| 某个子目录 | 仅该子树,直到你授予更多 | 该目录的加上每个祖先目录的 | 工作限定在一个包或子系统 |
.claude/settings.json 里的项目设置不像 CLAUDE.md 文件那样从父目录继承。会话读取哪个目录的 .claude/settings.json,见设置页的「Claude Code 到哪里找每个文件」。下面每一节都会说明它的设置文件属于仓库根目录还是你启动所在的子目录,以及是提交的还是留在本地的。
按目录分层 CLAUDE.md 文件
在大型代码库里,仓库根目录的单个 CLAUDE.md 往往要么膨胀到覆盖每个子系统的约定(为与当前任务无关的指令消耗上下文),要么太通用而没用。把指令拆到各个目录的文件里,意味着 Claude 加载仓库范围的规则,再加上你正在处理的那部分代码的约定。
Claude Code 在启动时加载你工作目录和每个父目录里的所有 CLAUDE.md 文件,然后在读取子目录里的文件时按需加载该子目录的文件。根文件设定仓库范围的规则,每个子目录再添加自己的。常见的拆分是两层:
- 根
CLAUDE.md:适用于所有地方的指令,如编码规范和提交约定。 - 每个子目录的
CLAUDE.md:特定于该区域技术栈的约定。在 monorepo 里每个包一个;在大型单树里每个子系统(如src/db/或src/api/)一个。
把这些文件提交到仓库,让队友继承。每个目录的所有者通常维护自己的文件。要精简已检入的文件,运行 /doctor 检查。根 CLAUDE.md 存放适用于每个包的规则:
Run package scripts from the package directory, not the monorepo root.
Prefix commit subjects with the package name, for example `api: add rate limiting`.
Never edit files under packages/*/generated/. Run `npm run codegen` in the package instead.每个子目录的 CLAUDE.md(这里是 packages/api/CLAUDE.md)添加该区域专属的约定:
Copy `.env.example` to `.env` before running anything. Tests and the dev server fail without it.
Write database queries with the Knex query builder. Never put raw SQL strings in route handlers.
Never edit a migration after it has merged. Add a new migration instead.当你从 packages/api/ 启动 Claude 时,它会同时加载 packages/api/CLAUDE.md 和根 CLAUDE.md:Claude 看到本地指令和仓库范围的规则,上下文里没有来自 packages/web/ 的指令。非 monorepo 树里的任何子目录同理。要确认加载了哪些文件,运行 /context 并查看 Memory files 下的列表。
随着代码库和模型变化,保持这些文件最新的几个办法:
- 在拉取请求里评审:像对待其他文档改动一样对待 CLAUDE.md 的编辑,让约定跟上代码。
- 在重大模型发布之后重新审视:为绕过较旧模型的局限而写的指令,在较新的模型自己能处理该情况后可能变成负担;例如强制单文件重构的规则,在局限消失后就可以删掉。
- 添加提出更新建议的 Stop hook:
Stophook 在 Claude 完成响应时收到会话转录的路径,所以脚本可以审查会话,并在它暴露的缺口还新鲜时提出 CLAUDE.md 更新建议。
CLAUDE.md 文件如何加载和相互作用,见「记忆与项目指令」。
在分目录 CLAUDE.md 与路径范围规则之间选择
分目录的 CLAUDE.md 文件和 .claude/rules/ 下的路径范围规则都能让你把指令对准树的某一部分,区别在于文件放在哪、何时加载。
| 做法 | 文件位置 | 何时加载 | 何时使用 |
|---|---|---|---|
分目录的 CLAUDE.md | 在目录里,与它的代码放在一起 | 从该目录启动时在启动加载,或 Claude 读取那里的文件时按需加载 | 目录所有者维护自己的约定;指令与代码一起版本化 |
.claude/rules/ 里的路径范围规则 | 仓库根目录的集中 .claude/ | Claude 处理匹配规则 paths: glob 的文件时 | 你想把所有约定放在一处,或同一条规则适用于许多分散的路径 |
包括 skills 在内的对比见功能概览的「比较相似功能」。
排除无关的 CLAUDE.md 文件
当你从仓库根目录启动 Claude 时,一旦 Claude 读取某个子目录里的文件,该子目录的 CLAUDE.md 就会加载。claudeMdExcludes 设置按路径或 glob 模式跳过特定文件,使它们永远不加载。用它处理你从不涉足的目录,例如其他团队的包、遗留代码或第三方子树。排除列表是静态的,不是按任务切换的开关;要今天聚焦一个包、明天聚焦另一个,改为从那个包的目录启动 Claude,而不是编辑排除项。
如果你只想为自己设置这些排除,把设置放在 .claude/settings.local.json 里。Claude Code 在往那里保存设置时会把该文件加入你的全局 gitignore;这里你是手工创建它,所以要自己把它加进 gitignore。模式使用与绝对文件路径匹配的 glob 语法,所以相对风格的模式要以 **/ 开头,才能匹配树中任何位置。下面的例子排除另一个团队拥有的包:
{
"claudeMdExcludes": [
"**/packages/web/**"
]
}这会跳过该包下的每个 CLAUDE.md 和规则文件;根 CLAUDE.md 和你确实工作的包照常加载。这些模式涵盖其他常见情形:
"**/packages/*/CLAUDE.md":排除每个包的 CLAUDE.md 而保留根的"**/packages/legacy-*/**":排除名称匹配该 glob 的每个包,包括规则"/home/user/monorepo/legacy/CLAUDE.md":按绝对路径排除某个特定文件
托管策略的 CLAUDE.md 文件不能被排除,所以组织范围的指令总是适用。你可以在任何设置作用域设置 claudeMdExcludes:用户、项目、本地或托管;数组会跨作用域合并,所以团队可以设项目级默认值,个人再添加本地覆盖。完整的排除文档见记忆页的「排除特定 CLAUDE.md 文件」。
减少 Claude 读取的内容
指令只是进入 Claude 上下文的一部分,文件读取是另一项随代码库增长的成本。下面的设置阻止对无关路径的读取,并用语言服务器查询取代穷举式的文件扫描。
阻止读取生成代码和第三方代码
Claude 的内容搜索默认遵守 .gitignore,所以已经列在那里的路径(如 node_modules/、dist/ 和 build/)无需额外配置就不会出现在搜索结果里。对已检入的路径(如第三方 SDK 或已提交的生成代码),在 permissions.deny 里添加 Read 拒绝规则,阻止 Claude 打开这些文件。
拒绝规则可以覆盖在仓库里工作的所有人、只覆盖你,或覆盖这台机器上的每个会话,取决于你把它们放进哪个设置文件:
- 在仓库里工作的所有人:把规则提交到
.claude/settings.json:如果你从根目录启动 Claude,就在仓库根目录;如果从子目录启动,就在每个包自己的.claude/里。与本页的其他项目设置一样,该文件不从父目录继承。 - 只有你自己:使用仓库根目录的
.claude/settings.local.json,它在仓库内的每个 CLI 会话里加载,不论启动目录是什么(Claude Code 不使用仓库根目录的情形除外,如在 Windows 上)。像例子里的Read(./**/vendor/**/*)这样的相对模式仍然锚定在会话的当前工作目录而不是仓库根目录,所以如果你从子目录启动会话,在这个文件里要把规则写成//开头的绝对路径,如Read(//absolute/path/to/repo/**/vendor/**/*)(v2.1.211 之前,.claude/settings.local.json也只从启动目录加载)。 - 所有人,在每个会话里强制执行:在托管设置里设置规则,用户和项目设置无法覆盖它。
下面的例子阻止构建产物和一个第三方 SDK。它的目录模式以 /**/* 而不是 /** 结尾,这样每条规则覆盖目录内的一切但不覆盖目录本身,Claude 仍然可以列出这些目录或切换进去,例如 ls dist 或 cd build。
{
"permissions": {
"deny": [
"Read(./**/dist/**/*)",
"Read(./**/build/**/*)",
"Read(./**/*.generated.*)",
"Read(./**/vendor/**/*)"
]
}
}拒绝规则覆盖 Claude 内置的文件工具。在 Bash 里,当被拒绝的路径作为参数出现时,它们覆盖 Claude Code 认得的文件命令(如 cat、head、grep 和 find),以及 < file 这类重定向的目标。Claude Code 还会尽力把被拒绝的路径排除在内置 Grep 和 Glob 工具的结果之外;对包含被拒绝文件的目录做 grep -r 或 find 这样的 Bash 搜索,输出里仍然包括它们。拒绝规则不覆盖自己打开文件的子进程。完整的模式语法见权限页的 Read 和 Edit 规则。
用代码智能减少文件读取
在大型代码库里,找一个符号在哪定义或在哪使用,可能要花许多次文件读取和 grep 调用。代码智能插件把 Claude 连接到语言服务器,使它能直接跳转到定义、查找引用并呈现类型错误,而不是扫描整棵树。官方市场里有 TypeScript、Python、Go、Rust 和其他常见语言的插件。在 Claude Code 会话里运行下面的命令安装 TypeScript 插件:
/plugin install typescript-lsp@claude-plugins-official如果安装失败,按 Claude Code 报告的消息处理:Marketplace "claude-plugins-official" not found 时,先用 /plugin marketplace add anthropics/claude-plugins-official 添加市场再重试;插件在市场里找不到时,检查插件名称。要为仓库里的所有人启用某个插件,而不是自己安装,把它加进 enabledPlugins 项目设置。
代码智能插件要求每个开发者机器上有该语言服务器的二进制文件(每种语言需要哪个二进制见代码智能页)。从官方市场安装需要能访问托管该市场的 GitHub;在受限网络上,改为从内部 Git 主机或本地路径添加市场。这与上面的 claudeMdExcludes 和 Read 拒绝规则配合得很好:它们把无关内容挡在上下文之外,而代码智能让 Claude 不必通读剩下的内容来定位定义。
限定 worktree 和文件访问
这些设置控制 worktree 里磁盘上有什么,以及 Claude 在你的启动点之外能读写哪些目录。
只检出你需要的目录
--worktree 标志在新的 git worktree 里启动会话,使改动与你的主检出隔离。默认情况下它检出整个仓库。在大型仓库里,worktree.sparsePaths 设置用 git sparse-checkout 只把列出的目录加上根目录文件写到磁盘,所以 worktree 启动更快、占用空间更少。
如果在这个目录里工作的所有人需要相同的路径,把设置提交到 .claude/settings.json;要为自己添加路径,用 .claude/settings.local.json:列表跨作用域合并,所以本地文件可以给已提交的列表添加路径但不能移除。本页的 JSON 例子一次只展示一个设置;如果你的 .claude/settings.json 已经包含其他键(如上面的 permissions.deny 规则),把 worktree 键加到它们旁边,而不是替换整个文件。「整合起来」展示合并结果。下面是已提交的文件:
{
"worktree": {
"sparsePaths": [
".claude",
"packages/api",
"packages/shared"
]
}
}Claude 创建 worktree 时,只检出 .claude/、packages/api/ 和 packages/shared/,而不是完整的树。sparsePaths 里的路径相对仓库根目录,不论你从哪个子目录启动 Claude;这里任何目录路径都行,不只是包的根目录。这对子智能体的 worktree 隔离特别有用:子智能体是为子任务派生的并行 Claude 实例,每个在 worktree 里运行的子智能体得到轻量检出而不是完整的树。一个会话里所有 worktree 共享同一个 sparsePaths,所以如果一个子智能体需要 packages/api/ 而另一个需要 packages/web/,两个都要列出。
在 sparsePaths 里列出目录,而不是单个文件。package.json、tsconfig.base.json 和锁文件这样的根目录文件总是与你列出的目录一起被检出;根目录下的目录则不是,所以如果你想在 worktree 里用仓库根的 .claude/settings.json 或 .claude/rules/,要把 .claude 包含在列表里。项目的 skills、智能体和命令见 worktree 页的「worktree 与主检出共享什么」。
sparse checkout 要求 git 在存在 sparse worktree 期间,在仓库共享的 .git/config 里启用 extensions.worktreeConfig。Claude Code 在最后一个 worktree 被移除后删除该条目,但只有该条目是 Claude Code 添加的才删;它从不删除你自己设置的值。(v2.1.207 之前,该条目在最后一个 worktree 移除后仍然保留,基于 go-git 的工具如 tea 在你运行 git config --unset extensions.worktreeConfig 之前无法打开仓库。)
为避免在 worktree 之间重复 node_modules 这样的大目录,在同一个 .claude/settings.json 里把 sparsePaths 与 symlinkDirectories 配对:
{
"worktree": {
"sparsePaths": [
".claude",
"packages/api",
"packages/shared"
],
"symlinkDirectories": [
"node_modules"
]
}
}这会从每个 worktree 的 node_modules/ 创建一个指回主仓库副本的符号链接,而不是在磁盘上重复一份。
注意:sparsePaths 和 symlinkDirectories 设置是在创建 worktree 之前从你的启动目录读取的。创建之后,会话的工作目录是 worktree 根目录,而不是你启动所在的子目录;因此 worktree 里的项目设置从 worktree 根的 .claude/settings.json(即仓库根文件的检出副本)加载。你在 worktree 里需要的其他任何设置(如权限规则或 hooks),要放进仓库根的 .claude/settings.json。完整的 worktree 设置参考见设置参考页的 Worktree 部分。
跨包或仓库授予访问
本节适用于你从子目录启动 Claude,或任务跨越多个检出的情形。如果你在单个大型树里从仓库根目录启动,Claude 已经能访问每个文件,可以跳过这一节。
当你从 packages/api/ 启动 Claude 时,它能读写该目录内的文件。如果任务需要跨包改动(例如更新 api 和 web 都导入的共享类型),你需要授予对兄弟目录的访问;同样的机制也能授予对单独检出的另一个仓库的访问。.claude/settings.json 里的 additionalDirectories 设置让 Claude 访问工作目录之外的目录。下面的例子授予对两个兄弟包的访问:
{
"permissions": {
"additionalDirectories": [
"../shared",
"../web"
]
}
}相对路径相对你启动 Claude 的目录解析。用这个配置,Claude 从 packages/api/ 工作时能读取和编辑 packages/shared/ 和 packages/web/ 里的文件。你也可以不编辑设置,在运行时通过启动 Claude 时传 --add-dir 授予访问:
claude --add-dir ../shared不论你怎么添加目录,Claude 都能读取和编辑其中的文件;该目录的 CLAUDE.md、.claude/rules/ 文件和 skills 是否也加载,取决于你如何添加它:
| 添加方式 | 加载 CLAUDE.md 和规则 | 加载 skills |
|---|---|---|
additionalDirectories 设置 | 从不 | 从不 |
--add-dir 标志或 /add-dir 命令 | 只有设了下面的环境变量才加载 | 是 |
要从用 --add-dir 或 /add-dir 添加的目录加载 CLAUDE.md 和规则文件,设置 CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD 环境变量:
CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1 claude --add-dir ../shared该环境变量对列在 additionalDirectories 设置里的目录无效;详情见记忆页的「从额外目录加载」。对这个区域里每个人都需要的兄弟目录,把 additionalDirectories 提交到 .claude/settings.json;对个人选择或一次性访问,用 .claude/settings.local.json 或在启动时传 --add-dir。
添加分目录的 skills
任何子目录都可以定义限定在自己技术栈的 skills。skill 在 Claude 判断相关时按需加载,所以做前端工作时,API 专属的工具不会占用上下文。skills 放在目录内的 .claude/skills/ 下;与该区域的代码一起提交,让任何克隆仓库的人都能得到它们。在 monorepo 里这可以是每个包一套 skills;在大型单树代码库里是每个子系统一套,如 src/db/.claude/skills/。
在子目录里创建 skill 目录:
mkdir -p packages/api/.claude/skills/api-testing然后在该目录里写 SKILL.md,这里是 packages/api/.claude/skills/api-testing/SKILL.md。这个例子教 Claude API 包的测试模式:
---
name: api-testing
description: Testing patterns for the API package. Use when writing or modifying tests in packages/api/.
---
## Test structure
Tests are in `src/__tests__/` mirroring the `src/` directory structure.
Each route file has a corresponding `.test.ts` file.
## Running tests
- All tests: `npm test`
- Single file: `npm test -- src/__tests__/routes/users.test.ts`
- Watch mode: `npm test -- --watch`
## Test utilities
- `src/__tests__/helpers/db.ts`: provides `setupTestDb()` and `teardownTestDb()` for database tests
- `src/__tests__/helpers/auth.ts`: provides `createTestUser()` and `getAuthToken()` for authenticated endpoints
## Patterns
- Use `supertest` for HTTP assertions, not raw fetch
- Always wrap database tests in a transaction that rolls back
- Mock external services in `src/__tests__/mocks/`另一个子目录以同样方式容纳不同的 skills:packages/web/.claude/skills/component-patterns/ 描述的是前端的组件约定而不是测试。Claude 处理 packages/api/ 里的文件时,加载 api-testing skill;处理 packages/web/ 时,加载 component-patterns;任何一个目录的 skills 都不会在另一个目录的任务期间加载。
你也可以按文件模式而不是按放置位置来限定 skill 的范围:paths frontmatter 字段接受 glob 模式,Claude 只在处理匹配文件时自动加载该 skill。用它处理放在仓库根目录 .claude/skills/ 里、但只适用于无论出现在哪里的某些文件的 skill,例如限定在 **/migrations/** 的数据库迁移 skill。创建和组织 skills 的更多内容见 Skills 页。
保持 skills 可被发现
skills 分散在许多目录里时,Claude 可选的列表可能变得很大。Claude 通过阅读每个被发现 skill 的名称和描述来选择 skill,只有被选中的那个 skill 的完整内容才会加载进上下文。本节讲如何让这个列表保持精简。
哪些 skills 在范围内取决于你从哪里启动 Claude:
- 从
packages/api/这样的子目录:来自该目录、每个直到仓库根的父目录,以及用户和企业级别的 skills。 - 从仓库根目录:根 skills,加上 Claude 在会话期间接触的每个子目录里的 skills,这可能累积到数百个。
- 用
--add-dir添加兄弟目录之后:该兄弟目录的 skills 也加载;additionalDirectories设置只授予文件访问而不加载 skills。
名称总是加载,但当 skills 很多时,有些 skill 会完全丢掉描述,这可能去掉 Claude 用来判断某个 skill 是否适用的关键词。保持描述简短,并以请求会包含的词开头,如「writing or modifying tests in packages/api/」。对许多目录共享的 skills(如 PR 约定或部署清单),把它们放在仓库根目录的 .claude/skills/,这样从任何启动目录都能加载。当共享的 skills 需要自己的版本历史或必须跨仓库工作时,改为把它们打包成插件:插件 skills 使用 plugin-name:skill-name 命名空间,所以永远不会与分目录 skills 冲突,平台团队可以在一处对它们进行版本化和更新。
要找出哪些 skills 没被使用,启用 OpenTelemetry 日志导出器并设置 OTEL_LOG_TOOL_DETAILS=1,使 skill 名称被逐字记录而不是被脱敏。skill_activated 事件在它的 skill.name 属性里记录每次调用,invocation_trigger 记录是命令、Claude 还是嵌套 skill 调用了它,这能告诉你该合并或淘汰什么。
当分层不再可扩展时集中化约定
随着代码库增长,分目录的 CLAUDE.md 文件可能变得难以治理:约定漂移、文件过时、没人拥有根文件。解决这个问题通常落在维护仓库 Claude Code 配置的团队身上,而不是每个在自己区域工作的开发者。
把约定和参考内容从始终加载的 CLAUDE.md 里挪到按需加载的机制里:
- Skills:Claude 只在与任务相关时才加载的参考资料。
- 插件:由平台团队集中拥有的、有版本的 skills、hooks 和命令包。
- MCP 服务器:如果你的组织已经在仓库上运行代码搜索或 RAG 索引,把它作为 MCP 工具暴露,让 Claude 查询它,而不是直接读取文件。
平台团队如何集中强制执行这些,见服务端托管设置与端点托管设置的选择说明。
在会话开始时推荐合适的插件
一旦约定放进了插件,在树中不熟悉部分启动 Claude 的队友没有任何信号表明该区域的所有者维护着哪个插件。SessionStart hook 可以弥补这个缺口:Claude Code 会把 hook 打印到 stdout 的纯文本在第一个提示之前加入 Claude 的上下文。例如,你可以写一个脚本,从 hook 输入读取启动目录,在提交到仓库的路径到插件映射里查找,并打印推荐,让 Claude 在它的第一条回复里转述。编写并注册 hook 见「用 hooks 自动化动作」。
整合起来
下面的组合配置使用 monorepo 布局;同样的文件适用于大型单树里的任何子目录。每个子目录的 .claude/settings.json 必须是自包含的,而不是叠加在根文件上。这个例子把 worktree、additionalDirectories 和 Read 拒绝规则提交在 .claude/settings.json 里,使 packages/api/ 里的每个开发者得到相同的兄弟访问、稀疏路径和排除。下面是 packages/api/ 已提交的、按区域的设置:
{
"worktree": {
"sparsePaths": [
".claude",
"packages/api",
"packages/shared"
],
"symlinkDirectories": [
"node_modules"
]
},
"permissions": {
"additionalDirectories": [
"../shared"
],
"deny": [
"Read(./**/dist/**/*)",
"Read(./**/build/**/*)"
]
}
}因为这个会话从 packages/api/ 启动,兄弟包的 CLAUDE.md 文件已经在范围之外,所以这里不需要 claudeMdExcludes;如果你也从根目录启动会话,把它加到仓库根的 .claude/settings.local.json 里。
additionalDirectories 条目在你直接从 packages/api/ 启动 Claude 时适用。在从这个会话创建的 worktree 内,工作目录是 worktree 根目录,所以这个设置文件不加载:兄弟包在 worktree 里无需它就已经可达,但拒绝规则需要在仓库根的 .claude/settings.json 里有第二份副本,worktree 会话才能拾取它们,如 worktree 设置说明所述:
{
"permissions": {
"deny": [
"Read(./**/dist/**/*)",
"Read(./**/build/**/*)"
]
}
}设置完成后,仓库有这样的布局:
monorepo/
CLAUDE.md
.claude/settings.json # worktree 会话的拒绝规则
packages/
api/
CLAUDE.md
.claude/settings.json # worktree、additionalDirectories、拒绝规则
.claude/skills/api-testing/SKILL.md
web/
CLAUDE.md
.claude/skills/component-patterns/SKILL.md
shared/
CLAUDE.md有了这套设置,从 packages/api/ 启动 Claude:
- 加载根 CLAUDE.md 和
packages/api/CLAUDE.md,跳过packages/web/CLAUDE.md - 能读写
packages/api/和packages/shared/里的文件 - 跳过
packages/api/里dist/和build/下构建产物的读取 - 按需提供 api-testing skill
- 创建包含
.claude/、packages/api/、packages/shared/和根目录文件的 worktree,拒绝规则通过根设置文件应用到整个 worktree
限定并规划跨包的改动
上面的配置控制 Claude 看到什么。当单个改动涉及多个包时(例如更新共享类型以及每个使用它的调用点),你如何限定和排序任务也会影响结果。有两个技巧有助于保持跨包改动的一致:
- 在一个会话里把整个改动交给 Claude:把共享的修改和它的调用点一起交出去,能让每次编辑背后的决策保持一致,而不是按包重新推导。
- 编辑之前先规划:在 plan 模式下先做计划,Claude 把计划写到文件里。长的跨包会话会在过程中压缩上下文;Claude Code 在每次压缩之后重新注入计划文件,所以计划能在对话历史可能丢失的地方留存。
下一步
这套配置就位后,你可以进一步完善:
- 用 hooks 在 Claude 编辑文件后运行分目录的 linter 或类型检查器。
- 阅读「有效管理成本」,了解代码库大小如何影响 token 用量,以及在更大范围推行之前如何设置支出限额。
- 阅读 Claude 博客上的《How Claude Code works in large codebases》,了解位于本页按仓库配置之上的组织推行模式和所有权模型。