# How to Export Code-Graph-RAG Knowledge Graph to JSON: A Complete Technical Guide

> Export your Code-Graph-RAG knowledge graph to JSON using the CLI or programmatically. Save your Memgraph knowledge graph as a portable JSON document preserving all data.

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

---

**Use the `--output` flag in the CLI or call `export_graph_to_file()` programmatically to save your Memgraph-backed knowledge graph as a portable JSON document with full node, relationship, and metadata preservation.**

Code-Graph-RAG builds a language-agnostic knowledge graph of any codebase inside Memgraph. When you need a portable, human-readable snapshot for archiving, sharing, or offline analysis, you can export that graph as structured JSON. This guide walks through the complete export flow using the actual source implementation in the `vitali87/code-graph-rag` repository.

## CLI Export: The Quick Path

The fastest way to export a knowledge graph is through the primary CLI command. When you run `cgr start` with the `--output` (or `-o`) flag, the pipeline automatically serializes the graph after ingestion completes.

In [`codebase_rag/cli.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/cli.py), lines 26-30 handle this flag:

```python

# codebase_rag/cli.py – lines 26-30

if output:
    _info(style(cs.CLI_MSG_EXPORTING_TO.format(path=output), cs.Color.CYAN))
    if not export_graph_to_file(ingestor, output):
        raise typer.Exit(1)

```

The CLI validates the path, triggers the export, and exits with code 1 on failure—ensuring CI/CD pipelines can detect export errors.

**Example CLI invocation:**

```bash
cgr start \
    --repo-path /path/to/project \
    --update-graph \
    --output /tmp/project_graph.json

```

## The Export Pipeline: Three Core Functions

The export logic flows through three layered functions in [`codebase_rag/main.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/main.py). Understanding this hierarchy helps you debug failures or extend functionality.

### 1. `export_graph_to_file()` — Entry Point

This public function (lines 1403-1419) orchestrates the export:

```python

# codebase_rag/main.py – lines 1403-1419

def export_graph_to_file(ingestor: MemgraphIngestor, output: str) -> bool:
    output_path = Path(output)
    try:
        graph_data = _write_graph_json(ingestor, output_path)
        metadata = graph_data[cs.KEY_METADATA]
        app_context.console.print(
            cs.UI_GRAPH_EXPORT_SUCCESS.format(path=output_path.absolute())
        )
        app_context.console.print(
            cs.UI_GRAPH_EXPORT_STATS.format(
                nodes=metadata[cs.KEY_TOTAL_NODES],
                relationships=metadata[cs.KEY_TOTAL_RELATIONSHIPS],
            )
        )
        return True
    except Exception as e:
        app_context.console.print(cs.UI_ERR_EXPORT_FAILED.format(error=e))
        logger.exception(ls.EXPORT_ERROR.format(error=e))
        return False

```

Key responsibilities:
- Creates `Path` object for cross-platform compatibility
- Delegates serialization to `_write_graph_json`
- Prints success banner with **node count** and **relationship count**
- Returns boolean status for error handling

### 2. `_write_graph_json()` — File I/O

The internal helper (lines 1384-1389) handles actual disk operations:

```python

# codebase_rag/main.py – lines 1384-1389

def _write_graph_json(ingestor: MemgraphIngestor, output_path: Path) -> GraphData:
    graph_data: GraphData = ingestor.export_graph_to_dict()
    output_path.parent.mkdir(parents=True, exist_ok=True)
    with open(output_path, "w", encoding=cs.ENCODING_UTF8) as f:
        json.dump(graph_data, f, indent=cs.JSON_INDENT, ensure_ascii=False)
    return graph_data

```

Notable behaviors:
- `mkdir(parents=True, exist_ok=True)` creates missing directories automatically
- `indent=cs.JSON_INDENT` (typically 2 or 4 spaces) enables human-readable formatting
- `ensure_ascii=False` preserves Unicode characters in source code identifiers

### 3. `MemgraphIngestor.export_graph_to_dict()` — Data Extraction

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) implements the actual graph traversal:

```python

# codebase_rag/services/graph_service.py – class definition

class MemgraphIngestor:
    ...
    def export_graph_to_dict(self) -> GraphData:
        # (implementation details omitted for brevity)

        return {
            cs.KEY_NODES: self._nodes,
            cs.KEY_RELATIONSHIPS: self._relationships,
            cs.KEY_METADATA: self._metadata,
        }

```

