How to Query the Code Graph Generated by code-graph-rag: A Complete Guide
Query the code graph generated by code-graph-rag using the query-graph tool via CLI (cgr start -a "<question>") or the Python API (create_query_tool) to translate natural language into Cypher and execute against Memgraph.
The code-graph-rag project by vitali87 builds a Neo-type property graph stored in Memgraph that captures your codebase structure—files, symbols, imports, definitions, and call relationships. Once indexed, you query this graph using natural language without writing Cypher manually. This article explains both the CLI and programmatic approaches based on the actual source implementation.
Architecture Overview
The query system follows a four-stage pipeline implemented across codebase_rag/services/graph_service.py and codebase_rag/services/llm.py:
- Storage – Graph resides in Memgraph via
MemgraphIngestorimplementingQueryProtocol - Translation –
CypherGeneratoruses an orchestrator LLM to convert natural language to Cypher - Execution –
ingestor.fetch_all()runs the generated query against Memgraph - Presentation – Results render as formatted tables or JSON via
codebase_rag/tools/codebase_query.py
The entry point is the Typer-based CLI in codebase_rag/cli.py, which orchestrates the run_chat_loop in codebase_rag/main.py.
Method 1: CLI One-Off Queries
The fastest way to query the code graph generated by code-graph-rag is the --ask-agent (or -a) flag with cgr start. This runs a single agent turn, generates Cypher, executes it, prints results, and exits.
Prerequisites
First, ensure your repository is indexed:
cgr start --repo-path /path/to/project --update-graph
Run a Natural-Language Query
cgr start --repo-path /path/to/project -a "List all classes that inherit from BaseModel"
The LLM (configured in settings.yaml) generates approximately this Cypher:
MATCH (c:Class)-[:INHERITS]->(p:Class)
WHERE p.name = 'BaseModel'
RETURN c.name AS class_name, c.file AS file_path
Output format – A rich table with automatic truncation for large result sets:
┏━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┓
┃ class_name ┃ file_path ┃
┣━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━┫
┃ MyModel ┃ src/models.py ┃
┃ AnotherModel ┃ src/extra.py ┃
┗━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━┛
The truncation logic lives in codebase_rag/tools/codebase_query.py#L61–82 to prevent console flooding.
Method 2: Python API for Custom Scripts
For notebooks, tests, or automation, embed the query pipeline directly. This bypasses the CLI and gives full control over the MemgraphIngestor and CypherGenerator instances.
Complete Working Example
import asyncio
from pathlib import Path
from codebase_rag.services.graph_service import MemgraphIngestor
from codebase_rag.services.llm import CypherGenerator, create_rag_orchestrator
from codebase_rag.tools.codebase_query import create_query_tool
from pydantic_ai import Tool
async def main():
# 1️⃣ Connect to Memgraph
ingestor = MemgraphIngestor(
host="localhost",
port=7687,
batch_size=100,
username="memgraph",
password="memgraph",
)
# 2️⃣ Initialize the LLM orchestrator for Cypher generation
orchestrator = create_rag_orchestrator() # Reads settings.yaml
cypher_gen = CypherGenerator(orchestrator=orchestrator)
# 3️⃣ Build the query-graph tool
query_tool: Tool = create_query_tool(ingestor, cypher_gen)
# 4️⃣ Execute natural language query
result = await query_tool.function(
natural_language_query="Find all functions that read a file named 'config.yaml'"
)
# 5️⃣ Process results (list of dictionaries)
for row in result.results:
print(f"{row['function_name']} in {row['file_path']}")
asyncio.run(main())
Key implementation details from source:
CypherGeneratordefined incodebase_rag/services/llm.py#L23–35wraps the orchestrator LLMcreate_query_toolincodebase_rag/tools/codebase_query.py#L44–53assembles thepydantic_ai.Toolwith proper error handlingingestor.fetch_all()incodebase_rag/services/graph_service.pyexecutes raw Cypher and returnsList[Dict[str, Any]]
Method 3: Direct Cypher Execution
If you already know Cypher or need precise control, skip the LLM translation entirely. Use MemgraphIngestor directly as shown in codebase_rag/main.py#L58–66.
from codebase_rag.services.graph_service import MemgraphIngestor
ingestor = MemgraphIngestor(
host="localhost",
port=7687,
batch_size=100,
username="memgraph",
password="memgraph",
)
cypher = """
MATCH (caller:Function)-[:CALLS]->(callee:Function)
WHERE caller.name = 'process_data'
RETURN callee.name AS function_name,
callee.file AS file_path,
callee.line AS line_number
"""
rows = ingestor.fetch_all(cypher)
# Returns: [{'function_name': 'validate_input', 'file_path': 'src/core.py', 'line_number': 42}, ...]
This approach eliminates LLM latency and is ideal for:
- Cached or pre-validated queries
- Performance-sensitive operations
- Debugging graph structure
Graph Export and Offline Analysis
Before querying, you may want to export the graph for inspection or backup. The CLI supports this via cgr export:
cgr export --output graph_backup.json
Implementation in codebase_rag/main.py#L103–124 serializes the entire Memgraph state to JSON using ingestor.export_graph_to_dict(). The export format preserves nodes, relationships, and properties for re-import via codebase_rag/graph_loader.py.
Configuration and LLM Selection
The CypherGenerator relies on an orchestrator LLM configured in settings.yaml. Supported providers include:
- Ollama (local models)
- OpenAI (GPT-4, GPT-3.5)
- Anthropic (Claude models)
The orchestrator is instantiated via create_rag_orchestrator() and passed to CypherGenerator as shown in codebase_rag/services/llm.py.
Key Source Files Reference
| Component | File Path | Purpose |
|---|---|---|
| CLI entry | codebase_rag/cli.py |
Typer app with start, export commands |
| Agent loop | codebase_rag/main.py |
Interactive REPL, status bar, tool dispatch |
| Memgraph client | codebase_rag/services/graph_service.py |
MemgraphIngestor, fetch_all, export_graph_to_dict |
| LLM bridge | codebase_rag/services/llm.py |
CypherGenerator, create_rag_orchestrator |
| Query tool | codebase_rag/tools/codebase_query.py |
create_query_tool, result formatting |
| Graph loader | codebase_rag/graph_loader.py |
JSON export/import, in-memory indexes |
| Constants | codebase_rag/constants/*.py |
UI strings, error codes, colors |
Summary
- CLI quick queries: Use
cgr start -a "<question>"for one-off natural language questions against your code graph - Python integration: Import
create_query_toolwithMemgraphIngestorandCypherGeneratorfor custom workflows - Direct Cypher: Call
ingestor.fetch_all()to bypass LLM translation and execute optimized queries - Export capability: Run
cgr exportto snapshot the graph as JSON viacodebase_rag/main.py#L103–124 - Extensible design: The
QueryProtocolinterface allows swapping Memgraph for other graph databases
Frequently Asked Questions
What database stores the code graph generated by code-graph-rag?
Memgraph, a native in-memory graph database. The MemgraphIngestor class in codebase_rag/services/graph_service.py manages connections, queries, and exports using the Bolt protocol on port 7687.
Can I query the graph without using the LLM translation?
Yes. Instantiate MemgraphIngestor directly and call fetch_all(cypher_query) with your own Cypher. This skips the CypherGenerator entirely, eliminating LLM latency for known query patterns.
How does the natural language translation to Cypher work?
The CypherGenerator class prompts an orchestrator LLM with the user's question and schema context. The LLM returns valid Cypher, which create_query_tool validates and executes via ingestor.fetch_all() in codebase_rag/tools/codebase_query.py#L44–53.
Is there a way to export the graph for external tools?
Yes. Use the CLI command cgr export --output file.json which invokes export_graph_to_dict() from codebase_rag/main.py#L103–124. The JSON contains nodes, relationships, and properties compatible with codebase_rag/graph_loader.py for re-import.
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 →