tencent cloud

Monorepos and Large Repositories

Download
Focus Mode
Font Size
Last updated: 2026-09-30 18:28:06
AI-Translated

Setting Up CodeBuddy Code in a Monorepo or Large Codebase

Note:
Configure CodeBuddy Code for monorepos and large single-tree repositories, using nested CODEBUDDY.md files, sparse worktrees, code intelligence, and per-package skills to keep CodeBuddy focused on the code you are working on.
A large codebase can be a single repository with millions of lines of code or a monorepo containing many packages. CodeBuddy Code works at any scale, but as your codebase grows, default settings tuned for smaller projects can fill the context window with task-irrelevant instructions and file reads, wasting tokens and degrading CodeBuddy's performance.
This guide shows individual developers and engineering teams how to limit CodeBuddy's scope to the parts of the codebase involved in a task. Each section indicates whether the setting is personal or committed to the repository.

What This Guide Covers

The following table lists each setting and its purpose. The file tree that follows is the sample monorepo referenced by each code example on this page.

Settings on This Page

Each setting below is independent. They stack rather than replace each other, so apply whichever settings suit your repository. Choosing where to launch CodeBuddy determines where your settings files live, so read that first. Putting it all together shows how all of these settings combine.
I Want To
Use
Load only the conventions for the code you touch, rather than a root file overriding every subsystem.
Per-directory CODEBUDDY.md files
Prevent CodeBuddy from opening build outputs, generated code, and vendor dependencies.
Read deny rule in permissions.deny
Find symbol definitions or callers through the language server instead of scanning files.
Code intelligence plugin
When CodeBuddy creates a worktree, check out only the directories required by the task.
worktree.sparsePaths
Read and edit sibling packages or another repository from the same session.
--add-dir or additionalDirectories
Provide CodeBuddy with area-specific programs that are loaded only when relevant.
Per-directory Skills
Replace many per-directory CODEBUDDY.md files with a single set of conventions that everyone installs.
plugin in the internal marketplace
Note:
For workflow techniques for keeping context small in any repository, such as running exploration in subagents so that file reads do not enter the main conversation, see CodeBuddy Code practical tutorial.

Sample monorepo

The examples on this page reference a monorepo with three packages. The same pattern applies to large single-tree repositories: replace packages/api/ with your own subsystem directory, such as src/backend/ or lib/core/.
monorepo/
CODEBUDDY.md # Root instructions
packages/
api/
CODEBUDDY.md # API-specific instructions
.codebuddy/skills/
src/
web/
CODEBUDDY.md # Frontend-specific instructions
.codebuddy/skills/
src/
shared/
CODEBUDDY.md # Shared library instructions
src/

Choosing Where to Launch CodeBuddy From

Where you launch codebuddy determines which files CodeBuddy can read and edit without additional permission grants, which CODEBUDDY.md files are loaded at startup, and which project settings apply.
Launch From
File Access
CODEBUDDY.md Loaded at Startup
Scenario
Repository root directory
Every file
Only the root directory; when CodeBuddy reads there, subdirectory files are loaded on demand.
Tasks span multiple packages or subsystems.
Subdirectory
Only this subtree until you grant more permissions.
The CODEBUDDY.md in this directory plus that in each ancestor directory
Work scope limited to a single package or subsystem.
Project settings in .codebuddy/settings.json are loaded only from your launch directory, not inherited from parent directories like CODEBUDDY.md files: the .codebuddy/settings.json at the repository root applies only when you launch from the root.
Each section below explains whether its settings file should live at the repository root or in the subdirectory where you launch, and whether it is committed or kept local.

Layering CODEBUDDY.md Files by Directory

In large codebases, a single CODEBUDDY.md at the repository root often either grows to cover conventions for every subsystem, wasting context on instructions irrelevant to the current task, or stays too generic to be useful. Distributing instructions across per-directory files means CodeBuddy loads repository-wide rules plus conventions only for the code you are working on.
At startup, CodeBuddy Code loads every CODEBUDDY.md file from your working directory and each parent directory, and then loads files from each subdirectory on demand when it reads files there. The root file sets repository-wide rules, and each subdirectory adds its own rules.
A common split is two levels:
Root CODEBUDDY.md: Instructions that apply everywhere, such as coding standards, commit conventions, and repository layout
Per-subdirectory CODEBUDDY.md: Conventions specific to that area of the stack. In a monorepo, this is one per package. In a large single tree, it is one per subsystem, such as src/db/ or src/api/
Commit these files to the repository so that teammates inherit them. The owner of each directory typically maintains its file.
The root CODEBUDDY.md directs CodeBuddy to the repository structure:
# CODEBUDDY.md

