1> ## Documentation Index
2> Fetch the complete documentation index at: https://code.claude.com/docs/llms.txt
3> Use this file to discover all available pages before exploring further.
4
5# Set up Claude Code in a monorepo or large codebase
6
7> Configure Claude Code for monorepos and large single-tree codebases with nested CLAUDE.md files, sparse worktrees, code intelligence, and per-package skills so Claude stays focused on the code you're working in.
8
9A large codebase can be one repository with millions of lines or a monorepo with many packages. Claude Code works at any size, but as the codebase grows, the defaults tuned for smaller projects can fill the context window with instructions and file reads unrelated to the task, costing tokens and degrading Claude's performance.
10
11This guide shows individual developers and engineering teams how to scope Claude to the part of the codebase a task touches. Each section notes whether a setting is personal to your machine or committed to the repository.
12
13## What this guide covers
14
15The [table below](#settings-on-this-page) lists each setting and what it accomplishes. The [file tree after it](#the-example-monorepo) is the example monorepo every code sample on this page refers to.
16
17### Settings on this page
18
19Each setting below is independent. They layer rather than replace each other, so apply whichever fit your repository. [Choose where to start Claude](#choose-where-to-start-claude) determines where your settings files live, so read it first. [Put it together](#put-it-together) shows all of them combined.
20
21| I want to | Use |
22| :-------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------- |
23| Load only the conventions for the code you touch, instead of one root file covering every subsystem | Per-directory [CLAUDE.md files](#layer-claude-md-files-by-directory) |
24| Exclude CLAUDE.md files for packages you never work in | [`claudeMdExcludes`](#exclude-irrelevant-claude-md-files) |
25| Block Claude from opening build output, generated code, and vendored dependencies | [`Read` deny rules](#block-reads-of-generated-and-vendored-code) in `permissions.deny` |
26| Find a symbol's definition or callers through the language server instead of scanning files | A [code intelligence plugin](#reduce-file-reads-with-code-intelligence) |
27| Check out only the directories a task needs when Claude creates a worktree | [`worktree.sparsePaths`](#check-out-only-the-directories-you-need) |
28| Read and edit a sibling package or another repository from the same session | [`--add-dir`](#grant-access-across-packages-or-repositories) or `additionalDirectories` |
29| Give Claude procedures specific to one area that load only when relevant | Per-directory [skills](#add-per-directory-skills) |
30| Replace many per-directory CLAUDE.md files with one set of conventions everyone installs | A [plugin](#centralize-conventions-when-layering-stops-scaling) in an internal marketplace |
31
32<Tip>
33 For workflow techniques that keep context small in any repository, such as [running exploration in a subagent](/en/best-practices#use-subagents-for-investigation) so file reads stay out of the main conversation, see [Best practices for Claude Code](/en/best-practices). To roll out a baseline configuration to every developer in your organization, see [Set up Claude Code for your organization](/en/admin-setup).
34</Tip>
35
36### The example monorepo
37
38The examples throughout this page refer to a monorepo with three packages. The same patterns work in a large single-tree codebase: where an example uses `packages/api/`, substitute your own subsystem directory such as `src/backend/` or `lib/core/`.
39
40```text theme={null}
41monorepo/
42 CLAUDE.md # root instructions
43 packages/
44 api/
45 CLAUDE.md # API-specific instructions
46 .claude/skills/
47 src/
48 web/
49 CLAUDE.md # frontend-specific instructions
50 .claude/skills/
51 src/
52 shared/
53 CLAUDE.md # shared library instructions
54 src/
55```
56
57## Choose where to start Claude
58
59Where you launch `claude` determines which files Claude can read and edit without an additional permission grant, which CLAUDE.md files load into context at startup, and which project settings apply.
60
61| Start from | File access | CLAUDE.md loaded at launch | Use when |
62| :-------------- | :-------------------------------------- | :------------------------------------------------------------------- | :----------------------------------------- |
63| Repository root | Every file | Root only; subdirectory files load on demand when Claude reads there | Tasks span multiple packages or subsystems |
64| A subdirectory | That subtree only, until you grant more | That directory's plus every ancestor's | Work is scoped to one package or subsystem |
65
66Project settings in `.claude/settings.json` load only from your starting directory and are not inherited from parent directories the way CLAUDE.md files are: a `.claude/settings.json` at the repository root applies only when you start from the root.
67
68Each section below states whether its settings file belongs at the repository root or in the subdirectory you start from, and whether it is committed or kept local.
69
70## Layer CLAUDE.md files by directory
71
72In a large codebase, a single CLAUDE.md at the repository root tends to either grow to cover every subsystem's conventions, costing context on instructions unrelated to the current task, or stay too generic to be useful. Splitting instructions across per-directory files means Claude loads repository-wide rules plus only the conventions for the code you're working in.
73
74Claude Code loads every [CLAUDE.md](/en/memory) file from your working directory and every parent directory at launch, then loads each subdirectory's file on demand when it reads files there. A root file sets repository-wide rules and each subdirectory adds its own.
75
76A common split is two levels:
77
78* **Root `CLAUDE.md`**: instructions that apply everywhere, such as coding standards, commit conventions, and repository layout
79* **Per-subdirectory `CLAUDE.md`**: conventions specific to that area's stack. In a monorepo that's one per package. In a large single tree it's one per subsystem such as `src/db/` or `src/api/`
80
81Commit these files to the repository so teammates inherit them. Each directory's owner typically maintains its file.
82
83The root `CLAUDE.md` orients Claude to the repository structure:
84
85```markdown CLAUDE.md theme={null}
86This is a monorepo with three packages under packages/:
87
88- packages/api: Node.js REST API with Express, TypeScript, and PostgreSQL
89- packages/web: React frontend with Vite, TypeScript, and TailwindCSS
90- packages/shared: shared TypeScript utilities used by both api and web
91
92Run commands from the package directory, not the monorepo root.
93Each package has its own tsconfig.json, package.json, and test suite.
94```
95
96Each subdirectory's `CLAUDE.md`, here `packages/api/CLAUDE.md`, adds context specific to that area's stack:
97
98```markdown packages/api/CLAUDE.md theme={null}
99This package is the REST API server.
100
101- Run tests: `npm test` (uses Vitest)
102- Run dev server: `npm run dev` (port 3001)
103- Database migrations: `npm run migrate`
104- Environment variables: copy `.env.example` to `.env`
105
106API routes are in src/routes/. Each route file exports an Express router.
107Database queries use Knex in src/db/. Never write raw SQL strings in route handlers.
108```
109
110When you start Claude from `packages/api/`, it loads both `packages/api/CLAUDE.md` and the root `CLAUDE.md`. Claude sees the local instructions alongside the repository-wide rules, with no instructions from `packages/web/` in context. The same holds for any subdirectory in a non-monorepo tree.
111
112A few ways to keep the files current as the codebase and models change:
113
114* **Review in pull requests**: treat CLAUDE.md edits like any other documentation change so conventions track the code
115* **Revisit after major model releases**: instructions that worked around an older model's limitation may become overhead once a newer model handles the case on its own. For example, a rule that forces single-file refactors can be deleted once the limitation is gone
116* **Add a Stop hook that proposes updates**: a [`Stop` hook](/en/hooks#stop) receives the path to the session transcript when Claude finishes responding, so a script can review the session and propose CLAUDE.md updates while the gap it exposed is fresh
117
118For more on how CLAUDE.md files load and interact, see [Memory and project instructions](/en/memory).
119
120### Choose between per-directory CLAUDE.md and path-scoped rules
121
122Per-directory `CLAUDE.md` files and [path-scoped rules](/en/memory#path-specific-rules) under `.claude/rules/` both let you target instructions to part of the tree. They differ in where the file lives and when it loads.
123
124| Approach | File location | Loads when | Use when |
125| :----------------------------------- | :--------------------------------------- | :-------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------- |
126| Per-directory `CLAUDE.md` | Inside the directory, alongside its code | At launch when started from that directory, or on demand when Claude reads a file there | Directory owners maintain their own conventions; instructions are versioned with the code |
127| Path-scoped rule in `.claude/rules/` | Central `.claude/` at the repo root | When Claude works with a file matching the rule's `paths:` glob | You want all conventions in one place, or the same rule applies to many scattered paths |
128
129For a comparison that also covers skills, see [Compare similar features](/en/features-overview#compare-similar-features).
130
131### Exclude irrelevant CLAUDE.md files
132
133When you start Claude from the repository root, each subdirectory's CLAUDE.md loads as soon as Claude reads a file in that directory. The `claudeMdExcludes` setting skips specific files by path or glob pattern so they never load.
134
135Use this for directories you never work in, such as other teams' packages, legacy code, or vendored subtrees. The exclusion list is static, not a per-task switch. To focus on one package today and another tomorrow, [start Claude from that package's directory](#choose-where-to-start-claude) instead of editing exclusions.
136
137If you only want these exclusions for yourself, put the setting in `.claude/settings.local.json`, which is gitignored and not committed. Patterns use glob syntax matched against absolute file paths, so start relative-style patterns with `**/` to match anywhere in the tree. The example below excludes packages owned by other teams:
138
139```json .claude/settings.local.json theme={null}
140{
141 "claudeMdExcludes": [
142 "**/packages/admin-dashboard/**",
143 "**/packages/legacy-*/**"
144 ]
145}
146```
147
148This skips every CLAUDE.md and rules file under those packages. The root CLAUDE.md and the packages you do work in still load normally.
149
150These patterns cover other common cases:
151
152* `"**/packages/*/CLAUDE.md"`: excludes every package's CLAUDE.md while keeping the root
153* `"**/packages/web/**"`: excludes everything under the web package, including rules
154* `"/home/user/monorepo/legacy/CLAUDE.md"`: excludes one specific file by absolute path
155
156Managed policy CLAUDE.md files cannot be excluded, so organization-wide instructions always apply. You can set `claudeMdExcludes` at any [settings scope](/en/settings#configuration-scopes): user, project, local, or managed. Arrays merge across scopes, so a team can set project-level defaults while individuals add local overrides.
157
158For the full exclusion documentation, see [Exclude specific CLAUDE.md files](/en/memory#exclude-specific-claude-md-files).
159
160## Reduce what Claude reads
161
162Instructions are only part of what ends up in Claude's context. File reads are another cost that grows with the codebase. The settings below block reads of irrelevant paths and replace exhaustive file scans with language-server lookups.
163
164### Block reads of generated and vendored code
165
166Claude's content searches respect `.gitignore` by default, so paths already listed there, such as `node_modules/`, `dist/`, and `build/`, stay out of search results without additional configuration.
167
168For paths that are checked in, such as a vendored SDK or committed generated code, add `Read` deny rules in `permissions.deny` to block Claude from opening those files even when a search lists them.
169
170To apply these exclusions for everyone working in the repository, commit them to `.claude/settings.json`. To keep them personal, use `.claude/settings.local.json` instead. Like other project settings on this page, these files load only from your starting directory. Place them at the repository root if you start Claude there, or in each package's `.claude/` if you start from subdirectories. To enforce the same deny rules in every session regardless of starting directory, set them in [managed settings](/en/settings#settings-files), which user and project settings cannot override.
171
172The example below blocks build artifacts and a vendored SDK:
173
174```json .claude/settings.json theme={null}
175{
176 "permissions": {
177 "deny": [
178 "Read(./**/dist/**)",
179 "Read(./**/build/**)",
180 "Read(./**/*.generated.*)",
181 "Read(./vendor/**)"
182 ]
183 }
184}
185```
186
187Deny rules cover Claude's built-in file tools and recognized Bash file commands, including `cat`, `head`, `grep`, and `find`, when a denied path is passed as an argument. They do not filter denied paths out of a recursive search's output, and they do not cover arbitrary subprocesses that open files themselves. For the full pattern syntax, see [Read and Edit permission rules](/en/permissions#read-and-edit).
188
189### Reduce file reads with code intelligence
190
191In a large codebase, finding where a symbol is defined or used can cost many file reads and grep calls. [Code intelligence plugins](/en/discover-plugins#code-intelligence) connect Claude to a language server so it can jump to definitions, find references, and surface type errors directly instead of scanning the tree.
192
193The official marketplace has plugins for TypeScript, Python, Go, Rust, and other common languages. The example below installs the TypeScript plugin:
194
195```shell theme={null}
196/plugin install typescript-lsp@claude-plugins-official
197```
198
199To enable a plugin for everyone in the repository rather than installing it yourself, add it to the [`enabledPlugins` project setting](/en/settings#plugin-settings).
200
201Code intelligence plugins require the language's language server binary on each developer's machine. See [which binary each language requires](/en/discover-plugins#code-intelligence). Installing from the official marketplace requires network access to GitHub, where the marketplace is hosted. On a restricted network, [add the marketplace from an internal Git host or local path](/en/discover-plugins#add-from-other-git-hosts) instead.
202
203This pairs well with `claudeMdExcludes` and the `Read` deny rules above. Those keep irrelevant content out of context, and code intelligence keeps Claude from reading through what remains to locate a definition.
204
205## Scope worktrees and file access
206
207These settings control what's on disk in worktrees and which directories Claude can read and write beyond your starting point.
208
209### Check out only the directories you need
210
211The `--worktree` flag starts a session in a new git worktree so changes stay isolated from your main checkout. By default it checks out the entire repository. In a large repository, the `worktree.sparsePaths` setting uses git sparse-checkout to write only the listed directories plus root-level files to disk, so worktrees start faster and use less space.
212
213If everyone working in this directory needs the same paths, commit the setting to `.claude/settings.json`. To add paths for yourself, use `.claude/settings.local.json`: the lists merge across scopes, so a local file can add paths to the committed list but not remove them. The example below shows the committed file:
214
215```json .claude/settings.json theme={null}
216{
217 "worktree": {
218 "sparsePaths": [
219 ".claude",
220 "packages/api",
221 "packages/shared"
222 ]
223 }
224}
225```
226
227When Claude creates a worktree, it checks out only `.claude/`, `packages/api/`, and `packages/shared/` instead of the full tree. Paths in `sparsePaths` are relative to the repository root, regardless of which subdirectory you start Claude from. Any directory paths work here, not only package roots.
228
229This is particularly useful for [subagent worktree isolation](/en/worktrees#isolate-subagents-with-worktrees). Subagents are parallel Claude instances spawned for subtasks, and each one that runs in a worktree gets a lightweight checkout instead of the full tree. All worktrees in a session share the same `sparsePaths`, so if one subagent needs `packages/api/` and another needs `packages/web/`, list both.
230
231List directories in `sparsePaths`, not individual files. Root-level files like `package.json`, `tsconfig.base.json`, and lock files are always checked out alongside the directories you list. Root-level directories are not, so include `.claude` in the list if you want the repository root's `.claude/settings.json`, `.claude/rules/`, or `.claude/skills/` available inside the worktree.
232
233To avoid duplicating large directories like `node_modules` across worktrees, pair `sparsePaths` with `symlinkDirectories` in the same `.claude/settings.json`:
234
235```json .claude/settings.json theme={null}
236{
237 "worktree": {
238 "sparsePaths": [
239 ".claude",
240 "packages/api",
241 "packages/shared"
242 ],
243 "symlinkDirectories": [
244 "node_modules"
245 ]
246 }
247}
248```
249
250This creates a symlink from each worktree's `node_modules/` back to the main repository's copy rather than duplicating it on disk.
251
252<Note>
253 The `sparsePaths` and `symlinkDirectories` settings are read from your starting directory before the worktree is created. After creation, the session's working directory is the worktree root, not the subdirectory you launched from. Project settings inside the worktree therefore load from the worktree root's `.claude/settings.json`, the checked-out copy of the repository root's file. Put any other settings you need inside worktrees, such as permission rules or hooks, in the repository root's `.claude/settings.json`.
254</Note>
255
256For the full worktree settings reference, see [Worktree settings](/en/settings#worktree-settings).
257
258### Grant access across packages or repositories
259
260This section applies when you start Claude from a subdirectory, or when a task spans multiple checkouts. If you start from the repository root in a single large tree, Claude already has access to every file and you can skip this.
261
262When you start Claude from `packages/api/`, it can read and write files within that directory. If a task requires changes across packages, such as updating a shared type that both `api` and `web` import, you need to grant access to the sibling directory. The same mechanism grants access to a separately-checked-out repository.
263
264The `additionalDirectories` setting in `.claude/settings.json` gives Claude access to directories outside the working directory. The example below grants access to two sibling packages:
265
266```json .claude/settings.json theme={null}
267{
268 "permissions": {
269 "additionalDirectories": [
270 "../shared",
271 "../web"
272 ]
273 }
274}
275```
276
277Relative paths resolve against the directory you start Claude from. With this configuration, Claude can read and edit files in `packages/shared/` and `packages/web/` while working from `packages/api/`.
278
279You can also grant access at runtime without editing settings by passing `--add-dir` when you start Claude:
280
281```bash theme={null}
282claude --add-dir ../shared
283```
284
285However you add a directory, Claude can read and edit files in it. Whether the directory's CLAUDE.md, `.claude/rules/` files, and skills also load depends on how you added it:
286
287| Added with | Loads CLAUDE.md and rules | Loads skills |
288| :------------------------------------- | :--------------------------------------- | :----------- |
289| `additionalDirectories` setting | Never | Never |
290| `--add-dir` flag or `/add-dir` command | Only with the environment variable below | Yes |
291
292To load CLAUDE.md and rules files from a directory added with `--add-dir` or `/add-dir`, set the `CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD` environment variable:
293
294```bash theme={null}
295CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1 claude --add-dir ../shared
296```
297
298The environment variable has no effect on directories listed in the `additionalDirectories` setting. See [Load from additional directories](/en/memory#load-from-additional-directories) for details.
299
300For sibling directories that everyone in this area needs, commit `additionalDirectories` to `.claude/settings.json`. For a personal selection or one-off access, use `.claude/settings.local.json` or pass `--add-dir` at launch.
301
302## Add per-directory skills
303
304Any subdirectory can define [skills](/en/skills) scoped to its own stack. A skill loads on demand when Claude determines it's relevant, so API-specific tooling doesn't consume context during frontend work.
305
306Skills live under `.claude/skills/` inside the directory. Commit them alongside that area's code so anyone who clones the repository gets them. In a monorepo this can be one set of skills per package. In a large single-tree codebase it's one set per subsystem such as `src/db/.claude/skills/`.
307
308Create a skill directory inside the subdirectory:
309
310```bash theme={null}
311mkdir -p packages/api/.claude/skills/api-testing
312```
313
314Then write `SKILL.md` inside that directory, here `packages/api/.claude/skills/api-testing/SKILL.md`. This example teaches Claude the API package's testing patterns:
315
316```markdown packages/api/.claude/skills/api-testing/SKILL.md theme={null}
317---
318name: api-testing
319description: Testing patterns for the API package. Use when writing or modifying tests in packages/api/.
320---
321
322## Test structure
323
324Tests are in `src/__tests__/` mirroring the `src/` directory structure.
325Each route file has a corresponding `.test.ts` file.
326
327## Running tests
328
329- All tests: `npm test`
330- Single file: `npm test -- src/__tests__/routes/users.test.ts`
331- Watch mode: `npm test -- --watch`
332
333## Test utilities
334
335- `src/__tests__/helpers/db.ts`: provides `setupTestDb()` and `teardownTestDb()` for database tests
336- `src/__tests__/helpers/auth.ts`: provides `createTestUser()` and `getAuthToken()` for authenticated endpoints
337
338## Patterns
339
340- Use `supertest` for HTTP assertions, not raw fetch
341- Always wrap database tests in a transaction that rolls back
342- Mock external services in `src/__tests__/mocks/`
343```
344
345A different subdirectory holds different skills the same way: `packages/web/.claude/skills/component-patterns/` describes the frontend's component conventions instead of testing. When Claude works on a file in `packages/api/`, it loads the api-testing skill. When it works in `packages/web/`, it loads component-patterns instead. Neither directory's skills load during the other's tasks.
346
347You can also scope a skill by file pattern instead of by placement. The [`paths` frontmatter field](/en/skills#frontmatter-reference) takes glob patterns, and Claude loads the skill automatically only when it works with matching files. Use this for a skill that lives in the repository root's `.claude/skills/` but applies only to certain files wherever they appear, such as a database-migration skill scoped to `**/migrations/**`.
348
349For more on creating and organizing skills, see [Skills](/en/skills).
350
351### Keep skills discoverable
352
353With skills spread across many directories, the list Claude chooses from can grow large. Claude picks a skill by reading every discovered skill's name and description, and only the chosen skill's full content loads into context. This section covers how to keep that list small and write descriptions that survive shortening.
354
355Which skills are in scope depends on where you start Claude:
356
357* **From a subdirectory such as `packages/api/`**: skills from that directory, every parent up to the repository root, and the user and enterprise levels
358* **From the repository root**: skills from every subdirectory Claude touches during the session, which can accumulate into the hundreds
359* **After adding a sibling with [`--add-dir`](#grant-access-across-packages-or-repositories)**: that sibling's skills load too. The `additionalDirectories` setting grants file access only and does not load skills
360
361Names always load, but [descriptions are shortened when there are many](/en/skills#skill-descriptions-are-cut-short), which can strip the keywords Claude uses to decide whether a skill applies. Keep descriptions short and lead with words a request would contain, like "writing or modifying tests in `packages/api/`".
362
363For skills that many directories share, such as PR conventions or a deploy checklist, place them in the repository root's `.claude/skills/` so they load from any starting directory. When shared skills need their own version history or must work across repositories, package them as a [plugin](/en/plugins) instead. Plugin skills use a `plugin-name:skill-name` namespace, so they never collide with per-directory skills. A platform team can version and update them in one place.
364
365To find which skills go unused, enable the OpenTelemetry [logs exporter](/en/monitoring-usage) and set `OTEL_LOG_TOOL_DETAILS=1` so skill names are recorded verbatim instead of redacted. The [`skill_activated` event](/en/monitoring-usage#skill-activated-event) records every invocation in its `skill.name` attribute, and `invocation_trigger` records whether a command, Claude, or a nested skill invoked it, which tells you what to consolidate or retire.
366
367## Centralize conventions when layering stops scaling
368
369Per-directory CLAUDE.md files can become hard to govern as the codebase grows. Conventions drift, files go stale, and no one owns the root. Solving that typically falls to the team that maintains the repository's Claude Code setup rather than to each developer working in their own area.
370
371Move conventions and reference content out of always-loaded CLAUDE.md and into mechanisms that load on demand:
372
373* [Skills](/en/skills): reference material Claude loads only when relevant to the task
374* [Plugins](/en/plugins): versioned bundles of skills, hooks, and commands that a platform team owns centrally
375* [MCP servers](/en/mcp): if your organization already runs a code search or RAG index over the repository, expose it as an MCP tool so Claude queries it instead of reading files directly
376
377See [server-managed or endpoint-managed settings](/en/server-managed-settings#choose-between-server-managed-and-endpoint-managed-settings) for how platform teams can enforce these centrally.
378
379### Recommend the right plugin at session start
380
381Once conventions live in plugins, a teammate starting Claude in an unfamiliar part of the tree has no signal about which plugin that area's owners maintain. A [`SessionStart` hook](/en/hooks#sessionstart) can close that gap, since anything the hook prints to stdout is added to Claude's context before the first prompt.
382
383For example, you can write a script that reads the launch directory from the [hook input](/en/hooks#common-input-fields), looks it up in a path-to-plugin map committed to the repository, and prints the recommendation for Claude to relay in its first reply. See [Automate workflows with hooks](/en/hooks-guide) to write and register the hook.
384
385## Put it together
386
387The combined configuration below uses the monorepo layout. The same files work for any subdirectory in a large single tree. Project settings load only from the directory you start Claude in, so each subdirectory's `.claude/settings.json` must be self-contained rather than layered on a root file.
388
389The example commits `worktree`, `additionalDirectories`, and the `Read` deny rules in `.claude/settings.json` so every developer in `packages/api/` gets the same sibling access, sparse paths, and exclusions. The file below is the committed per-area settings for `packages/api/`:
390
391```json packages/api/.claude/settings.json theme={null}
392{
393 "worktree": {
394 "sparsePaths": [
395 ".claude",
396 "packages/api",
397 "packages/shared"
398 ],
399 "symlinkDirectories": [
400 "node_modules"
401 ]
402 },
403 "permissions": {
404 "additionalDirectories": [
405 "../shared"
406 ],
407 "deny": [
408 "Read(./**/dist/**)",
409 "Read(./**/build/**)"
410 ]
411 }
412}
413```
414
415Because this session starts from `packages/api/`, sibling packages' CLAUDE.md files are already out of scope, so `claudeMdExcludes` is not needed here. Add it to the repository root's `.claude/settings.local.json` instead if you also start sessions from the root.
416
417The `additionalDirectories` entry applies when you start Claude from `packages/api/` directly. Inside a worktree created from this session, the working directory is the worktree root, so this settings file does not load. The sibling packages are already reachable inside the worktree without it, but the deny rules need a second copy in the repository root's `.claude/settings.json` so worktree sessions pick them up, as the [worktree settings note](#check-out-only-the-directories-you-need) describes:
418
419```json .claude/settings.json theme={null}
420{
421 "permissions": {
422 "deny": [
423 "Read(./**/dist/**)",
424 "Read(./**/build/**)"
425 ]
426 }
427}
428```
429
430After setup, the repository has this layout:
431
432```text theme={null}
433monorepo/
434 CLAUDE.md
435 .claude/settings.json # deny rules for worktree sessions
436 packages/
437 api/
438 CLAUDE.md
439 .claude/settings.json # worktree, additionalDirectories, deny rules
440 .claude/skills/api-testing/SKILL.md
441 web/
442 CLAUDE.md
443 .claude/skills/component-patterns/SKILL.md
444 shared/
445 CLAUDE.md
446```
447
448With this setup, starting Claude from `packages/api/`:
449
450* Loads the root CLAUDE.md and `packages/api/CLAUDE.md`, skips `packages/web/CLAUDE.md`
451* Can read and edit files in `packages/api/` and `packages/shared/`
452* Skips reads of build output under `dist/` and `build/` in `packages/api/`
453* Has the api-testing skill available on demand
454* Creates worktrees containing `.claude/`, `packages/api/`, `packages/shared/`, and root-level files, with the deny rules applied across the worktree from the root settings file
455
456## Scope and plan changes that span packages
457
458The configuration above controls what Claude sees. When a single change touches several packages, such as updating a shared type along with every call site that uses it, how you scope and sequence the task also affects the result.
459
460Two techniques help keep a cross-package change consistent:
461
462* **Give Claude the whole change in one session**: handing over the shared edit and its call sites together keeps the decisions behind each edit consistent, rather than re-deriving them per package
463* **Save the plan to a file before editing**: [plan first](/en/best-practices#explore-first-then-plan-then-code) and ask Claude to write the plan to a markdown file in the repository. A long cross-package session [compacts its context](/en/context-window#what-survives-compaction) along the way, and the saved plan survives where conversation history may not
464
465## Next steps
466
467Once this configuration is in place, you can refine it:
468
469* Use [hooks](/en/hooks-guide) to run per-directory linters or type-checkers after Claude edits files
470* Review [Manage costs effectively](/en/costs) to understand how codebase size affects token usage and how to set spend limits before a wider rollout
471* Read [How Claude Code works in large codebases](https://claude.com/blog/how-claude-code-works-in-large-codebases-best-practices-and-where-to-start) on the Claude blog for organizational rollout patterns and ownership models that sit above the per-repository configuration on this page