# How Dead Code Detection Works Using Call Graph Degree Filtering in Codebase Memory

> Learn how Codebase Memory detects dead code by filtering call graphs using degree lookup. Discover efficient codebase memory management techniques.

- Repository: [Martin Vogel/codebase-memory-mcp](https://github.com/DeusData/codebase-memory-mcp)
- Tags: deep-dive
- Published: 2026-07-08

---

**Codebase Memory identifies dead code by filtering the call graph for functions that have zero incoming CALLS edges and zero incoming USAGE edges, using a scalable two-stage batch degree lookup system.**

Codebase Memory, the graph analysis engine from the DeusData/codebase-memory-mcp repository, provides automated dead code detection by analyzing function relationships within the complete call graph topology. The system classifies functions as dead when they lack both caller relationships and usage references, enabling developers to identify truly unused code across entire codebases without sampling.

## What Defines Dead Code in Codebase Memory

Codebase Memory applies a strict topological definition to identify dead code. A node representing a function or method receives the **"dead"** status classification only when it satisfies two simultaneous conditions: it has **no incoming CALLS edges** and **no incoming USAGE edges**.

This definition ensures that functions referenced by configuration files, reflection systems, or documentation (captured via USAGE edges) are not falsely flagged as dead, even if they lack explicit caller relationships. The system specifically excludes non-function nodes from dead code analysis, assigning them the **"structural"** status instead.

## How the Two-Stage Detection Process Works

The dead code detection mechanism operates through a high-performance pipeline that performs batch degree lookups followed by classification logic. This architecture allows the system to analyze the full graph—spanning potentially millions of nodes—without loading the entire structure into memory.

### Stage 1: Batch Degree Lookups with cbm_store_batch_count_degrees

The detection process begins in [`src/store/store.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/store/store.c) with the `cbm_store_batch_count_degrees` function. This C function executes parameterized bulk queries against the graph store to count inbound relationships:

```c
/* src/store/store.c – batch query that returns in‑ and out‑degree counts */
int cbm_store_batch_count_degrees(cbm_store_t *s,
                                    const int64_t *node_ids,
                                    int id_count,
                                    const char *edge_type,
                                    int *out_in,
                                    int *out_out);

```

The function constructs a parameterized `IN` clause (`(?,?,…)`) and invokes the helper `count_degrees_direction` twice—once for inbound relationships (`true`) and once for outbound relationships (`false`). According to the source code in [`src/store/store.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/store/store.c) (lines 2099-2139), this writes the degree counts into the caller-provided arrays.

For dead code detection, the UI layer invokes this function twice per node batch: once with the edge type `"CALLS"` and once with `"USAGE"`, capturing the precise inbound degree counts needed for the classification decision.

### Stage 2: Classification Logic in the UI Layer

After retrieving the batch degree data, the classification logic in [`src/ui/layout3d.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/ui/layout3d.c) (lines 4450-4470) iterates over the nodes and applies the dead code criteria:

```c
/* src/ui/layout3d.c – node classification based on degree counts */
int ic = in_calls ? in_calls[i] : 1;   // inbound CALLS
int iu = in_usage ? in_usage[i] : 1;   // inbound USAGE
const char *status;
if (!is_fn)                status = "structural";
else if (testish)          status = "test";
else if (nf.is_entry ||
         nf.is_route)     status = "entry";
else if (nf.is_exported)   status = "exported";
else if (ic == 0 && iu == 0) status = "dead";   // ← dead‑code case
else if (ic == 1)          status = "single";
else                       status = "normal";

```

The logic first filters out non-function nodes, then checks for test functions, entry points, and exported symbols. **Only when both `ic` (inbound CALLS) and `iu` (inbound USAGE) equal zero does the node receive the `"dead"` label**, as implemented in the DeusData/codebase-memory-mcp source code.

## Implementing Dead Code Detection in Practice

Developers can access dead code detection through multiple interfaces: the command-line query interface, the C API for programmatic integration, or the 3D visualization UI.

### Querying Dead Code via CLI

The Cypher query interface translates degree filters into the underlying batch API. To list all functions classified as dead:

```bash

# List all functions that are dead (no callers and no usage)

cbm query "MATCH (n:Function) WHERE n.in_degree = 0 AND n.usage_in_degree = 0 RETURN n"

```

The Cypher parser in [`src/cypher/cypher.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/cypher/cypher.c) (lines 2109-2115) maps `in_degree = 0` to a `"CALLS"` inbound-degree filter and `usage_in_degree = 0` to a `"USAGE"` inbound-degree filter, which the UI later visualizes with the `"dead"` status indicator.

### Programmatic Access Using the C API

For custom analysis tools, the `cbm_store_batch_count_degrees` function provides direct access to the degree data required for dead code identification:

```c
int64_t ids[3] = {42, 73, 101};
int in_calls[3], in_usage[3];
cbm_store_batch_count_degrees(store, ids, 3,
                              "CALLS", in_calls, NULL);
cbm_store_batch_count_degrees(store, ids, 3,
                              "USAGE", in_usage, NULL);

/* nodes with both counts == 0 are dead */
for (int i = 0; i < 3; ++i) {
    if (in_calls[i] == 0 && in_usage[i] == 0)
        printf("Node %lld is dead code\n", ids[i]);
}

```

This approach retrieves the precise inbound-degree information from the full call graph, not just sampled subsets used for layout calculations.

### Visualizing Dead Code in the UI

When the 3D layout engine renders the graph, each node carries the `status` field determined by the classification logic. The renderer draws dead nodes in a distinctive color (typically red) and displays the `"dead"` label in tooltips, making it immediately visible which functions lack both callers and usage references.

## Summary

- **Dead code definition**: Codebase Memory flags functions with zero incoming CALLS edges and zero incoming USAGE edges as dead.
- **Batch processing**: The `cbm_store_batch_count_degrees` function in [`src/store/store.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/store/store.c) performs efficient bulk degree queries using parameterized SQL `IN` clauses.
- **Classification logic**: The UI layer in [`src/ui/layout3d.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/ui/layout3d.c) applies the dead code check only after filtering out tests, entry points, and exported symbols.
- **Full graph analysis**: Unlike layout sampling, dead code detection scans the complete call graph to ensure accurate identification of unused functions.
- **Multiple interfaces**: Developers can query dead code via Cypher CLI commands, the C API, or interactive 3D visualization.

## Frequently Asked Questions

### What is the difference between CALLS and USAGE edges in dead code detection?

**CALLS edges represent explicit function invocations**, while **USAGE edges track implicit references** such as configuration file mentions, documentation references, or reflection usage. A function with zero CALLS edges but positive USAGE edges is not considered dead because external systems or documentation may still depend on it.

### How does Codebase Memory handle batch queries for large codebases?

The `cbm_store_batch_count_degrees` function in [`src/store/store.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/store/store.c) uses parameterized `IN` clauses to query multiple nodes in a single database round-trip. This batching approach scales to millions of nodes by avoiding individual queries and processing degree counts in memory-efficient arrays.

### Can dead code detection identify unused structs or classes?

No. According to the classification logic in [`src/ui/layout3d.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/ui/layout3d.c), non-function nodes automatically receive the **"structural"** status regardless of their degree counts. The dead code detection specifically targets functions and methods, as these represent executable code paths that can be safely removed when unused.

### Where can I find test cases for dead code detection?

The test suite includes reproduction cases in [`tests/repro/repro_issue627.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/tests/repro/repro_issue627.c) (lines 58-108), which verifies that functions with no incoming callers are correctly identified and returned as dead code. This file demonstrates the expected behavior of the detection algorithm on synthetic graph data.