# How to Visualize the Code Graph Generated by code‑graph‑rag: 3 Export Methods Explained

> Visualize code graphs from code-graph-rag using DOT/GraphViz, NetworkX or Neo4j. Learn 3 export methods to create interactive and static diagrams from your protobuf-based GraphCodeIndex.

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

---

**Use DOT/GraphViz, NetworkX + Matplotlib, or Neo4j Cypher export to turn the protobuf‑based `GraphCodeIndex` into interactive or static diagrams.**

The `code‑graph‑rag` repository builds a language‑agnostic **code graph** that captures projects, packages, modules, classes, functions, and their relationships. This internal representation is stored as a `GraphCodeIndex` protobuf definition in [`codec/schema_pb2.py`](https://github.com/vitali87/code-graph-rag/blob/main/codec/schema_pb2.py). The project provides three distinct pathways to visualize this graph: DOT for GraphViz rendering, NetworkX for Python‑based plotting, and Cypher for Neo4j graph databases. According to the `vitali87/code-graph-rag` source code, all export functionality is centralized in [`codebase_rag/graph_loader.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/graph_loader.py) and exposed through the CLI in [`codebase_rag/cli.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/cli.py).

## DOT/GraphViz Export for Static Diagrams

The **DOT exporter** is the fastest way to generate a publishable image of your code graph. It serializes the protobuf structure to the GraphViz DOT language, which can then render to PNG, SVG, PDF, or other formats.

### Generating a DOT File

Run the graph loader with `--output-format dot`:

```bash
python -m codebase_rag.graph_loader \
    --path /path/to/your/project \
    --output-format dot \
    --output myproject.dot

```

This invokes the export logic in [`codebase_rag/graph_loader.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/graph_loader.py), which traverses the `GraphCodeIndex` and emits nodes and edges in DOT syntax.

### Rendering to Image

Use GraphViz's `dot` command to convert to your preferred format:

```bash
dot -Tsvg myproject.dot -o myproject.svg
dot -Tpng myproject.dot -o myproject.png

```

The SVG output scales cleanly for documentation, while PNG works well for slide decks and README files.

## NetworkX + Matplotlib for Programmatic Visualization

For **interactive Python workflows**, convert the protobuf to a `networkx.MultiDiGraph` and leverage Matplotlib or any NetworkX‑compatible visualizer.

### Using the Example Script

The repository includes a ready‑made demonstration in [`examples/graph_export_example.py`](https://github.com/vitali87/code-graph-rag/blob/main/examples/graph_export_example.py):

```bash
python examples/graph_export_example.py \
    --input codegraph.pb \
    --format nx \
    --output graph.png

```

### Manual NetworkX Integration

For custom visualizations, load and convert the graph directly:

```python
from codebase_rag.graph_loader import load_graph
import networkx as nx
import matplotlib.pyplot as plt

# Load protobuf into internal model

graph = load_graph("codegraph.pb")

# Convert to NetworkX MultiDiGraph preserving parallel edges

nx_graph = graph.to_networkx(multigraph=True)

# Draw with labels and save

nx.draw(nx_graph, with_labels=True, node_size=50, font_size=6)
plt.savefig("graph.png", dpi=300, bbox_inches="tight")

```

The `to_networkx(multigraph=True)` method preserves multiple edges between the same node pair—essential for capturing distinct relationship types (imports vs. inheritance vs. calls).

## Neo4j Cypher Export for Interactive Exploration

The **Cypher exporter** generates import statements for Neo4j, enabling browser‑based exploration of large codebases with filtering, search, and path analysis.

### Exporting Cypher Statements

```bash
python -m codebase_rag.graph_loader \
    --path /my/codebase \
    --output-format cypher \
    --output codegraph.cypher

```

The output file contains `CREATE` statements for nodes (projects, packages, modules, classes, functions) and relationships (imports, contains, inherits, calls).

### Importing to Neo4j

Use `neo4j-admin import` or the Cypher shell to bulk‑load:

```bash
neo4j-admin import \
    --nodes=import/nodes.csv \
    --relationships=import/relationships.csv

```

Once loaded, query interactively:

```cypher
MATCH (c:Class)-[:INHERITS]->(p:Class)
WHERE p.name = 'BaseModel'
RETURN c.name, c.file_path

```

## Key Source Files for Visualization

Understanding these files helps debug or extend the export pipeline:

| File | Purpose |
|------|---------|
| [`codebase_rag/graph_loader.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/graph_loader.py) | Central loader; implements DOT, NetworkX, and Cypher export formats |
| [`codebase_rag/cli.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/cli.py) | Command‑line interface exposing `--output-format` and `--output` options |
| [`codec/schema_pb2.py`](https://github.com/vitali87/code-graph-rag/blob/main/codec/schema_pb2.py) | Protobuf definition of `GraphCodeIndex`—the serialization format |
| [`examples/graph_export_example.py`](https://github.com/vitali87/code-graph-rag/blob/main/examples/graph_export_example.py) | Reference implementation for NetworkX visualization |
| [`codebase_rag/graph_updater.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/graph_updater.py) | Incremental graph updates for live visualization scenarios |
| [`codebase_rag/graph_audit.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/graph_audit.py) | Structural validation; useful when exports appear incorrect |

## Summary

- **DOT/GraphViz** — Best for static documentation images; one‑line export and render.
- **NetworkX + Matplotlib** — Best for Python‑centric workflows and custom styling.
- **Neo4j Cypher** — Best for large‑scale interactive exploration and complex queries.

All three methods originate from [`codebase_rag/graph_loader.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/graph_loader.py) and operate on the same `GraphCodeIndex` protobuf structure defined in [`codec/schema_pb2.py`](https://github.com/vitali87/code-graph-rag/blob/main/codec/schema_pb2.py). The CLI in [`codebase_rag/cli.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/cli.py) provides uniform access regardless of output format.

## Frequently Asked Questions

### How do I choose between DOT, NetworkX, and Neo4j export?

**DOT** suits quick documentation needs and CI pipelines where you need a PNG in seconds. **NetworkX** fits data science workflows where you already use Python for analysis and want tight control over layout algorithms. **Neo4j** becomes necessary when exploring graphs too large for static images or when you need to run complex path‑finding queries across the codebase.

### Can I visualize incremental changes to a code graph?

Yes—use [`codebase_rag/graph_updater.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/graph_updater.py) to apply deltas to an existing `GraphCodeIndex`, then re‑export via your preferred format. This avoids rebuilding the entire graph for small codebase changes, keeping visualization workflows responsive.

### What if my exported graph looks corrupted or incomplete?

Run [`codebase_rag/graph_audit.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/graph_audit.py) to validate the protobuf structure before export. Common issues include missing relationship targets (orphaned edges) or duplicate node identifiers that confuse renderers. The audit tool reports structural violations that may not surface during normal loading.

### Does code‑graph‑rag support real‑time visualization as I edit code?

Not natively, but you can approximate it: configure a file watcher to trigger [`graph_loader.py`](https://github.com/vitali87/code-graph-rag/blob/main/graph_loader.py) on save, pipe DOT output to a viewer that auto‑reloads (such as `xdot` or a browser with live‑reload), or stream updates to a running Neo4j instance using the updater module.