# How to Query the Code Graph Generated by code-graph-rag: A Complete Guide

> Learn how to query the code graph generated by code-graph-rag using the query-graph tool. Translate natural language questions into Cypher and execute against Memgraph via CLI or Python API.

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

---

**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`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/services/graph_service.py) and [`codebase_rag/services/llm.py`](https://github.com/vitali87/code-graph-rag/blob/main/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`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/tools/codebase_query.py)

The entry point is the **Typer-based CLI** in [`codebase_rag/cli.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/cli.py), which orchestrates the `run_chat_loop` in [`codebase_rag/main.py`](https://github.com/vitali87/code-graph-rag/blob/main/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:

```bash
cgr start --repo-path /path/to/project --update-graph

```

### Run a Natural-Language Query

```bash
cgr start --repo-path /path/to/project -a "List all classes that inherit from BaseModel"

```

The LLM (configured in [`settings.yaml`](https://github.com/vitali87/code-graph-rag/blob/main/settings.yaml)) generates approximately this Cypher:

```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

```python
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`](https://github.com/vitali87/code-graph-rag/blob/main/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`.

```python
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`:

```bash
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`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/graph_loader.py).

---

## Configuration and LLM Selection

The `CypherGenerator` relies on an **orchestrator LLM** configured in [`settings.yaml`](https://github.com/vitali87/code-graph-rag/blob/main/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`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/services/llm.py).

---

## Key Source Files Reference

| Component | File Path | Purpose |
|-----------|-----------|---------|
| **CLI entry** | [`codebase_rag/cli.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/cli.py) | Typer app with `start`, `export` commands |
| **Agent loop** | [`codebase_rag/main.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/main.py) | Interactive REPL, status bar, tool dispatch |
| **Memgraph client** | [`codebase_rag/services/graph_service.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/services/graph_service.py) | `MemgraphIngestor`, `fetch_all`, `export_graph_to_dict` |
| **LLM bridge** | [`codebase_rag/services/llm.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/services/llm.py) | `CypherGenerator`, `create_rag_orchestrator` |
| **Query tool** | [`codebase_rag/tools/codebase_query.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/tools/codebase_query.py) | `create_query_tool`, result formatting |
| **Graph loader** | [`codebase_rag/graph_loader.py`](https://github.com/vitali87/code-graph-rag/blob/main/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`](https://github.com/vitali87/code-graph-rag/blob/main/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`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/graph_loader.py) for re-import.