Dead Code Detection in Codebase Memory MCP: Knowledge Graph Implementation

The system detects dead code by querying the SQLite knowledge graph for true inbound degrees of CALLS and USAGE edges, classifying functions as "dead" only when both counts equal zero across the entire graph.

Dead code detection in DeusData's codebase-memory-mcp relies on a complete knowledge graph stored in SQLite to accurately identify unused functions. Unlike visual sampling methods that might miss cross-file references, the system performs full-graph degree queries to ensure a symbol truly has zero inbound dependencies before marking it as dead.

How the Knowledge Graph Tracks Symbol Usage

The codebase-memory-mcp stores the entire codebase structure as a graph in a SQLite database. When the 3D layout engine generates visualizations in src/ui/layout3d.c, it does not rely on the sampled edges visible in the current viewport to determine code health. Instead, it queries the underlying store for the true incoming degree of every node.

The system uses two primary edge types to calculate dependency counts:

  • CALLS: Represents function or method invocations
  • USAGE: Represents symbol references and imports

These counts come directly from the store via the cbm_store_batch_count_degrees function implemented in src/store/cbm_store.c, ensuring the classification reflects the complete graph rather than a subset.

The Classification Algorithm for Dead Code Detection

The dead code detection logic executes during layout generation and assigns a status string to each node based on its structural role and connectivity.

Querying True Inbound Degrees

Before classification, the renderer fetches the complete inbound degree counts for batches of nodes. This operation must query the store directly rather than using sampled edge data:

/* True full‑graph incoming degree for dead‑code classification. This MUST
 * come from the store, not the sampled `mapped` edges built above … */
cbm_store_batch_count_degrees(store, node_ids + off, cnt,
                              "CALLS", in_calls + off, deg_dummy + off);
cbm_store_batch_count_degrees(store, node_ids + off, cnt,
                              "USAGE", in_usage + off, deg_dummy + off);

This batch operation populates arrays with the exact number of incoming CALLS and USAGE edges for each node in the batch, guaranteeing that no cross-file or off-screen references are missed.

Status Assignment Logic

After retrieving the degree counts, the system applies a priority-based classification in src/ui/layout3d.c (lines 84-90). The logic checks structural properties first, then dependency counts:

Condition Assigned Status
Not a function/method "structural"
Test file or test-marked "test"
Entry point or route "entry"
Exported symbol "exported"
Both in_calls == 0 and in_usage == 0 "dead"
in_calls == 1 "single"
Otherwise "normal"

The critical check for dead code requires both incoming call and usage counts to equal zero:

if (!is_fn)               status = "structural";
else if (testish)         status = "test";
else if (nf.is_entry)    status = "entry";
else if (nf.is_exported) status = "exported";
else if (ic == 0 && iu == 0) status = "dead";
else if (ic == 1)         status = "single";
else                      status = "normal";

Implementation in layout3d.c

The dead code detection implementation centers on src/ui/layout3d.c, specifically between lines 45-55 and 62-75 where the degree queries execute, and lines 84-90 where the status determination occurs.

By querying cbm_store_batch_count_degrees directly against the SQLite store rather than using the visual window's sampled mapped edges, the system eliminates false positives that could arise from incomplete subgraph views. This ensures that a function is marked "dead" only if it truly has no callers or references anywhere in the codebase.

Exposing Dead Code Data to Consumers

Once classified, the status information flows through the system architecture for downstream consumption. The cbm_layout_node_t structure defined in src/ui/cbm_layout.h holds the status field, which is then serialized to JSON by src/ui/cbm_layout_to_json.c. This allows external tools and IDE integrations to consume dead code information programmatically.

/* Example: fetch full‑graph degrees for a batch of nodes */
int64_t ids[] = { 101, 102, 103 };
int calls[3], usage[3], dummy[3];
cbm_store_batch_count_degrees(store, ids, 3, "CALLS", calls, dummy);
cbm_store_batch_count_degrees(store, ids, 3, "USAGE", usage, dummy);

/* Determine dead‑code status */
for (int i = 0; i < 3; ++i) {
    const char *status = (calls[i] == 0 && usage[i] == 0) ? "dead" : "alive";
    printf("Node %lld is %s\n", (long long)ids[i], status);
}

Summary

  • Full-graph queries via cbm_store_batch_count_degrees in src/store/cbm_store.c provide accurate inbound degree counts for CALLS and USAGE edges.
  • Zero-inbound rule: A function is classified as "dead" in src/ui/layout3d.c only when both in_calls and in_usage equal zero.
  • Priority classification: The system checks structural roles (tests, exports, entry points) before evaluating dependency counts to avoid misclassifying special symbols.
  • JSON serialization through src/ui/cbm_layout_to_json.c makes dead code detection results available to external tools.

Frequently Asked Questions

How does codebase-memory-mcp avoid false positives in dead code detection?

The system queries the complete knowledge graph stored in SQLite using cbm_store_batch_count_degrees rather than relying on sampled edges from the visual viewport. This ensures that cross-file references outside the current view are counted, preventing functions from being incorrectly marked as dead when they have legitimate callers elsewhere in the codebase.

What types of symbols are excluded from dead code classification?

The algorithm in src/ui/layout3d.c excludes non-functions ("structural"), test files ("test"), entry points ("entry"), and exported symbols ("exported") from dead code evaluation. These categories receive special status assignments regardless of their inbound degree counts, as they serve architectural or integration purposes even with zero internal callers.

How can downstream tools access dead code information?

Downstream tools consume dead code data through the JSON serialization layer in src/ui/cbm_layout_to_json.c, which exports the status field defined in src/ui/cbm_layout.h. This field contains string values like "dead", "single", or "normal" that tools can parse to identify unused functions and prioritize refactoring efforts.

What distinguishes "dead" status from "single" status?

A node receives "single" status when it has exactly one incoming call (in_calls == 1), indicating it is used but potentially fragile or tightly coupled. In contrast, "dead" status requires both in_calls and in_usage to equal zero, indicating the function has no inbound dependencies whatsoever and can be safely removed without affecting system functionality.

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 →