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

> Specify entry points for dead code detection in Code Graph RAG by populating the entry_points tuple in DeadCodeConfig. Learn how this enables accurate reachable symbol identification.

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

---

**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`](https://github.com/vitali87/code-graph-rag/blob/main/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)](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/dead_code.py)](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/dead_code.py#L50-L51).

```python
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)](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/cli.py).

```bash

# 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`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/types_defs.py) and utilized in [`codebase_rag/dead_code.py`](https://github.com/vitali87/code-graph-rag/blob/main/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)](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.