This is a monorepo with three packages under packages/:

- packages/api: A Node.js REST API using Express, TypeScript, and PostgreSQL
- packages/web: A React frontend using Vite, TypeScript, and TailwindCSS
- packages/shared: Shared TypeScript utilities used by both api and web

Run commands from the package directory, not from the monorepo root.
Each package has its own tsconfig.json, package.json, and test suite.
The per-subdirectory CODEBUDDY.md, here packages/api/CODEBUDDY.md, adds context specific to that area of the stack:
# packages/api/CODEBUDDY.md

This package is a REST API server.

- Run tests: `npm test` (using Vitest)
- Run the development server: `npm run dev` (port 3001)
- Database migration: `npm run migrate`
- Environment variables: Copy `.env.example` to `.env`

API routes are in src/routes/. Each route file exports an Express router.
Database queries use Knex in src/db/. Never write raw SQL strings in route handlers.
When you start CodeBuddy from packages/api/, it loads packages/api/CODEBUDDY.md and the root CODEBUDDY.md. CodeBuddy sees the local instructions alongside the repository-wide rules, with no instructions from packages/web/ in the context. The same applies to any subdirectory in a non-monorepo tree.
Several ways to keep the file up to date as the codebase and models evolve:
Review in pull requests: Treat CODEBUDDY.md edits like any other documentation change so that conventions track the code.
Revisit after major model releases: Instructions that work around older model limitations may become overhead once newer models handle the situation themselves. For example, a rule enforcing single-file refactoring can be removed once the limitation disappears.
Add a Stop hook to propose updates: Stop hook receives the path to the session transcript when CodeBuddy finishes a response, so a script can review the session and propose CODEBUDDY.md updates while the exposed gaps are still fresh.
For more information about how CODEBUDDY.md files are loaded and interact, see Memory and project instructions.

Choosing Between Directory-Based CODEBUDDY.md and Path-Scoped Rules

Both per-directory CODEBUDDY.md files and path-scoped rules under .codebuddy/rules/ allow you to target instructions to a part of the tree. They differ in file location and load timing.
Methodology
File Location
Load Time
Scenario
By directory CODEBUDDY.md
Inside the directory, alongside its code
At startup when it is launched from that directory, or on demand when CodeBuddy reads files there.
Directory owners maintain their own conventions; instructions are versioned alongside the code.
Path-scoped rules in .codebuddy/rules/
Central .codebuddy/ at the repository root
When CodeBuddy processes files that match the rule's paths: glob
You want all conventions in one place, or the same rules apply to many scattered paths.

Reducing What CodeBuddy Reads

Instructions are only one part of what ultimately goes into CodeBuddy's context. File reading is another cost that increases as the codebase grows. The following settings prevent reading irrelevant paths and replace exhaustive file scanning with language server lookups.

Preventing Reads of Generated and Vendor Code

CodeBuddy's content search respects .gitignore by default, so paths already listed there, such as node_modules/, dist/, and build/, stay out of search results without additional configuration.
For checked-in paths, such as vendor SDKs or committed generated code, add a Read deny rule in permissions.deny to prevent CodeBuddy from opening these files even if search lists them.
To apply these exclusions for everyone working in the repository, commit them to .codebuddy/settings.json. To keep them personal, use .codebuddy/settings.local.json instead. Like other project settings on this page, these files are loaded only from your launch directory. Place them at the repository root if you launch CodeBuddy from there, or in each package's .codebuddy/ if you launch from a subdirectory.
The following example blocks build artifacts and vendor SDKs:
// .codebuddy/settings.json
{
"permissions": {
"deny": [
"Read(./**/dist/**)",
"Read(./**/build/**)",
"Read(./**/*.generated.*)",
"Read(./vendor/**)"
]
}
}
Deny rules cover CodeBuddy'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 from recursive search output, nor do they cover arbitrary subprocesses that open files on their own. For the complete pattern syntax, see Read and Edit permission rules.

Reducing File Reads with Code Intelligence

