.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:

  1. Built-in skip list – Hard-coded directories such as .git, node_modules, dist, and target that cannot be overridden by any configuration file.
  2. Repository-wide .gitignore – The file at the repository root (<repo>/.gitignore) combined with Git’s info/exclude. Later patterns in this file override earlier ones on conflict.
  3. Nested .gitignore files – Any .gitignore found in subdirectories, applied relative to their containing directory.
  4. .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).
  5. 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.sql can 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 .gitignore or nested .gitignore files (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

  • .cbmignore evaluates 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 .cbmignore add new exclusions beyond what Git ignores define.
  • Negated patterns (!) only rescue files from global Git excludes (layer 5), not from repository .gitignore rules (layers 2-3).
  • The hierarchy is implemented in src/discover/discover.c and documented in docs/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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →