# What Kind of Code Analysis Does Code-Graph-RAG Perform? A Deep Dive into Static Analysis Architecture

> Explore code-graph-rag's multi-language static code analysis architecture. Discover how it parses code into a knowledge graph for structural queries, dead-code detection, and natural language semantic search.

- Repository: [Vitali Avagyan/code-graph-rag](https://github.com/vitali87/code-graph-rag)
- Tags: deep-dive
- Published: 2026-08-14

---

**Code-Graph-RAG performs multi-language static code analysis by parsing source files into a language-agnostic knowledge graph, then enabling structural queries, dead-code detection, data-flow tracing, and semantic search-and-replace operations—all accessible via natural language prompts.**

Code-Graph-RAG is an open-source static analysis platform that transforms entire codebases into queryable **knowledge graphs**. Built around **Tree-sitter** parsing and **Memgraph** storage, it extracts structural relationships from source code without execution. This article breaks down exactly what analyses it performs, how they're implemented, and where to find the source code behind each capability.

## Three Core Analysis Categories

Code-Graph-RAG's analysis pipeline divides cleanly into **structural extraction**, **relationship discovery**, and **higher-level reasoning tasks**.

### Structural AST Extraction

The foundation of all analysis is **abstract syntax tree (AST) parsing** across multiple languages. The `ParserLoader` class in [`codebase_rag/parser_loader.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/parser_loader.py) selects language-specific Tree-sitter parsers or falls back to a **pluggable ast-grep tier** for languages without native support (e.g., Ruby).

Parsing produces normalized nodes for:

- **Functions, methods, and classes**
- **Modules and imports**
- **Decorators and visibility modifiers**

These nodes flow into [`codebase_rag/graph_loader.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/graph_loader.py), where the `GraphLoader` class builds lookup tables (`_nodes_by_id`, `_outgoing_rels`) and provides the `find_nodes_by_label` convenience method for downstream queries.

### Relationship and Data-Flow Discovery

Beyond structure, Code-Graph-RAG maps **semantic relationships** between entities. The edge types—defined in [`codebase_rag/constants/graph.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/constants/graph.py) and traversed in [`codebase_rag/dead_code.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/dead_code.py)—include:

| Edge Type | Meaning |
|-----------|---------|
| `CALLS` | Function or method invocations |
| `REFERENCES` | Variable or symbol usage |
| `INSTANTIATES` | Object creation patterns |
| `INHERITS` | Class hierarchy relationships |
| `DEFINES` | Scope containment |
| `FLOWS_TO` | **Taint-style data-flow** between assignments and sinks |

The `FLOWS_TO` edges enable **cross-language data-flow analysis**, tracing values from sources to potential security-sensitive sinks across all ten supported languages.

### Higher-Level Analyses

Building on the graph foundation, Code-Graph-RAG implements several specialized analyses:

**Dead-Code Detection**

The engine in [`codebase_rag/dead_code.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/dead_code.py) performs **reachability analysis** from defined *root* symbols—entry points, exports, and decorator-marked functions. Starting at line 92, `dead_code_from_graph` executes a BFS over `CALLS` and `REFERENCES` edges, expanding overrides and factory registrations to minimize false positives.

**Semantic Search and Replace**

Using **ast-grep patterns**, Code-Graph-RAG matches structural code fragments and applies AST-level patches. This operates safely without regex fragility, as noted in the [`NEWS.md`](https://github.com/vitali87/code-graph-rag/blob/main/NEWS.md) entry for "Structural Search & Replace."

**Code Optimization**

Language-specific best-practice rules run against the graph to flag inefficient patterns or suggest modernizations.

**Real-Time Graph Updates**

File system listeners trigger incremental graph updates, keeping analysis current without full re-parsing.

## How the Analysis Pipeline Works

### Step 1: Parsing and Normalization

The `ParserLoader` walks each source file's AST and emits a **language-agnostic representation**. For unsupported languages, YAML-based ast-grep patterns substitute for native parsers.

### Step 2: Graph Construction

Nodes and edges stream into **Memgraph** following the unified schema in [`codebase_rag/constants/graph.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/constants/graph.py). The `GraphLoader.load()` method (lines 48-89 in [`graph_loader.py`](https://github.com/vitali87/code-graph-rag/blob/main/graph_loader.py)) reads the persisted JSON and builds in-memory indexes.

### Step 3: Natural Language Querying

The RAG component in [`codebase_rag/main.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/main.py) translates natural language prompts into **Cypher queries** via an LLM, executes them against Memgraph, and formats results with source code snippets.

### Step 4: Advanced Reasoning

Specialized engines like `_walk` in [`dead_code.py`](https://github.com/vitali87/code-graph-rag/blob/main/dead_code.py) implement graph algorithms for reachability, data-flow taint analysis, and structural transformations.

## Practical Code Examples

### Building the Knowledge Graph

```bash

# Start the Memgraph + Qdrant infrastructure stack

cgr daemon up

# Parse a project into the knowledge graph

cgr start --repo-path /path/to/my/project --update-graph

```

The `cgr start` command invokes `ParserLoader` and ultimately `GraphLoader.load()` to populate the graph.

### Querying for Dead Code

```bash

# Open the interactive RAG shell

cgr

# Ask the model for unused functions

> "Which functions are never used?"

```

The LLM generates a Cypher query executing `dead_code_from_graph` from [`codebase_rag/dead_code.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/dead_code.py), returning fully-qualified names of unreachable symbols.

### Performing Structural Replacement

```bash
cgr replace --pattern 'function $NAME($ARGS) { $BODY }' \
            --replacement 'const $NAME = ($ARGS) => { $BODY }'

```

This uses ast-grep to match JavaScript/TypeScript functions and generate AST patches, with underlying implementation spanning [`dead_code.py`](https://github.com/vitali87/code-graph-rag/blob/main/dead_code.py) and [`codebase_rag/cypher_queries.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/cypher_queries.py).

## Key Implementation Files

| File | Purpose |
|------|---------|
| [`codebase_rag/parser_loader.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/parser_loader.py) | Language parser selection and AST walking |
| [`codebase_rag/graph_loader.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/graph_loader.py) | Graph loading, indexing, and node lookup API |
| [`codebase_rag/dead_code.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/dead_code.py) | Dead-code reachability analysis and root detection |
| [`codebase_rag/constants/graph.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/constants/graph.py) | Unified schema for nodes, edges, and properties |
| [`codebase_rag/main.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/main.py) | RAG CLI entry point and natural-language-to-Cypher conversion |
| [`docs/architecture/overview.md`](https://github.com/vitali87/code-graph-rag/blob/main/docs/architecture/overview.md) | High-level system architecture |
| [`docs/architecture/graph-schema.md`](https://github.com/vitali87/code-graph-rag/blob/main/docs/architecture/graph-schema.md) | Detailed graph model documentation |

These files collectively demonstrate how Code-Graph-RAG abstracts concrete syntax into a queryable semantic layer.

## Summary

- **Code-Graph-RAG performs static analysis** by parsing source into a language-agnostic knowledge graph stored in Memgraph
- **Three analysis tiers**: structural AST extraction, relationship/data-flow discovery, and higher-level reasoning (dead code, search/replace, optimization)
- **Multi-language support** via Tree-sitter with ast-grep fallback for edge cases
- **Natural language interface** converts prompts to Cypher queries executed against the graph
- **All analyses are execution-free**, operating entirely on AST and graph structures

## Frequently Asked Questions

### Is Code-Graph-RAG only for Python code?

No. Code-Graph-RAG is **language-agnostic** by design. It uses Tree-sitter parsers for ten-plus languages and provides a pluggable ast-grep tier for languages without native parsers. The unified graph schema in [`codebase_rag/constants/graph.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/constants/graph.py) abstracts away language-specific syntax.

### How does dead-code detection avoid false positives?

The engine in [`codebase_rag/dead_code.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/dead_code.py) expands analysis beyond simple call graphs to include **overrides, factory-class registrations, and closure-based decorators**. The `_walk` function performs BFS from multiple root types—not just entry points, but also exported symbols and framework-registered handlers.

### Can Code-Graph-RAG analyze data flow for security vulnerabilities?

Yes. The **`FLOWS_TO` edge type** enables taint-style analysis, tracking values from sources (user input, environment variables) through assignments to sinks (database queries, file operations). This works across all supported languages as documented in [`docs/architecture/data-flow-edges.md`](https://github.com/vitali87/code-graph-rag/blob/main/docs/architecture/data-flow-edges.md).

### What database does Code-Graph-RAG use for the knowledge graph?

**Memgraph** serves as the primary graph database, with **Qdrant** handling vector storage for embedding-based semantic search. The `GraphLoader` class manages all interactions with the persisted JSON representation and Memgraph's Cypher interface.