# How to Use Ignore Patterns to Exclude Files and Directories from Code‑Graph‑RAG Analysis

> Master Code-Graph-RAG ignore patterns to exclude files and directories. Learn to filter out build artifacts and environments for cleaner code analysis.

- Repository: [Vitali Avagyan/code-graph-rag](https://github.com/vitali87/code-graph-rag)
- Tags: how-to-guide
- Published: 2026-08-15

---

**Code‑Graph‑RAG uses a layered ignore system—built‑in patterns, `.cgrignore` files, `.gitignore` inheritance, and CLI flags—to filter out build artifacts, virtual environments, and other non‑source content before building the code graph.**

The **code‑graph‑rag** repository implements a Git‑compatible ignore mechanism that prevents noisy files from polluting your retrieval‑augmented generation (RAG) graph. Understanding how to configure these patterns gives you precise control over what gets indexed and what gets skipped.

## Core Components of Code‑Graph‑RAG Ignore Patterns

### Built‑in IGNORE_PATTERNS in constants/languages.py

The foundation of CGR's filtering system is a frozen set of directory names, file suffixes, and glob patterns defined in **[`codebase_rag/constants/languages.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/constants/languages.py)**. This constant—`IGNORE_PATTERNS`—includes standard exclusions like:

- `.git`, `.hg`, `.svn`
- `node_modules`, `__pycache__`, `.pytest_cache`
- `venv`, `.venv`, `env`, `.tox`
- `build`, `dist`, `target`, `out`

These patterns are applied automatically to every repository walk. The file also defines **`IGNORE_SUFFIXES`** for file extensions that should never be parsed.

### Git‑Wildmatch Pattern Matching in path_utils.py

The actual matching logic resides in **[`codebase_rag/utils/path_utils.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/utils/path_utils.py)**. Key functions include:

- **`compiled_ignore_spec(patterns)`** – Compiles a list of patterns into a `PathSpec` using `GITWILDMATCH_STYLE`, giving you full Git‑ignore semantics
- **`matches_ignore_patterns(path, spec)`** – Tests whether a specific path matches any pattern in the compiled spec
- **`should_skip_path(path, repo_root, compiled_spec, unignore_spec)`** – The primary gatekeeper used during directory traversal

The `should_skip_path` function (lines 111–124) applies checks in order: file suffix filtering, repository root containment, ignore pattern matching, and finally unignore pattern evaluation.

### Unignore Support for Selective Inclusions

CGR supports **unignore patterns** prefixed with `!`. These are handled separately:

- Stored in **`unignore_paths`** list
- Evaluated by **`unignore_could_match_within(path, unignore_paths)`** to determine if a directory should be kept (because an unignore might match a descendant)

This ensures that ignored directories aren't pruned prematurely when they contain files you explicitly want to keep.

## Configuration Methods for Ignore Patterns

### Method 1: Project‑Level .cgrignore Files

Create a `.cgrignore` file at your repository root with Git‑ignore syntax:

```gitignore

# Ignore generated documentation

docs/_build/
site/

# Ignore local configuration but keep example

config/local.yml
!config/local.example.yml

# Ignore all log files

*.log

```

CGR automatically discovers and loads `.cgrignore` during ingestion. If no `.cgrignore` exists, CGR falls back to the repository's **`.gitignore`** file.

### Method 2: CLI --exclude Flag

Pass patterns directly via command line in **[`codebase_rag/cli.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/cli.py)**:

```bash
cgr ingest \
  --repo /path/to/project \
  --exclude "tmp,cache,__pycache__" \
  --output graph.json

```

The `--exclude` value is parsed as comma‑separated patterns and merged into the active ignore set before graph construction begins.

### Method 3: Environment Variable CGR_IGNORE_DIRS

As demonstrated in **[`realtime_updater.py`](https://github.com/vitali87/code-graph-rag/blob/main/realtime_updater.py)**, you can set patterns via environment:

```bash
export CGR_IGNORE_DIRS="node_modules,dist,coverage"
cgr ingest --repo /path/to/project

```

The updater forwards `CGR_IGNORE_DIRS_ENV` to subprocesses, ensuring consistent ignore behavior across incremental updates.

### Method 4: Programmatic Modification

For custom scripts or tests, modify the constants directly:

```python
from codebase_rag.constants import languages as cs

# Add custom patterns to the built‑in set

cs.IGNORE_PATTERNS = cs.IGNORE_PATTERNS | {"my_temp_dir", "*.generated.py"}
cs.IGNORE_SUFFIXES = cs.IGNORE_SUFFIXES | {".tmp", ".bak"}

```

This pattern appears in the CGR test suite for scenario‑specific filtering.

## Practical Code Examples

### Checking Whether a Path Would Be Skipped

```python
from pathlib import Path
from codebase_rag.utils.path_utils import (
    compiled_ignore_spec,
    should_skip_path
)
from codebase_rag.constants.languages import IGNORE_PATTERNS

# Compile the default ignore patterns

spec = compiled_ignore_spec(IGNORE_PATTERNS)

repo_root = Path("/home/user/myproject")

# Test a specific path

test_path = Path("/home/user/myproject/node_modules/lodash/index.js")
would_skip = should_skip_path(test_path, repo_root, spec, None)
print(f"Would skip {test_path}: {would_skip}")  # True

```

### Creating a Custom Ignore Spec with Unignore Rules

```python
from pathlib import Path
from codebase_rag.utils.path_utils import compiled_ignore_spec

# Mix ignore and unignore patterns

raw_patterns = [
    "build/",           # Ignore build directory

    "!build/release/",  # But keep release subdirectory

    "*.min.js",         # Ignore minified JS

    "!vendor/",         # Exception: keep vendor folder

]

spec = compiled_ignore_spec(raw_patterns)

# Test matching

from pathspec import PathSpec
match = spec.match_file("build/release/app.js")  # True (unignore works)

match = spec.match_file("build/debug/app.js")    # False (still ignored)

```

### Loading and Merging Multiple Ignore Sources

```python
from pathlib import Path
from codebase_rag.utils.path_utils import load_ignore_patterns

# Prioritized loading: .cgrignore first, then .gitignore

patterns = load_ignore_patterns(
    repo_path=Path("/path/to/repo"),
    prefer_cgrignore=True
)

# Returns list of patterns found, ready for compilation

```

## How Directory Pruning Works

The function **`should_keep_dir(path, unignore_paths)`** (in [`path_utils.py`](https://github.com/vitali87/code-graph-rag/blob/main/path_utils.py)) optimizes traversal by pruning entire directories when safe. A directory is pruned only when:

1. Its name matches an ignore pattern, **and**
2. No unignore pattern could possibly match any descendant

This prevents the expense of walking into `node_modules` or `__pycache__` while still respecting selective unignore rules that might target nested files.

## Summary

- **`IGNORE_PATTERNS`** in [`constants/languages.py`](https://github.com/vitali87/code-graph-rag/blob/main/constants/languages.py) provides the default exclusion set for common build tools and package managers
- **[`path_utils.py`](https://github.com/vitali87/code-graph-rag/blob/main/path_utils.py)** implements Git‑compatible matching via `PathSpec` with `GITWILDMATCH_STYLE`
- **`.cgrignore`** files override defaults with project‑specific rules; **`.gitignore`** serves as automatic fallback
- **`--exclude`** CLI flag and **`CGR_IGNORE_DIRS`** environment variable enable ad‑hoc filtering without file changes
- **Unignore patterns** (`!pattern`) rescue specific files or subdirectories from blanket ignores

## Frequently Asked Questions

### What is the difference between .cgrignore and .gitignore in Code‑Graph‑RAG?

Code‑Graph‑RAG checks for `.cgrignore` first and uses it exclusively if found. Only when `.cgrignore` is absent does CGR fall back to `.gitignore`. This design lets you maintain RAG‑specific exclusions separate from version control rules—for example, ignoring API documentation that exists in Git but shouldn't be embedded in your code graph.

### Can I use glob patterns and negation in my ignore files?

Yes. CGR uses Git's wildmatch specification through the `pathspec` library. You can use `*` for wildcards, `**` for recursive matching, `?` for single characters, and `!` at the start of a line to negate previous patterns. Trailing slashes match directories only. These rules are identical to standard `.gitignore` behavior.

### Why does Code‑Graph‑RAG still index some files in an ignored directory?

This occurs when you have an **unignore pattern** targeting specific files or subdirectories. CGR's `should_keep_dir` function detects whether any unignore could match a descendant; if so, it keeps the directory open for traversal. Check your `.cgrignore` or `.gitignore` for lines starting with `!` that might be resurrecting content you intended to exclude.