How to Exclude Specific Files or Patterns from Dead Code Analysis

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 (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, 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:

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.
  • Match full repository-relative paths: Patterns are tested against the complete path from the repository root (e.g., 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 in production code.
  • Avoid overly broad matches: A pattern like *test* might inadvertently exclude contest_entry.py or 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:


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

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 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, the pattern helpers.py will not match, but *helpers.py or 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 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.

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 →