# How to Exclude Specific Files or Patterns from Dead Code Analysis in Code-Graph-RAG

> Exclude files and patterns from dead code analysis using the cgr dead-code --exclude flag. Filter generated, vendored, or test files from your reachability analysis.

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

---

**Use the `--exclude` flag with glob patterns when running `cgr dead-code` to filter out generated, vendored, or test files from the reachability analysis.**

The `cgr dead-code` command in the `vitali87/code-graph-rag` repository identifies unreachable functions and methods by walking a call graph built from your source tree. When generated protobuf stubs, vendored dependencies, or auto-generated client code appear in the dead code report, you can suppress them using path-based glob exclusions that filter symbols after the reachability walk completes.

## How the Exclusion Filter Works

The exclusion mechanism operates at two distinct layers to ensure matching symbols never appear in the final dead code list.

### CLI Layer: The --exclude Flag

When invoking `cgr dead-code` from the terminal, pass the `--exclude` flag multiple times to supply one or more glob patterns. Each pattern is matched against the **repo-relative file path** of symbols (for example, [`src/client/core/api.py`](https://github.com/vitali87/code-graph-rag/blob/main/src/client/core/api.py)).

According to the source code in [`codebase_rag/cli.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/cli.py), these patterns are collected and passed to `default_dead_code_config(..., exclude_patterns=tuple(...))`, which instantiates a `DeadCodeConfig` dataclass. This configuration object stores the exclusion patterns in its `exclude_patterns` field (`codebase_rag/dead_code.py:44-52`).

### Engine Layer: Filtering in dead_code_from_graph

After the reachability walk identifies candidate dead symbols, the `dead_code_from_graph` function applies the exclusion filter. The implementation in `codebase_rag/dead_code.py:792-800` uses `fnmatch` to test each symbol's file path against the configured patterns:

```python
if config.exclude_patterns:
    dead = {
        qn
        for qn in dead
        if not any(
            fnmatch(str(props_by_qn[qn].get(cs.KEY_PATH) or ""), pattern)
            for pattern in config.exclude_patterns
        )
    }

```

This logic discards any symbol whose repo-relative path matches at least one exclusion glob, ensuring the final report contains only relevant dead code.

## Writing Effective Glob Patterns

To avoid accidentally excluding production code or failing to match target files, follow these pattern-writing guidelines:

- **Quote the glob** to prevent shell expansion before `cgr` receives the argument.
- **Match the full path** because patterns are tested against the complete repo-relative path. Use `'tests/*'` or `'src/tests/*'` rather than just `'tests'`.
- **Place wildcards around directories** since `*` spans directory separators. The pattern `'*/tests/*'` captures nested test directories without matching production paths like [`contests/entry.py`](https://github.com/vitali87/code-graph-rag/blob/main/contests/entry.py).
- **Be specific** with your globs; broad patterns like `'*tests*'` risk excluding legitimate files such as [`contests/entry.py`](https://github.com/vitali87/code-graph-rag/blob/main/contests/entry.py) if they appear in non-test directories.

## Practical Examples

Exclude generated client code and files containing `.gen.` in the name:

```bash
cgr dead-code \
  --exclude '*client/core*' \
  --exclude '*.gen.*'

```

Exclude a specific auto-generated protobuf stub file:

```bash
cgr dead-code --exclude 'src/protos/generated_pb2.py'

```

Combine exclusions with CI-friendly JSON output and failure flags:

```bash
cgr dead-code \
  --format json \
  --output dead-code.json \
  --fail-on-found \
  --exclude '*_generated*'

```

For programmatic usage, build a `DeadCodeConfig` directly in Python:

```python
from codebase_rag.dead_code import default_dead_code_config, dead_code_from_graph

# Configure exclusions for vendor directories and generated files

config = default_dead_code_config(
    include_tests=True,
    include_classes=False,
    exclude_patterns=('*vendor/*', '*_generated.py')
)

# Analyze the graph (nodes and rels loaded previously)

dead_qns = dead_code_from_graph(nodes, rels, prefix, config)

```

## Summary

- The `cgr dead-code` command supports file exclusion via the `--exclude` flag using standard glob syntax.
- Exclusion patterns are stored in the `exclude_patterns` field of the `DeadCodeConfig` class defined in [`codebase_rag/dead_code.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/dead_code.py).
- Filtering occurs after the reachability analysis in `dead_code_from_graph`, removing matches from the final dead symbol set.
- Patterns must match the full repo-relative file path; use wildcards like `*/tests/*` to target specific directory structures.
- Always quote glob patterns in shell commands to prevent premature expansion.

## Frequently Asked Questions

### Can I use multiple --exclude flags in a single command?

Yes. The CLI accepts multiple `--exclude` arguments, which are collected into a tuple and passed to the configuration. For example: `cgr dead-code --exclude '*tests/*' --exclude '*vendor/*'`.

### Do exclusion patterns support regular expressions?

No. The engine uses Python's `fnmatch` module, which supports Unix shell-style wildcards (`*`, `?`, `[seq]`), not full regular expressions. Patterns are matched against the repo-relative file path strings.

### When in the analysis process are exclusions applied?

Exclusions are applied **after** the reachability walk completes but **before** the final report is generated. This means excluded files are still parsed and included in the call graph; they are simply filtered from the dead code output. This ensures that calls from excluded files to production code are still considered during reachability analysis.

### How do I exclude an entire directory like `node_modules` or `vendor`?

Use a glob pattern that matches the directory contents, such as `'*vendor/*'` or `*/node_modules/*'`. Remember that the pattern must match the full repo-relative path, so including wildcards on both sides of the directory name ensures you capture files at any nesting level within that directory.