Who this is for and what you will be able to do
This guide is for teams whose repository has grown so large that Claude keeps reading files unrelated to the task, and for developers who work inside one or two packages of a monorepo. After reading it you will know which directory to launch Claude from, how to split instruction files across directories, how to block generated and vendored code, and how to set up worktrees and cross-package access.
Why large repositories need tuning
Claude Code works at any size, but its defaults were tuned with smaller projects in mind. In a big repository, instructions and file reads can fill the context window with material that has nothing to do with the current task. That wastes tokens and can weaken Claude's output[1]. Everything below aims to keep that material out.
Decide where to start
The directory you launch from controls which files Claude can touch without extra permission, and which CLAUDE.md files load at startup[1].
- Launching from the repository root gives access to every file. Only the root CLAUDE.md loads at launch, and subdirectory files load on demand. This suits tasks that span several packages[1].
- Launching from a subdirectory limits file access to that subtree until you grant more. The CLAUDE.md files of that directory and of every ancestor load at startup. This suits work confined to one package[1].
Keep in mind that .claude/settings.json is not inherited from parent directories the way CLAUDE.md files are, so each directory needs its own settings[1].
Splitting CLAUDE.md files by directory
At launch, Claude Code loads each CLAUDE.md in the working directory and in every parent directory, and it loads subdirectory files on demand. A common arrangement is a root file for rules that hold across the whole repository, plus one file per package or subsystem with that area's conventions[1].
The root file can hold rules that apply everywhere. For example:
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.To confirm which files loaded, run /context all and check the Memory files list[1].
Another option is a path-scoped rule. Rules under .claude/rules/ load only when Claude works with a file that matches the rule's paths: glob. Per-directory CLAUDE.md files load at launch from that directory or on demand. Choose between them by asking who maintains the conventions and where they are easiest to find[1].
If you launch from the root and some directories are irrelevant to you, claudeMdExcludes can skip their CLAUDE.md files. The list is static rather than a per-task switch. To focus on a different package tomorrow, it is simpler to launch from that package's directory[1]. As an example, this in .claude/settings.local.json skips a package owned by another team:
{
"claudeMdExcludes": [
"**/packages/web/**"
]
}Reducing file reads with deny rules
Context is not only instructions. File reads add up too. Claude's content search respects .gitignore by default, so directories already listed there, such as node_modules/, dist/, and build/, stay out of results without extra setup[1].
Checked-in material is different. A vendored SDK or committed generated code is not covered by .gitignore, so add Read deny rules under permissions.deny to stop Claude from opening it[1]. A .claude/settings.json could look like this:
{
"permissions": {
"deny": [
"Read(./**/dist/**/*)",
"Read(./**/build/**/*)",
"Read(./**/*.generated.*)",
"Read(./**/vendor/**/*)"
]
}
}The directory patterns end in /**/*, not /**. That keeps the directory itself listable and enterable while blocking what is inside it[1].
It helps to know what the rules reach. They apply to Claude's built-in file tools. In Bash they apply to recognized file commands such as cat, head, grep, and find when a denied path is one of the arguments, and to a redirection target such as < file. They do not stop a subprocess from opening a file on its own[1].
Choose the scope carefully. Committing the rules to .claude/settings.json covers everyone in the repository. A .claude/settings.local.json at the root covers only you. Managed settings enforce the rules in a way user and project settings cannot override[1].
Code intelligence instead of full-tree scans
Finding where a symbol is defined or called can take many reads and greps in a large repository. Code intelligence plugins connect Claude to a language server, so it can jump to definitions, find references, and see type errors without scanning files. The official marketplace includes plugins for TypeScript, Python, Go, Rust, and other common languages[1].
Start claude in a terminal and enter this at the prompt to install the TypeScript plugin:
/plugin install typescript-lsp@claude-plugins-officialEach developer's machine needs the matching language server binary, and installing from the official marketplace needs network access to GitHub, where it is hosted[1].
Checking out only the directories you need
The --worktree flag creates a git worktree so changes stay apart from your main checkout, and by default it checks out the whole repository. The worktree.sparsePaths setting uses git sparse-checkout instead. It writes only the listed directories, plus root-level files, to disk. Worktrees then start faster and take less space[1].
In the committed .claude/settings.json, that looks like this:
{
"worktree": {
"sparsePaths": [
".claude",
"packages/api",
"packages/shared"
]
}
}List directories, not single files. Root-level files such as package.json and lock files always come along, but root-level directories do not. If the worktree needs the root .claude/settings.json or .claude/rules/, include .claude in the list[1].
You can also add symlinkDirectories, for example with node_modules. Each worktree's node_modules/ then becomes a symbolic link back to the main repository's copy instead of a second copy on disk[1].
Cross-package access and per-directory skills
When you launch from a subdirectory but a change must touch a sibling package, such as a shared type that two packages import, grant access with additionalDirectories. Relative paths resolve from the directory where you launched Claude. From packages/api/, listing "../shared" and "../web" makes both siblings readable and editable[1].
How you grant access also decides what loads. Directories added through additionalDirectories never load CLAUDE.md, rules, or skills. Directories added with --add-dir or /add-dir load skills. Their CLAUDE.md and rules load only when CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD is set, as in CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1 claude --add-dir ../shared[1].
Any subdirectory can hold skills under .claude/skills/. They load on demand when Claude judges them relevant. Create one with mkdir -p packages/api/.claude/skills/api-testing, then write its SKILL.md[1].
Many skills create their own problem. Claude reads every discovered skill's name and description when it picks one, and once there are many, some descriptions are cut off. Keep descriptions short and open them with words a request would contain[1].
Limits and common problems
- **
sparsePathsandsymlinkDirectoriesare read before the worktree exists.** They come from the directory you launched in. Once the worktree is created, the session's working directory is its root, so anadditionalDirectoriesentry in a subdirectory settings file does not apply there[1]. - Deny rules do not reach subprocesses. A file opened by a child process is outside their reach[1].
- Code intelligence needs the server binary. Without the language server installed locally, the plugin has nothing to run[1].
- Sparse checkout saves space only when configured. Worktrees write only the listed directories when
worktree.sparsePathsis set[1].
Next steps
Hooks can run a per-directory linter or type checker after Claude edits files. For the full set of settings and their details, see the official documentation[1].
Sources
- 1Set up Claude Code in a monorepo or large codebaseAnthropic Claude Code docs
Cite this page: Claude Code in large codebases. TellWorld, https://www.tellworld.net/practice/practice-claude-code-large-codebases. Updated 2026-11-14