In large codebases, finding where a symbol is defined or used can require many file reads and grep calls. The code intelligence plugin connects CodeBuddy to language servers so it can jump to definitions, find references, and surface type errors directly instead of scanning the tree.
The official marketplace has plugins for TypeScript, Python, Go, Rust, and other common languages. The following example installs the TypeScript plugin:
/plugin install typescript-lsp@claude-plugins-official
To enable a plugin for everyone in the repository instead of installing it yourself, add it to the enabledPlugins project setting.
The code intelligence plugin requires language server binaries for the language on each developer's machine. Installing from the official marketplace requires network access to GitHub, where the marketplace is hosted. On restricted networks, add a marketplace from an internal Git host or a local path.
This pairs well with the Read deny rule above. The deny rule keeps irrelevant content out of the context, and code intelligence keeps CodeBuddy from reading the rest to locate definitions.

Scoped Worktrees and File Access

These settings control what is on disk in worktrees and which directories beyond the launch point CodeBuddy can read from and write to.

Checking Out Only the Directories You Need

The --worktree flag starts a session in a new git worktree so that changes are isolated from the main checkout. By default, it checks out the entire repository. In large repositories, the worktree.sparsePaths setting uses git sparse-checkout to write only the listed directories plus root-level files to disk, so that worktrees start faster and use less space.
If everyone working in this directory needs the same paths, commit the setting to .codebuddy/settings.json. To add paths for yourself, use .codebuddy/settings.local.json: the lists are merged by scope, so the local file can add paths to the committed list but cannot remove them. The following example shows the committed file:
// .codebuddy/settings.json
{
"worktree": {
"sparsePaths": [
".codebuddy",
"packages/api",
"packages/shared"
]
}
}
When CodeBuddy creates a worktree, it checks out only .codebuddy/, 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 CodeBuddy from. Any directory path works here, not just package roots.
This is especially useful for subagent worktree isolation. Subagents are parallel CodeBuddy instances spawned for subtasks, and each one running 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.
List directories in sparsePaths, not individual files. Root-level files such as package.json, tsconfig.base.json, and lock files are always checked out along with the directories you list. Root-level directories are not, so if you want .codebuddy/settings.json, .codebuddy/rules/, or .codebuddy/skills/ from the repository root to be available inside the worktree, include .codebuddy in the list.
To avoid copying large directories such as node_modules in worktrees, pair sparsePaths with symlinkDirectories in the same .codebuddy/settings.json:
// .codebuddy/settings.json
{
"worktree": {
"sparsePaths": [
".codebuddy",
"packages/api",
"packages/shared"
],
"symlinkDirectories": [
"node_modules"
]
}
}
This creates a symlink from each worktree's node_modules/ back to the main repository copy instead of duplicating it on disk.
Note:
The sparsePaths and symlinkDirectories settings are read from your launch directory before the worktree is created. After creation, the session's working directory is the worktree root, not the subdirectory you launched from. Therefore, project settings within the worktree are loaded from .codebuddy/settings.json at the worktree root, which is a checked-out copy of the repository root file. Place any other settings you need inside worktrees, such as permission rules or hooks, in .codebuddy/settings.json at the repository root.
For a complete reference of worktree settings, see Worktree Settings.

Granting Access Across Packages or Repositories

This section applies when you start CodeBuddy from a subdirectory, or when a task spans multiple checkouts. If you start from the repository root in a single large tree, CodeBuddy already has access to every file, and you can skip this section.
When you start CodeBuddy from packages/api/, it can read and write files within that directory. If a task requires cross-package changes, such as updating shared types that both api and web import, you need to grant access to sibling directories. The same mechanism grants access to separately checked-out repositories.
The additionalDirectories setting in .codebuddy/settings.json gives CodeBuddy access to directories outside the working directory. The following example grants access to two sibling packages:
// .codebuddy/settings.json
{
"permissions": {
"additionalDirectories": [
"../shared",
"../web"
]
}
}
Relative paths are resolved relative to the directory from which you start CodeBuddy. With this configuration, CodeBuddy can read and edit files in packages/shared/ and packages/web/ when working from packages/api/.
You can also grant access at runtime without editing settings by passing --add-dir when starting CodeBuddy:
codebuddy --add-dir ../shared
Regardless of how you add a directory, CodeBuddy can read and edit files within it. Whether the directory's CODEBUDDY.md, .codebuddy/rules/ files, and skills are also loaded depends on how you add it:
Adding Method
Loading CODEBUDDY.md and Rules
Loading skills
additionalDirectories setting
Never
Never
--add-dir flag or /add-dir command
Use Only the Environment Variables Below.
Yes
To load CODEBUDDY.md and rules files from directories added with --add-dir or /add-dir, set the CODEBUDDY_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD environment variable:
CODEBUDDY_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1 codebuddy --add-dir ../shared
The environment variable has no effect on directories listed in the additionalDirectories setting. For details, see Memory.
For sibling directories that everyone in this area needs, commit additionalDirectories to .codebuddy/settings.json. For personal preferences or one-off access, use .codebuddy/settings.local.json or pass --add-dir at startup.

