Architecture of the Graph Module in Hivemind: Virtual Filesystem Implementation
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/**/*.tsparse TypeScript, JavaScript, Python, and Rust files to emitGraphNodeandGraphEdgeobjects (defined insrc/graph/types.ts). - Cross-file resolution:
src/graph/resolve/cross-file.tsperforms Phase 1.5 resolution, usingImportBindingandRawCalldata to link calls across module boundaries. - Canonicalisation:
src/graph/snapshot.tssorts 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 theobservationfield (capturing branch, timestamp, and build context) is explicitly excluded from this hash. - Persistence:
src/graph/cache.tsandsrc/graph/last-build.tsstore 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. 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, 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, 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 |
renderIndex |
vfs-handler.ts |
find/<pattern> |
renderFind |
vfs-handler.ts |
show/<key> |
renderShow |
vfs-handler.ts |
query/<pattern> |
renderQuery |
vfs-handler.ts |
impact/<pattern> |
renderImpact |
render/impact.ts |
neighborhood/<file> |
renderNeighborhood |
render/neighborhood.ts |
layers |
renderLayers |
render/layers.ts |
tour |
renderTour |
render/tour.ts |
path/<from>/<to> |
renderPath |
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:
- Path rewriting: CLI hooks in
src/hooks/graph-on-stop.tsrewrite the host path~/.deeplake/memory/graph/to/graph/before the VFS sees it. - Command parsing:
tryGraphRead()ingraph-command.tsidentifies this as a graph VFS read. - Dispatch:
handleGraphVfs("find/HttpClient", cwd)loads the most recent snapshot for the current working directory. - Rendering:
renderFind()executes a substring search viafindMatches()oversnapshot.nodes, persists the numeric handle table viasaveHandles(), and returns a formatted list. - 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: Invoked after command completion, it may inject synthetic VFS reads and rewrites user paths to the VFS root.src/hooks/graph-pull-worker.ts: Runs asynchronous pulls of remote graph snapshots, enablinghivemind graph pullto fetch teammate-generated graphs.
Both hooks rely on tryGraphRead from graph-command.ts to obtain synthesized output before the shell proceeds.
Practical Usage Examples
Querying the Graph from Shell
# 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
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
# 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,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,src/graph/vfs-handler.ts) rewrites shell paths, loads snapshots, and routes to specific renderers. - Renderers (
src/graph/render/*.ts,vfs-handler.ts) generate human-readable text for endpoints likefind/,show/, andimpact/. - CLI hooks (
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, 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 and routed by handleGraphVfs in 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. 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 and src/graph/last-build.ts. The 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—no files are ever written to ~/.deeplake/memory/graph/; the directory exists only as a namespace for the virtual filesystem.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →