How to Specify Entry Points for Dead Code Detection in Code Graph RAG

You specify entry points for dead code detection by populating the entry_points tuple in DeadCodeConfig, which the engine uses to determine reachable symbols during call-graph traversal.

The vitali87/code-graph-rag repository provides a dead-code detection engine that walks the call-graph starting from a set of roots. By default, it considers framework hooks and test symbols as roots, but you can explicitly define custom entry points to ensure your application's legitimate starting points are recognized as reachable code.

How Entry Points Work in the Dead Code Engine

The dead-code engine determines reachability by checking if a symbol's fully-qualified name (QN) is reachable from any root. When a symbol's QN ends with any string listed in config.entry_points, the engine treats it as a reachable root according to the logic in [codebase_rag/dead_code.py at line 691](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/dead_code.py#L691). If a symbol is not reachable from these explicit entry points (or from implicit roots like test functions), it is reported as dead code.

The matching mechanism uses suffix comparison via qn.endswith(entry), meaning your entry point strings can be partial matches rather than fully-qualified names.

Programmatic Configuration

To specify entry points programmatically, construct a DeadCodeConfig instance or modify the configuration returned by default_dead_code_config. The DeadCodeConfig dataclass is defined in [codebase_rag/types_defs.py](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/types_defs.py) and used by the detection engine in [dead_code.py](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/dead_code.py#L50-L51).

from codebase_rag.dead_code import dead_code_from_graph, default_dead_code_config
from codebase_rag.types_defs import DeadCodeConfig

# Start with base configuration, disabling test and class symbols if desired

base_cfg = default_dead_code_config(include_tests=False, include_classes=False)

# Define your custom entry points using fully-qualified names or suffixes

cfg = DeadCodeConfig(
    include_tests=base_cfg.include_tests,
    include_classes=base_cfg.include_classes,
    root_decorators=base_cfg.root_decorators,
    entry_points=("my_app.main", "my_lib.startup"),  # Your entry points here

    test_patterns=base_cfg.test_patterns,
    exclude_patterns=base_cfg.exclude_patterns,
)

# Execute dead-code detection on your ingested graph

dead_symbols = dead_code_from_graph(nodes, rels, project_prefix, cfg)

print("Dead symbols:", dead_symbols)

This approach gives you full control over the configuration object passed to dead_code_from_graph, allowing you to combine custom entry points with other filtering options like exclude_patterns and test_patterns.

CLI Configuration

For command-line usage, the cgr dead-code command accepts an --entry-points flag that injects the specified strings into the DeadCodeConfig before invoking the engine. The CLI parsing logic is implemented in [codebase_rag/cli.py](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/cli.py).


# Detect dead code with custom entry points specified via CLI

cgr dead-code \
    --project-root /path/to/project \
    --entry-points my_app.main my_lib.startup

You can pass multiple entry points as separate arguments to the flag. The CLI aggregates these values into the entry_points tuple used by the detection engine, making this method ideal for CI/CD pipelines and quick analysis without writing Python scripts.

Entry Point Matching Behavior

The dead-code engine matches entry points using suffix comparison rather than exact string equality. When evaluating whether a symbol is a root, the code checks if qn.endswith(entry) returns true for any entry in your configuration.

This design means:

  • Partial matches work: An entry point of "main" matches my_pkg.main, my_pkg.sub.main, and other.main
  • Specificity control: Use fully-qualified names like my_app.main to narrow the match, or generic suffixes like startup for broader application initialization detection
  • No wildcards needed: The suffix matching eliminates the need for glob patterns or regular expressions in most cases

Summary

  • The entry point configuration prevents the dead-code engine from flagging your application's legitimate starting points as unreachable.
  • Set entry points via the entry_points tuple in DeadCodeConfig, defined in codebase_rag/types_defs.py and utilized in codebase_rag/dead_code.py.
  • Programmatic usage involves building a DeadCodeConfig instance and passing it to dead_code_from_graph.
  • CLI usage leverages the --entry-points flag on the cgr dead-code command.
  • The engine uses suffix matching (qn.endswith(entry)), so entry point strings can match any fully-qualified name ending with the specified text.

Frequently Asked Questions

What format should I use for entry point strings?

Entry point strings can be either fully-qualified names (like my_package.main) or simple suffixes (like main). The engine uses qn.endswith(entry) to check for matches, so a suffix of main will match any function whose name ends with .main, regardless of the package path. Choose fully-qualified names for precision, or short suffixes for flexibility across modules.

Can I combine multiple entry points with test detection?

Yes. The entry_points field operates independently of test symbol detection. When you set include_tests=True in your DeadCodeConfig, the engine treats test symbols as additional roots alongside your custom entry points. You can also set include_tests=False and rely solely on your explicit entry points for reachability analysis, which is useful when you only want to analyze production code paths.

How do entry points differ from root decorators?

Entry points (entry_points) identify callable symbols by their fully-qualified names (or suffixes), while root decorators (root_decorators) identify symbols based on their decorator usage. Use entry_points when you know the specific function names that serve as application entry points (like main functions or CLI handlers). Use root_decorators when you want to mark functions with specific decorators (like @app.route or @celery.task) as reachable regardless of whether they are explicitly called.

Where can I find examples of dead code detection configuration?

Reference the evaluation script in [evals/dead_code.py](https://github.com/vitali87/code-graph-rag/blob/main/evals/dead_code.py), which demonstrates Python-based invocation of the dead-code engine with custom configurations. This file shows how to import dead_code_from_graph, configure DeadCodeConfig, and process the results programmatically, complementing the CLI examples found in the repository documentation.

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 →