Adding Directory-Scoped Skills

Any subdirectory can define skills scoped to its own stack. Skills are loaded on demand when CodeBuddy determines they are relevant, so API-specific tools do not consume context during frontend work.
Skills live under .codebuddy/skills/ within a directory. Commit them alongside the code for that area so that anyone who clones the repository gets them. In a monorepo, this can be one set of skills per package. In a large single-tree repository, it is one set per subsystem, such as src/db/.codebuddy/skills/.
Create a skill directory within the subdirectory:
mkdir -p packages/api/.codebuddy/skills/api-testing
Then write SKILL.md in that directory, which is packages/api/.codebuddy/skills/api-testing/SKILL.md. This example teaches CodeBuddy the testing patterns for the API package:
---
name: api-testing
description: Testing patterns for the API package. Use when writing or modifying tests in packages/api/.
---

## Test Structure

Tests live in `src/__tests__/`, mirroring the `src/` directory structure.
Each route file has a corresponding `.test.ts` file.

## Run 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 testing.
- `src/__tests__/helpers/auth.ts`: Provides `createTestUser()` and `getAuthToken()` for authentication endpoints.

## Modes

- Use `supertest` for HTTP assertions instead of raw fetch.
- Always wrap database tests in a transaction that rolls back.
- Mock external services in `src/__tests__/mocks/`.
Different subdirectories store different skills in the same way: packages/web/.codebuddy/skills/component-patterns/ describes frontend component conventions rather than testing. When CodeBuddy processes files in packages/api/, it loads the api-testing skill. When it works in packages/web/, it loads component-patterns instead. During another task, the skills from both directories are not loaded.
You can also scope skills by file pattern instead of by location. The paths frontmatter field accepts glob patterns, and CodeBuddy automatically loads the skill only when processing matching files. Use this feature for skills that reside in .codebuddy/skills/ at the repository root but apply only to certain files, regardless of where they appear, such as a database migration skill scoped to /migrations/.
For more information about creating and organizing skills, see Skills.

Keeping Skills Discoverable

As skills are scattered across many directories, the list that CodeBuddy selects from can grow large. CodeBuddy selects a skill by reading the name and description of each discovered skill, and only the full content of the selected skill is loaded into context. This section covers how to keep that list small and write descriptions that survive truncation.
Which skills are in scope depends on where you launch CodeBuddy:
From a subdirectory such as packages/api/: skills from that directory, every parent directory up to the repository root, and the user level
From the repository root: skills from every subdirectory that CodeBuddy touches during a session, potentially accumulating to hundreds
After a sibling directory is added with --add-dir: the skills in that sibling directory are also loaded. The additionalDirectories setting only grants file access and does not load skills.
Names are always loaded, but descriptions are truncated when there are many, which may strip away the keywords that CodeBuddy uses to determine whether a skill applies. Keep descriptions short and start with words that a request would contain, such as "Write or modify tests in packages/api/".
For skills shared across many directories, such as PR conventions or deployment checklists, place them in .codebuddy/skills/ at the repository root so that they can be loaded from any launch directory. When shared skills need their own version history or must work across repositories, package them as plugins instead. Plugin skills use the plugin-name:skill-name namespace, so they never conflict with directory-based skills. Platform teams can version and update them in one place.

Centralizing Conventions When Layering Stops Scaling

