.cbmignore Precedence Over .gitignore in DeusData: 5-Layer Indexing Hierarchy Explained
In DeusData, .cbmignore is evaluated after the repository .gitignore, meaning repository ignore rules always take priority over project-specific patterns, with negations only able to rescue files from global Git excludes.
The DeusData indexing engine, implemented in the DeusData/codebase-memory-mcp repository, uses a layered ignore system to determine which files enter the codebase memory. Understanding the exact precedence of .cbmignore over .gitignore is critical for configuring what gets indexed without accidentally overriding your version control rules.
The Five-Layer Ignore Hierarchy
DeusData evaluates ignore rules in a strict sequence from highest to lowest priority. When a path matches multiple patterns, the first layer to reject it wins.
The precedence order is:
- Built-in skip list – Hard-coded directories such as
.git,node_modules,dist, andtargetthat cannot be overridden by any configuration file. - Repository-wide
.gitignore– The file at the repository root (<repo>/.gitignore) combined with Git’sinfo/exclude. Later patterns in this file override earlier ones on conflict. - Nested
.gitignorefiles – Any.gitignorefound in subdirectories, applied relative to their containing directory. .cbmignore– The project-specific ignore file at the repository root (<repo>/.cbmignore). Positive matches skip paths, while negated patterns (!) can only rescue paths from the next layer (global Git excludes).- Git global excludes – The file referenced by
core.excludesfile(typically~/.config/git/ignore).
In the implementation at src/discover/discover.c, the discovery walker applies each layer sequentially during the tree traversal [lines 64-84]. According to the .cbmignore documentation in docs/cbmignore.md, this ordering ensures repository-wide .gitignore rules maintain higher authority than .cbmignore rules [lines 66-84].
How .cbmignore Interacts with .gitignore
Because .cbmignore occupies layer 4 while repository .gitignore sits at layer 2, you cannot use .cbmignore to override a file ignored by .gitignore.
Positive patterns in .cbmignore (e.g., *.pb.go) add exclusions beyond what .gitignore defines. However, negated patterns (!pattern) function differently depending on what excluded the file:
- Rescuing from global excludes: A negation like
!important.sqlcan re-include a file that would otherwise be excluded by the global Git excludes (layer 5). - No effect on repository ignores: The same negation cannot rescue a file excluded by the root
.gitignoreor nested.gitignorefiles (layers 2 and 3).
This behavior is documented in the README under the "Ignoring Files" section, which describes the layered evaluation strategy [lines 16-20].
Practical Configuration Examples
Example 1: Repository .gitignore Rules
# .gitignore at repository root
/build/
*.log
Files under build/ and any *.log file are ignored during indexing before .cbmignore is even evaluated.
Example 2: Project-Specific .cbmignore
# .cbmignore at repository root
# Skip generated protobuf files
*.pb.go
# Re-include only if excluded by global Git excludes
!important.sql
Here, *.pb.go adds an extra exclusion not present in .gitignore, while !important.sql only takes effect if the file matches your global Git exclude patterns.
Example 3: Interaction Matrix
Consider this repository structure:
/build/output.bin (matches .gitignore)
src/generated/client.pb.go (matches .cbmignore)
docs/config.sql (matches global Git exclude)
| File | Ignored by .gitignore? |
Ignored by .cbmignore? |
Final Outcome |
|---|---|---|---|
build/output.bin |
Yes (layer 2) | No effect (layer 4) | Skipped |
src/generated/client.pb.go |
No | Yes (positive match) | Skipped |
docs/config.sql |
No | Yes (negation rescues) | Indexed |
Example 4: CLI Verification
# Initialize a test repository
mkdir test-repo && cd test-repo
git init -q
# Create .gitignore
cat > .gitignore <<'EOF'
build/
*.log
EOF
# Create .cbmignore
cat > .cbmignore <<'EOF'
*.pb.go
!secret.sql
EOF
# Generate test files
mkdir -p build src docs
touch build/output.bin src/generated.pb.go docs/secret.sql
# Index with exclusion reporting
codebase-memory-mcp index . --report excluded
This command reports build/output.bin and src/generated.pb.go as excluded. The docs/secret.sql file remains indexed only if it matches a pattern in your global Git excludes that the .cbmignore negation then overrides.
Implementation Details
The discovery logic resides in src/discover/discover.c, where the discovery function walks the repository tree and tests each path against the five ignore layers in sequence. The code explicitly checks built-in skips first, then Git ignore layers, and finally applies .cbmignore patterns before checking global excludes.
Key source files:
docs/cbmignore.md– Complete syntax documentation and precedence rules [lines 66-84].src/discover/discover.c– Core discovery implementation where the layered evaluation occurs [lines 64-84].README.md– High-level overview of the layered ignore strategy [lines 16-20].
Summary
.cbmignoreevaluates after.gitignore, meaning repository Git ignore rules always take precedence.- Built-in skips (
.git,node_modules,dist, etc.) are hard-coded at layer 1 and cannot be overridden by any ignore file. - Positive patterns in
.cbmignoreadd new exclusions beyond what Git ignores define. - Negated patterns (
!) only rescue files from global Git excludes (layer 5), not from repository.gitignorerules (layers 2-3). - The hierarchy is implemented in
src/discover/discover.cand documented indocs/cbmignore.md.
Frequently Asked Questions
Can .cbmignore override .gitignore rules?
No. Because .cbmignore is evaluated at layer 4 while repository .gitignore is layer 2, any file excluded by .gitignore will be skipped regardless of what appears in .cbmignore. The .cbmignore file is designed to supplement ignore rules, not override version control decisions.
What can .cbmignore negation patterns (!) actually do?
Negation patterns in .cbmignore can only re-include files that would be excluded by the global Git excludes file (layer 5), typically configured via core.excludesfile in your Git configuration. If a file is excluded by the repository .gitignore or nested .gitignore files, negation in .cbmignore has no effect.
Where should I place my .cbmignore file?
The .cbmignore file must reside at the repository root (<repo>/.cbmignore). Unlike .gitignore, it does not support nested configuration in subdirectories. All project-specific indexing rules should be defined in this single root-level file.
Which directories are in the built-in skip list?
The built-in skip list includes hard-coded directories such as .git, node_modules, dist, target, and other common build artifact directories. These are evaluated at layer 1 and cannot be overridden by any ignore file pattern, including negations in .cbmignore or .gitignore.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →