# What Is the .cbmignore File and How Does It Interact With .gitignore?

> Learn about the .cbmignore file and its interaction with .gitignore. Exclude files from indexing using gitignore-style syntax after .gitignore rules are applied.

- Repository: [Martin Vogel/codebase-memory-mcp](https://github.com/DeusData/codebase-memory-mcp)
- Tags: how-to-guide
- Published: 2026-07-28

---

**The `.cbmignore` file is a root-level configuration file used by the Codebase Memory MCP (CBM) indexer to exclude specific files and directories from indexing, applying gitignore-style syntax after the repository's `.gitignore` rules have already been processed.**

The `.cbmignore` file serves as a dedicated filter for the CBM indexing pipeline in the `DeusData/codebase-memory-mcp` repository. While `.gitignore` controls version control, `.cbmignore` specifically manages which files appear in the codebase memory graph, allowing teams to exclude generated assets, private notes, or large binaries from AI indexing without altering Git behavior.

## Understanding the .cbmignore File

### Location and Syntax Requirements

The `.cbmignore` file must reside at the **root of the indexed repository** (`<repo>/.cbmignore`). Unlike `.gitignore`, the CBM indexer **does not recognize nested `.cbmignore` files**—only the root-level file is read and applied.

The syntax follows standard **gitignore patterns** as documented in [`docs/cbmignore.md`](https://github.com/DeusData/codebase-memory-mcp/blob/main/docs/cbmignore.md):

- Wildcards (`*`, `?`) for pattern matching
- Double asterisks (`**`) for recursive directory matching
- Negation with `!` to re-include paths
- Directory markers with trailing slashes

```text

# .cbmignore

# Exclude all protobuf generated files

*.pb.go

# Exclude specific directories

/third_party/
build/

# Negate to include specific files

!important.proto

```

### Purpose Compared to .gitignore

While both files use identical pattern syntax, they serve different tooling ecosystems:

| Aspect | `.gitignore` | `.cbmignore` |
|--------|--------------|--------------|
| **Consumer** | Git version control | CBM indexer (`index_repository`) |
| **Effect** | Determines untracked files | Determines indexed files in memory graph |
| **Location** | Any directory (nested supported) | Repository root only |
| **Git impact** | Directly affects commits | No effect on Git operations |

## How .cbmignore Interacts With .gitignore

The CBM indexer implements a **fixed five-layer precedence chain** when discovering files. Understanding this hierarchy is critical because `.cbmignore` cannot override exclusions set by earlier layers.

### The Five-Layer Precedence Chain

According to the implementation in the `ignore` package (see `IgnorePredicate` logic), the indexer applies rules in this order:

1. **Built-in skip list** — Hardcoded exclusions like `.git/`, `node_modules/`, and `dist/` that cannot be overridden by any configuration
2. **Repository `.gitignore`** — Merged with `.git/info/exclude` and applied early
3. **Nested `.gitignore` files** — Scoped to their respective subdirectories
4. **`.cbmignore`** — Applied after all Git-related ignore rules
5. **Git global excludes** — From `core.excludesFile` configuration

**Critical implication**: Because `.cbmignore` sits at layer 4, it can only exclude *additional* files or negate exclusions from layer 5 (global git excludes). It **cannot** rescue files excluded by the repository's own `.gitignore` (layer 2) or the built-in skip list (layer 1).

### Negation Limitations and Parent Directory Exclusions

Negation patterns (`!`) in `.cbmignore` face specific constraints. You cannot re-include a file if its **parent directory was excluded by an earlier layer**, because the indexer walk never descends into that directory path.

For example, if `.gitignore` contains `tmp/`, adding `!tmp/keep.txt` to `.cbmignore` will not index the file—the directory was already pruned at layer 2. However, if the exclusion came from a global git ignore (layer 5), the `.cbmignore` negation would work.

To rescue files from `.cbmignore` itself, you must negate the directory before the file:

```text

# .cbmignore

tmp/          # Excludes the directory

!tmp/         # Re-includes the directory

tmp/keep.txt  # Now this specific file is indexed

```

## Practical Configuration Examples

### Excluding Files Beyond .gitignore

When you need to hide files from the indexer but not from Git:

```text

# .gitignore

build/        # Git ignores build artifacts

# .cbmignore

build/        # Also exclude from indexing (redundant but explicit)

private_notes/ # Exclude from indexing only - Git will still track if desired

```

### Overriding Global Git Excludes

To index files that a developer's global Git configuration might ignore:

```text

# Global ~/.gitconfig

[core]
    excludesFile = ~/.gitignore_global

# ~/.gitignore_global

*.sql

# Repository .cbmignore

!*.sql        # Forces SQL files to be indexed despite global Git ignore

```

### Verifying Exclusions

After configuring `.cbmignore`, run the `index_repository` function and inspect the `excluded` field in the response to verify which paths were filtered at each layer.

## Summary

- **`.cbmignore`** lives only at the repository root and uses gitignore syntax to control CBM indexing.
- The indexer applies a **five-layer precedence chain** where `.cbmignore` (layer 4) runs after `.gitignore` (layer 2) and nested `.gitignore` files (layer 3).
- **Negation patterns** can only override global Git excludes (layer 5), not repository-level Git ignores or built-in skip lists.
- Parent directory exclusions prevent file-level negations from working unless the directory itself is re-included first.
- Full syntax and precedence documentation resides in [`docs/cbmignore.md`](https://github.com/DeusData/codebase-memory-mcp/blob/main/docs/cbmignore.md) within the `DeusData/codebase-memory-mcp` repository.

## Frequently Asked Questions

### Can I have multiple .cbmignore files in different directories?

No. Unlike `.gitignore`, the CBM indexer only reads a single `.cbmignore` file from the repository root. Nested `.cbmignore` files are ignored entirely. Place all indexing exclusion rules in the root file using path patterns like `subdir/*.ext` to target specific directories.

### Why are my negation patterns not working?

Negation (`!`) only works if the exclusion occurred at a later precedence layer. If `.gitignore` (layer 2) excludes a file, `.cbmignore` (layer 4) cannot re-include it. Negations only rescue files excluded by global Git excludes (layer 5) or by earlier patterns within the same `.cbmignore` file itself.

### Does .cbmignore affect git status or commits?

No. The `.cbmignore` file is purely for the CBM indexer and has no effect on Git operations. Files excluded by `.cbmignore` but not by `.gitignore` will still appear in `git status` and can be committed normally.

### What happens if I exclude a parent directory in .cbmignore?

If you exclude a directory in `.cbmignore` (e.g., `tmp/`), you cannot subsequently re-include files inside it using `!tmp/file.txt` because the indexer prunes the directory tree before evaluating file-level patterns. You must first negate the directory exclusion (`!tmp/`) before targeting specific files within it.