As a codebase grows, per-directory CODEBUDDY.md files can become difficult to manage. Conventions drift, files become stale, and no one owns the root directory. Solving this problem typically falls to the team that maintains the repository's CodeBuddy Code settings, rather than to each developer working in their own area.
Move conventions and reference content out of the always-loaded CODEBUDDY.md into on-demand loading mechanisms:
Skills: reference material that CodeBuddy loads only when relevant to the task
Plugins: versioned packages of skills, hooks, and commands that platform teams own centrally
MCP servers: If your organization already runs code search or RAG indexing over repositories, expose it as an MCP tool so that CodeBuddy can query it instead of reading files directly.

Recommending the Right Plugins at Session Startup

Once conventions live in plugins, teammates who start CodeBuddy in unfamiliar parts of the tree have no signal about which plugin the owner of that area maintains. The SessionStart hook can bridge this gap, because anything the hook prints to stdout is added to CodeBuddy's context before the first prompt.
For example, you can write a script that reads the launch directory from the hook input, looks it up in a path-to-plugin mapping committed to the repository, and prints a suggestion for CodeBuddy to relay in its first reply. See Automating with hooks to write and register hooks.

Putting It All Together

The combined configuration below uses a monorepo layout. The same files apply to any subdirectory in a large single tree. Project settings are loaded only from the directory where you launch CodeBuddy, so the .codebuddy/settings.json in each subdirectory must be self-contained rather than layered on top of the root file.
The example commits the worktree, additionalDirectories, and Read deny rules in .codebuddy/settings.json so that every developer in packages/api/ gets the same sibling access, sparse paths, and exclusions. The following file is the committed per-area settings for packages/api/:
// packages/api/.codebuddy/settings.json
{
"worktree": {
"sparsePaths": [
".codebuddy",
"packages/api",
"packages/shared"
],
"symlinkDirectories": [
"node_modules"
]
},
"permissions": {
"additionalDirectories": [
"../shared"
],
"deny": [
"Read(./**/dist/**)",
"Read(./**/build/**)"
]
}
}
Because this session is launched from packages/api/, the CODEBUDDY.md files of sibling packages are already out of scope. If you also launch sessions from the repository root, add the exclusion rules to .codebuddy/settings.local.json at the repository root.
The additionalDirectories entries apply when you launch CodeBuddy directly from packages/api/. Inside a worktree created from this session, the working directory is the worktree root, so this settings file is not loaded. Sibling packages are already reachable within the worktree without it, but the deny rules need a second copy in .codebuddy/settings.json at the repository root so that worktree sessions can obtain them, as described in the worktree settings note:
// .codebuddy/settings.json
{
"permissions": {
"deny": [
"Read(./**/dist/**)",
"Read(./**/build/**)"
]
}
}
After setup, the repository has this layout:
monorepo/
CODEBUDDY.md
.codebuddy/settings.json # Deny rules for worktree sessions
packages/
api/
CODEBUDDY.md
.codebuddy/settings.json # worktree, additionalDirectories, and deny rules
.codebuddy/skills/api-testing/SKILL.md
web/
CODEBUDDY.md
.codebuddy/skills/component-patterns/SKILL.md
shared/
CODEBUDDY.md
With this setup, launch CodeBuddy from packages/api/:
Load the root CODEBUDDY.md and packages/api/CODEBUDDY.md, and skip packages/web/CODEBUDDY.md.
Can read and edit files in packages/api/ and packages/shared/.
Skip reading build output under dist/ and build/ in packages/api/.
An api-testing skill is available on demand.
Create worktrees that include .codebuddy/, packages/api/, packages/shared/, and root-level files, and apply the deny rules from the root settings file to the entire worktree.

Scoping and Planning Changes Across Packages

The configuration above controls what CodeBuddy sees. When a single change spans multiple packages, such as updating a shared type and every call site that uses it, how you scope and sequence tasks also affects the outcome.
Two techniques help maintain consistency across cross-package changes:
Give CodeBuddy the entire change in one session: deliver the shared edit and its call sites together to keep the decisions behind each edit consistent, rather than re-deriving them package by package.
Save the plan to a file before editing: plan first and ask CodeBuddy to write the plan to a markdown file in the repository. Long cross-package sessions compress their context as they progress, and a saved plan survives where conversation history may not.

Following Steps

Once this configuration is in place, you can refine it:
Use hooks to run per-directory linters or type checkers after CodeBuddy edits files.
See Managing costs effectively to learn how codebase size affects token usage and how to set spending limits before a broader rollout.


Help and Support

Was this page helpful?

Help us improve! Rate your documentation experience in 5 mins.

Feedback