# Architecture of the Graph Module in Hivemind: Virtual Filesystem Implementation

> Explore the Hivemind graph module architecture. Discover how its virtual filesystem implementation exposes repository code graphs as synthetic files using a three-layer design.

- Repository: [Activeloop/hivemind](https://github.com/activeloopai/hivemind)
- Tags: architecture
- Published: 2026-06-11

---

**The graph module in activeloopai/hivemind implements a read-only virtual filesystem (VFS) that exposes repository code graphs as synthetic files under `~/.deeplake/memory/graph/`, using a three-layer architecture comprising snapshot generation, path dispatching, and text rendering.**

The graph module serves as the intelligence layer behind Hivemind's code understanding capabilities. According to the source code in `activeloopai/hivemind`, this module creates a virtual filesystem interface that lets agents query code graphs as if they were ordinary files. The architecture cleanly separates expensive graph construction from fast read operations through a deterministic snapshot pipeline.

## Three-Layer Architecture of the Graph Module

The implementation in `src/graph/` follows a strict separation of concerns across three distinct layers: data extraction and storage, request routing, and output generation.

### Snapshot Generation and Storage Pipeline

The foundation of the system is a **canonicalized JSON snapshot** that captures symbols and relations from source files. This pipeline executes in distinct phases:

- **Extraction**: Language-specific extractors in `src/graph/extract/**/*.ts` parse TypeScript, JavaScript, Python, and Rust files to emit `GraphNode` and `GraphEdge` objects (defined in [`src/graph/types.ts`](https://github.com/activeloopai/hivemind/blob/main/src/graph/types.ts)).
- **Cross-file resolution**: [`src/graph/resolve/cross-file.ts`](https://github.com/activeloopai/hivemind/blob/main/src/graph/resolve/cross-file.ts) performs Phase 1.5 resolution, using `ImportBinding` and `RawCall` data to link calls across module boundaries.
- **Canonicalisation**: [`src/graph/snapshot.ts`](https://github.com/activeloopai/hivemind/blob/main/src/graph/snapshot.ts) sorts nodes and edges, strips volatile fields, and writes a deterministic NetworkX-compatible JSON file. The stable portion (`graph`, `nodes`, `links`) contributes to a SHA-256 hash used for de-duplication, while the `observation` field (capturing branch, timestamp, and build context) is explicitly excluded from this hash.
- **Persistence**: [`src/graph/cache.ts`](https://github.com/activeloopai/hivemind/blob/main/src/graph/cache.ts) and [`src/graph/last-build.ts`](https://github.com/activeloopai/hivemind/blob/main/src/graph/last-build.ts) store snapshots under `~/.hivemind/graphs/<repo-key>/snapshots/` and track the most recent build per worktree.

### Virtual Filesystem Dispatcher

The core entry point for VFS reads is **[`src/graph/graph-command.ts`](https://github.com/activeloopai/hivemind/blob/main/src/graph/graph-command.ts)**. It receives rewritten shell commands where paths are already mapped to the `/graph/` root. The `parseReadTargetPath` function isolates single file reads (e.g., `cat`, `head`, `tail`), while `tryGraphRead` validates traversal safety and checks for `ls /graph` listings.

The actual routing logic lives in **[`src/graph/vfs-handler.ts`](https://github.com/activeloopai/hivemind/blob/main/src/graph/vfs-handler.ts)**, which exports the `handleGraphVfs(subpath: string, cwd: string): GraphVfsResult` function. This dispatcher normalizes the incoming path, loads the appropriate snapshot via `loadSnapshotOrError()`, and delegates to the correct renderer based on the first path component ([`index.md`](https://github.com/activeloopai/hivemind/blob/main/index.md), `find/`, `show/`, `query/`, etc.).

### Renderers and Helper Functions

Each virtual endpoint has a dedicated renderer that consumes a `GraphSnapshot` and returns plain text:

| Endpoint | Renderer | Source File |
|----------|----------|-------------|
| [`index.md`](https://github.com/activeloopai/hivemind/blob/main/index.md) | `renderIndex` | [`vfs-handler.ts`](https://github.com/activeloopai/hivemind/blob/main/vfs-handler.ts) |
| `find/<pattern>` | `renderFind` | [`vfs-handler.ts`](https://github.com/activeloopai/hivemind/blob/main/vfs-handler.ts) |
| `show/<key>` | `renderShow` | [`vfs-handler.ts`](https://github.com/activeloopai/hivemind/blob/main/vfs-handler.ts) |
| `query/<pattern>` | `renderQuery` | [`vfs-handler.ts`](https://github.com/activeloopai/hivemind/blob/main/vfs-handler.ts) |
| `impact/<pattern>` | `renderImpact` | [`render/impact.ts`](https://github.com/activeloopai/hivemind/blob/main/render/impact.ts) |
| `neighborhood/<file>` | `renderNeighborhood` | [`render/neighborhood.ts`](https://github.com/activeloopai/hivemind/blob/main/render/neighborhood.ts) |
| `layers` | `renderLayers` | [`render/layers.ts`](https://github.com/activeloopai/hivemind/blob/main/render/layers.ts) |
| `tour` | `renderTour` | [`render/tour.ts`](https://github.com/activeloopai/hivemind/blob/main/render/tour.ts) |
| `path/<from>/<to>` | `renderPath` | [`render/path.ts`](https://github.com/activeloopai/hivemind/blob/main/render/path.ts) |

All renderers share utilities including `dirListing()` for static directory views and `saveHandles()` / `loadHandles()` for persisting numeric shortcuts returned by `find/` for later `show/` calls.

## How the VFS Intercepts File Requests

When a user runs a command like `cat ~/.deeplake/memory/graph/find/HttpClient`, the request flows through a specific interception chain:

1. **Path rewriting**: CLI hooks in [`src/hooks/graph-on-stop.ts`](https://github.com/activeloopai/hivemind/blob/main/src/hooks/graph-on-stop.ts) rewrite the host path `~/.deeplake/memory/graph/` to `/graph/` before the VFS sees it.
2. **Command parsing**: `tryGraphRead()` in [`graph-command.ts`](https://github.com/activeloopai/hivemind/blob/main/graph-command.ts) identifies this as a graph VFS read.
3. **Dispatch**: `handleGraphVfs("find/HttpClient", cwd)` loads the most recent snapshot for the current working directory.
4. **Rendering**: `renderFind()` executes a substring search via `findMatches()` over `snapshot.nodes`, persists the numeric handle table via `saveHandles()`, and returns a formatted list.
5. **Output**: The synthesized string is printed to stdout as if it were a physical file, though no real files exist under the memory graph path.

## Integration with CLI Hooks

Two critical hooks bridge the shell environment and the graph module:

- **[`src/hooks/graph-on-stop.ts`](https://github.com/activeloopai/hivemind/blob/main/src/hooks/graph-on-stop.ts)**: Invoked after command completion, it may inject synthetic VFS reads and rewrites user paths to the VFS root.
- **[`src/hooks/graph-pull-worker.ts`](https://github.com/activeloopai/hivemind/blob/main/src/hooks/graph-pull-worker.ts)**: Runs asynchronous pulls of remote graph snapshots, enabling `hivemind graph pull` to fetch teammate-generated graphs.

Both hooks rely on `tryGraphRead` from [`graph-command.ts`](https://github.com/activeloopai/hivemind/blob/main/graph-command.ts) to obtain synthesized output before the shell proceeds.

## Practical Usage Examples

### Querying the Graph from Shell

```bash

# List the virtual graph directory structure

cat ~/.deeplake/memory/graph/index.md

# Search for symbols containing "HttpClient" (returns numbered handles)

cat ~/.deeplake/memory/graph/find/HttpClient

# Show details of the first handle from the previous search

cat ~/.deeplake/memory/graph/show/1

# Combined find-and-expand for the top 5 matches

cat ~/.deeplake/memory/graph/query/HttpClient

```

### Programmatic API Usage

```typescript
import { handleGraphVfs } from "hivemind/src/graph/vfs-handler.js";

const cwd = process.cwd();

// Read the virtual index file
const result = handleGraphVfs("index.md", cwd);
if (result.kind === "ok") {
  console.log(result.body);   // Renders markdown from the snapshot
}

```

### Building the Graph Snapshot

```bash

# Generate a fresh snapshot for the current commit

hivemind graph build

# Pull a remote snapshot from a teammate

hivemind graph pull

```

After a successful build, the VFS becomes immediately reachable; snapshots persist under `~/.hivemind/graphs/<repo-key>/snapshots/`.

## Summary

- **The graph module** implements a read-only virtual filesystem in `src/graph/` that exposes code graphs through synthetic files.
- **Snapshot pipeline** ([`src/graph/snapshot.ts`](https://github.com/activeloopai/hivemind/blob/main/src/graph/snapshot.ts), [`src/graph/resolve/cross-file.ts`](https://github.com/activeloopai/hivemind/blob/main/src/graph/resolve/cross-file.ts)) extracts symbols, resolves cross-file calls, and writes deterministic JSON with SHA-256 de-duplication.
- **VFS dispatcher** ([`src/graph/graph-command.ts`](https://github.com/activeloopai/hivemind/blob/main/src/graph/graph-command.ts), [`src/graph/vfs-handler.ts`](https://github.com/activeloopai/hivemind/blob/main/src/graph/vfs-handler.ts)) rewrites shell paths, loads snapshots, and routes to specific renderers.
- **Renderers** (`src/graph/render/*.ts`, [`vfs-handler.ts`](https://github.com/activeloopai/hivemind/blob/main/vfs-handler.ts)) generate human-readable text for endpoints like `find/`, `show/`, and `impact/`.
- **CLI hooks** ([`src/hooks/graph-on-stop.ts`](https://github.com/activeloopai/hivemind/blob/main/src/hooks/graph-on-stop.ts)) intercept file reads to `~/.deeplake/memory/graph/` and redirect them to the VFS engine without creating physical files.

## Frequently Asked Questions

### What is the file path format used by the graph module's virtual filesystem?

The graph module intercepts accesses to paths under `~/.deeplake/memory/graph/` and rewrites them internally to `/graph/*`. Valid subpaths include [`index.md`](https://github.com/activeloopai/hivemind/blob/main/index.md), `find/<pattern>`, `show/<key>`, `query/<pattern>`, `impact/<pattern>`, `neighborhood/<file>`, `layers`, `tour`, and `path/<from>/<to>`. These paths are parsed by `parseReadTargetPath` in [`src/graph/graph-command.ts`](https://github.com/activeloopai/hivemind/blob/main/src/graph/graph-command.ts) and routed by `handleGraphVfs` in [`src/graph/vfs-handler.ts`](https://github.com/activeloopai/hivemind/blob/main/src/graph/vfs-handler.ts).

### How does the graph module resolve relationships between different source files?

Cross-file resolution occurs in Phase 1.5 of the snapshot pipeline via [`src/graph/resolve/cross-file.ts`](https://github.com/activeloopai/hivemind/blob/main/src/graph/resolve/cross-file.ts). This module analyzes `ImportBinding` and `RawCall` data to resolve function calls and symbol references across module boundaries, ensuring that the final `GraphSnapshot` contains accurate `GraphEdge` connections between nodes in different files.

### Where are graph snapshots stored on the local filesystem?

Snapshots are persisted under `~/.hivemind/graphs/<repo-key>/snapshots/` as managed by [`src/graph/cache.ts`](https://github.com/activeloopai/hivemind/blob/main/src/graph/cache.ts) and [`src/graph/last-build.ts`](https://github.com/activeloopai/hivemind/blob/main/src/graph/last-build.ts). The [`last-build.ts`](https://github.com/activeloopai/hivemind/blob/main/last-build.ts) component tracks the most recent build for each worktree, while the cache handles the actual JSON file storage. The snapshots are de-duplicated using SHA-256 hashes of their stable content (excluding the volatile `observation` metadata).

### How does the VFS generate content without creating physical files?

The VFS is strictly read-only and synthetic. When `tryGraphRead` detects a graph path, it loads the relevant `GraphSnapshot` into memory via `loadSnapshotOrError()`, executes the appropriate renderer (such as `renderFind` or `renderShow`), and returns the resulting string directly to the shell. This happens in [`src/graph/vfs-handler.ts`](https://github.com/activeloopai/hivemind/blob/main/src/graph/vfs-handler.ts)—no files are ever written to `~/.deeplake/memory/graph/`; the directory exists only as a namespace for the virtual filesystem.