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 matchingcontests.pyin production code. - Avoid overly broad matches: A pattern like
*test*might inadvertently excludecontest_entry.pyortesting_utils.pyin 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
--excludeflag accepts glob patterns that filter symbols after reachability analysis completes indead_code_from_graph. - Patterns are matched against repository-relative file paths using
fnmatchagainst the value stored undercs.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.pywithin theDeadCodeConfigclass 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →