What Kind of Code Analysis Does Code-Graph-RAG Perform? A Deep Dive into Static Analysis Architecture
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 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, 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 and traversed in 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 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 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. The GraphLoader.load() method (lines 48-89 in 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 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 implement graph algorithms for reachability, data-flow taint analysis, and structural transformations.
Practical Code Examples
Building the Knowledge Graph
# 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
# 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, returning fully-qualified names of unreachable symbols.
Performing Structural Replacement
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 and codebase_rag/cypher_queries.py.
Key Implementation Files
| File | Purpose |
|---|---|
codebase_rag/parser_loader.py |
Language parser selection and AST walking |
codebase_rag/graph_loader.py |
Graph loading, indexing, and node lookup API |
codebase_rag/dead_code.py |
Dead-code reachability analysis and root detection |
codebase_rag/constants/graph.py |
Unified schema for nodes, edges, and properties |
codebase_rag/main.py |
RAG CLI entry point and natural-language-to-Cypher conversion |
docs/architecture/overview.md |
High-level system architecture |
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 abstracts away language-specific syntax.
How does dead-code detection avoid false positives?
The engine in 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.
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.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →