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:

  1. Storage – Graph resides in Memgraph via MemgraphIngestor implementing QueryProtocol
  2. Translation – CypherGenerator uses an orchestrator LLM to convert natural language to Cypher
  3. Execution – ingestor.fetch_all() runs the generated query against Memgraph
  4. 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:

  • CypherGenerator defined in codebase_rag/services/llm.py#L23–35 wraps the orchestrator LLM
  • create_query_tool in codebase_rag/tools/codebase_query.py#L44–53 assembles the pydantic_ai.Tool with proper error handling
  • ingestor.fetch_all() in codebase_rag/services/graph_service.py executes raw Cypher and returns List[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_tool with MemgraphIngestor and CypherGenerator for custom workflows
  • Direct Cypher: Call ingestor.fetch_all() to bypass LLM translation and execute optimized queries
  • Export capability: Run cgr export to snapshot the graph as JSON via codebase_rag/main.py#L103–124
  • Extensible design: The QueryProtocol interface 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:

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 →