# How to Exclude Specific Files or Patterns from Dead Code Analysis

> Learn how to exclude specific files or patterns from dead code analysis using the cgr dead-code --exclude flag. Filter unwanted symbols from your reports effectively.

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

---

**The `cgr dead-code` command supports the `--exclude` flag, which accepts glob patterns that are matched against repository-relative file paths using Python's `fnmatch` module to filter out unwanted symbols from the final report.**

The `cgr dead-code` command in the `vitali87/code-graph-rag` repository identifies unreachable functions, methods, and classes by traversing a call-graph built from your source tree. When generated protobuf files, vendored dependencies, or test utilities clutter your dead code reports, you need precise control over exclusions. This guide explains how to use file-path glob exclusions to remove specific patterns from analysis after the reachability walk completes.

## How File Exclusion Works in the Dead Code Engine

The exclusion mechanism operates in two distinct layers: CLI argument parsing and post-processing filtration.

### CLI Layer and Configuration

When you invoke `cgr dead-code`, the `--exclude` flag can be specified multiple times. Each value is stored in the `DeadCodeConfig` dataclass via the `default_dead_code_config` factory function. According to the source in [`codebase_rag/dead_code.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/dead_code.py) (lines 44-52), the function accepts `exclude_patterns` as a tuple of glob strings and initializes the configuration object that the engine consumes.

### Engine Layer Filtering

After the reachability analysis identifies candidate dead symbols, the `dead_code_from_graph` function (implemented in [`codebase_rag/dead_code.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/dead_code.py), lines 792-800) applies the exclusion patterns. The engine retrieves each symbol's repository-relative path using `props_by_qn[qn].get(cs.KEY_PATH)` and tests it against every configured pattern using `fnmatch`:

```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
        )
    }

```

Only symbols whose paths fail to match all patterns remain in the final dead code set.

## Best Practices for Writing Glob Patterns

Effective exclusion requires careful pattern construction to avoid unintended matches:

- **Quote your patterns**: Always wrap arguments in single quotes to prevent shell expansion of wildcards before they reach the CLI parser in [`codebase_rag/cli.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/cli.py).
- **Match full repository-relative paths**: Patterns are tested against the complete path from the repository root (e.g., [`src/client/core/api.py`](https://github.com/vitali87/code-graph-rag/blob/main/src/client/core/api.py)), not just filenames.
- **Use directory wildcards carefully**: The `*` character matches across directory separators, so `*/tests/*` captures nested test directories without matching [`contests.py`](https://github.com/vitali87/code-graph-rag/blob/main/contests.py) in production code.
- **Avoid overly broad matches**: A pattern like `*test*` might inadvertently exclude [`contest_entry.py`](https://github.com/vitali87/code-graph-rag/blob/main/contest_entry.py) or [`testing_utils.py`](https://github.com/vitali87/code-graph-rag/blob/main/testing_utils.py) in production source directories.

## Practical Examples

### Excluding Generated and Vendored Code via CLI

To exclude generated client stubs and protobuf files from the dead code report:

```bash

# Exclude generated client code and any file containing ".gen."

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

# Exclude a particular auto-generated protobuf stub

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

# Combine with CI-friendly fail-on-found and JSON output

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

```

### Programmatic Configuration in Python

For custom scripts consuming the dead code engine directly, build a `DeadCodeConfig` programmatically:

```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')
)

# Execute analysis with custom config

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

```

## Summary

- The `--exclude` flag accepts glob patterns that filter symbols after reachability analysis completes in `dead_code_from_graph`.
- Patterns are matched against repository-relative file paths using `fnmatch` against the value stored under `cs.KEY_PATH`.
- Multiple exclusions are supported by repeating the flag or passing a tuple to `default_dead_code_config`.
- Always quote patterns to prevent shell interference and target full paths rather than simple suffixes.
- The exclusion logic resides in [`codebase_rag/dead_code.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/dead_code.py) within the `DeadCodeConfig` class and the filtering block at lines 792-800.

## Frequently Asked Questions

### How do I exclude multiple patterns in a single command?

Repeat the `--exclude` flag for each pattern. For example: `cgr dead-code --exclude '*tests/*' --exclude '*vendor/*'`. The CLI aggregates these into the `exclude_patterns` tuple consumed by the engine.

### Are exclusion patterns applied before or after reachability analysis?

Patterns are applied **after** the reachability walk completes. The engine first identifies all unreachable symbols, then filters out those matching your exclusion globs before generating the report. This ensures exclusions do not affect the call-graph construction.

### Why are my exclusion patterns not matching any files?

Ensure you are matching the **full repository-relative path** rather than just filenames. For a file at [`src/utils/helpers.py`](https://github.com/vitali87/code-graph-rag/blob/main/src/utils/helpers.py), the pattern [`helpers.py`](https://github.com/vitali87/code-graph-rag/blob/main/helpers.py) will not match, but `*helpers.py` or [`src/utils/helpers.py`](https://github.com/vitali87/code-graph-rag/blob/main/src/utils/helpers.py) will. Also verify that you have quoted the pattern to prevent shell glob expansion.

### Does the engine support regex patterns instead of globs?

No, the engine specifically uses Python's `fnmatch.fnmatch` function (as seen in [`codebase_rag/dead_code.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/dead_code.py) line 797), which supports Unix shell-style wildcards only. For complex exclusions, combine multiple glob patterns or preprocess your source list before invoking the engine.