This method emits a dictionary with three top-level keys:
- **`nodes`** — List of node objects with IDs, labels, and properties
- **`relationships`** — List of edges with source, target, and type
- **`metadata`** — Summary statistics including total counts

The structure conforms to the protobuf schema in [`codec/schema_pb2.py`](https://github.com/vitali87/code-graph-rag/blob/main/codec/schema_pb2.py), ensuring forward compatibility with SDK loaders.

## Programmatic Export from Python

For integration into data pipelines or custom workflows, skip the CLI and call the export functions directly:

```python

# Example – Programmatic export from a script

from codebase_rag.main import export_graph_to_file
from codebase_rag.services.graph_service import MemgraphIngestor
from codebase_rag.config import settings

ingestor = MemgraphIngestor(
    host=settings.MEMGRAPH_HOST,
    port=settings.MEMGRAPH_PORT,
    batch_size=1000,
    username=settings.MEMGRAPH_USERNAME,
    password=settings.MEMGRAPH_PASSWORD,
)
success = export_graph_to_file(ingestor, "graph_snapshot.json")

```

This pattern is essential when:
- Running inside Jupyter notebooks for exploratory analysis
- Embedding export into scheduled jobs
- Building custom ingestion pipelines with pre/post-processing

## Loading Exported JSON with the SDK

The published Python SDK provides [`codebase_rag/graph_loader.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/graph_loader.py) to reconstruct a queryable graph object without running Memgraph:

```python

# Example – Load the exported JSON with the SDK

from codebase_rag.graph_loader import load_graph

graph = load_graph("graph_snapshot.json")
print("Nodes:", len(graph.nodes))
print("Relationships:", len(graph.relationships))

```

The `GraphLoader` preserves the original graph topology, enabling offline traversal, subgraph extraction, and integration with network analysis libraries.

## Configuration Constants in [`config.py`](https://github.com/vitali87/code-graph-rag/blob/main/config.py)

The export pipeline relies on centralized constants defined in [`codebase_rag/config.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/config.py):

| Constant | Purpose |
|----------|---------|
| `cs.KEY_NODES` | Dictionary key for node list (`"nodes"`) |
| `cs.KEY_RELATIONSHIPS` | Dictionary key for relationship list |
| `cs.KEY_METADATA` | Dictionary key for metadata object |
| `cs.JSON_INDENT` | Pretty-print indentation level |
| `cs.ENCODING_UTF8` | File encoding specification |
| `UI_GRAPH_EXPORT_SUCCESS` | Success message template |
| `UI_ERR_EXPORT_FAILED` | Error message template |

This centralization ensures consistent behavior across CLI, programmatic, and SDK interfaces.

## Summary

- **CLI export** uses `cgr start --output path.json` triggered by flag handling in [`codebase_rag/cli.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/cli.py)
- **Core export logic** lives in [`codebase_rag/main.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/main.py) with `export_graph_to_file()` and `_write_graph_json()`
- **Data extraction** occurs in `MemgraphIngestor.export_graph_to_dict()` within [`codebase_rag/services/graph_service.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/services/graph_service.py)
- **JSON structure** follows the protobuf schema with `nodes`, `relationships`, and `metadata` top-level keys
- **SDK reloading** is available via `codebase_rag/graph_loader.load_graph()` for offline analysis

## Frequently Asked Questions

### What JSON format does Code-Graph-RAG export produce?

The export produces a dictionary with three top-level keys: `nodes` (list of node objects), `relationships` (list of edge objects), and `metadata` (summary statistics). This structure mirrors the protobuf schema defined in [`codec/schema_pb2.py`](https://github.com/vitali87/code-graph-rag/blob/main/codec/schema_pb2.py) and is compatible with the official SDK loader.

### Can I export without running the full CLI ingestion?

Yes. Instantiate `MemgraphIngestor` directly from [`codebase_rag/services/graph_service.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/services/graph_service.py), connect to your existing Memgraph instance, and call `export_graph_to_file()` from [`codebase_rag/main.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/main.py). This is useful when the graph was built in a previous session.

### Does the export require a running Memgraph server?

For the standard export flow, yes—the `MemgraphIngestor` queries live data. However, once exported, the JSON file is self-contained and can be loaded offline via [`codebase_rag/graph_loader.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/graph_loader.py) without any database connection.

### How do I handle large graphs that might timeout during export?

The `MemgraphIngestor` accepts a `batch_size` parameter (default typically 1000). Increase this for fewer round-trips on large graphs, or implement chunked export by modifying `_write_graph_json()` to stream JSON rather than buffer entirely in memory.