# Best Practices for Using the Graph Module in Hivemind

> Master the Hivemind graph module with these best practices. Explore code relationships using shell commands. Learn the query-first, drill-down navigation pattern for efficient code exploration.

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

---

**The Hivemind graph module is a read-only virtual filesystem that lets you explore code relationships using standard shell commands like `cat` and `ls`, requiring you to build or pull the snapshot first and follow a query-first, drill-down navigation pattern.**

The graph module in Hivemind provides a virtual filesystem (VFS) interface for exploring code-graph snapshots through familiar shell commands. As implemented in the `activeloopai/hivemind` repository, this system indexes your codebase into a queryable graph structure stored in `~/.deeplake/memory/graph/`. Understanding the **best practices for using the graph module** ensures efficient navigation and prevents common pitfalls like stale data or traversal errors.

## Understand the Three-Layer Architecture

The module operates through three distinct layers that handle command translation, dispatch, and rendering. Each layer has specific entry points in the source tree:

1. **Command Parsing** – Extracts virtual `/graph/*` paths from rewritten shell commands. The core parser `parseReadTargetPath` (lines 49-86) and dispatcher `tryGraphRead` (lines 102-125) live in [`src/graph/graph-command.ts`](https://github.com/activeloopai/hivemind/blob/main/src/graph/graph-command.ts).

2. **VFS Dispatch** – Routes sub-paths (like [`index.md`](https://github.com/activeloopai/hivemind/blob/main/index.md) or `find/foo`) to appropriate renderers. The entry point `handleGraphVfs` (lines 56-75) and snapshot loader `loadSnapshotOrError` (lines 62-84) are implemented in [`src/graph/vfs-handler.ts`](https://github.com/activeloopai/hivemind/blob/main/src/graph/vfs-handler.ts).

3. **Renderers** – Synthesize textual views from the JSON snapshot. These reside in `src/graph/render/` (e.g., [`render/index.ts`](https://github.com/activeloopai/hivemind/blob/main/render/index.ts), [`render/find.ts`](https://github.com/activeloopai/hivemind/blob/main/render/find.ts)) and generate outputs like index overviews, search results, and node details.

## Build the Snapshot Before Reading

The VFS returns `"no-graph"` errors if the snapshot is missing. Always initialize the graph before attempting reads:

```bash
hivemind graph build   # builds from the current checkout

hivemind graph pull    # fetches a teammate's snapshot

```

The pull operation runs asynchronously through the worker defined in [`src/hooks/graph-pull-worker.ts`](https://github.com/activeloopai/hivemind/blob/main/src/hooks/graph-pull-worker.ts). Because the graph lives only in memory or cached JSON, the module is strictly **read-only**—never modify files under `~/.deeplake/memory/graph/` directly.

## Use Canonical Virtual Paths and Safe Navigation

All reads must target the `/graph/` virtual root. The parser normalizes quoted paths and flags, but rejects traversal attempts (e.g., `../`) through the `hasTraversal` guard (lines 88-91). 

**Prefer `cat`-style single-file reads** over complex pipelines. The `parseReadTargetPath` function (lines 42-68) only supports single-file reads with optional `head` or `tail` pipes; multi-file `cat` operations or complex pipelines pass through to the real shell instead of the VFS.

When patterns contain spaces, use quotes to protect tokens:

```bash
cat "/graph/find/auth middleware"

```

The tokenizer respects single and double quotes (lines 22-25 in the command parser).

## Follow the Query-First, Drill-Down Pattern

Efficient navigation relies on starting broad and narrowing focus:

1. **Start with the overview** – Run `cat ~/.deeplake/memory/graph/index.md` to see commit hashes, node/edge counts, and a query cheat-sheet rendered by `renderIndex`.

2. **Search with `find/` or `query/`** – 
   - `find/<pattern>` performs case-insensitive substring searches, returning up to 50 matches and writing a handle table to [`.find-handles.json`](https://github.com/activeloopai/hivemind/blob/main/.find-handles.json). The ranking logic lives in `findMatches` (lines 22-38) with a fuzzy fallback.
   - `query/<pattern>` combines `find` with immediate expansion of the top 5 matches and their 1-hop neighbors (see `renderQuery`).

3. **Drill down with `show/<handle-or-pattern>`** – 
   - Supply a **numeric handle** (e.g., `show/3`) to load the specific node from the handle map produced by the last `find`/`query`. The handle persistence logic uses `saveHandles` (lines 33-41) and `loadHandles` (lines 47-60).
   - Supply a **string pattern** (e.g., `show/HttpClient`) to resolve a unique node or receive a disambiguation list.

The `renderShow` function (lines 87-124) ultimately calls `renderNodeDetail` (lines 149-186) to display inbound and outbound edges grouped by relation.

## Explore Advanced Endpoints

Beyond basic search, the VFS supports specialized views dispatched in `handleGraphVfs` (lines 99-155):

- `neighborhood/<file>` – Shows all symbols defined in a file plus cross-file neighbors.
- `layers` – Groups symbols by architectural path heuristics.
- `tour` – Provides a deterministic dependency-ordered walkthrough.
- `path/<from>/<to>` – Returns the shortest path between two symbol substrings.

## Maintain Snapshot Freshness and Handle Errors

The VFS **does not** automatically rebuild after source changes. If you edit files, re-run `hivemind graph build` to refresh the snapshot. Check the `built <timestamp>` header in [`index.md`](https://github.com/activeloopai/hivemind/blob/main/index.md) to verify data age.

All VFS entry points return a `GraphVfsResult` with `kind: "ok" | "not-found" | "no-graph"`. Inspect this status in scripts and, on `"no-graph"`, trigger a build or pull before retrying.

## Common Command Patterns

| Goal | Command | Implementation Detail |
|------|---------|---------------------|
| Show overview | `cat ~/.deeplake/memory/graph/index.md` | Uses `renderIndex` |
| Search symbols | `cat ~/.deeplake/memory/graph/find/pushSnapshot` | Ranked by `findMatches` |
| Search + neighbors | `cat ~/.deeplake/memory/graph/query/auth` | Combines find with 1-hop expansion |
| View by handle | `cat ~/.deeplake/memory/graph/show/3` | Reads [`.find-handles.json`](https://github.com/activeloopai/hivemind/blob/main/.find-handles.json) |
| Resolve pattern | `cat ~/.deeplake/memory/graph/show/HttpClient` | Falls back to disambiguation list |
| File neighborhood | `cat ~/.deeplake/memory/graph/neighborhood/src/utils.ts` | Cross-file dependencies |
| Architecture layers | `cat ~/.deeplake/memory/graph/layers` | Path heuristic grouping |
| Dependency tour | `cat ~/.deeplake/memory/graph/tour` | Deterministic walk order |
| Shortest path | `cat ~/.deeplake/memory/graph/path/Controller/Service` | Pathfinding between symbols |
| List directory | `ls ~/.deeplake/memory/graph` | Shortcut in `tryGraphRead` (lines 103-108) |

### Example: Handle-Based Navigation

```bash

# 1. Find symbols containing "cache"

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

# Output includes numbered handles:

#   [1] src/cache.js   function  exported

#   [2] src/utils/cache.ts   class  internal

# 2. Drill into the first result using its handle

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

```

## Key Source Files

| File | Role |
|------|------|
| [`src/graph/graph-command.ts`](https://github.com/activeloopai/hivemind/blob/main/src/graph/graph-command.ts) | Parses shell commands and dispatches to VFS via `parseReadTargetPath` and `tryGraphRead` |
| [`src/graph/vfs-handler.ts`](https://github.com/activeloopai/hivemind/blob/main/src/graph/vfs-handler.ts) | Core VFS dispatcher `handleGraphVfs` and snapshot loader `loadSnapshotOrError` |
| [`src/graph/render/index.ts`](https://github.com/activeloopai/hivemind/blob/main/src/graph/render/index.ts) | Renders the [`index.md`](https://github.com/activeloopai/hivemind/blob/main/index.md) overview |
| [`src/graph/render/find.ts`](https://github.com/activeloopai/hivemind/blob/main/src/graph/render/find.ts) | Implements `find/` endpoint with ranking and fuzzy matching |
| [`src/graph/render/query.ts`](https://github.com/activeloopai/hivemind/blob/main/src/graph/render/query.ts) | Implements `query/` endpoint with neighbor expansion |
| [`src/graph/render/show.ts`](https://github.com/activeloopai/hivemind/blob/main/src/graph/render/show.ts) | Implements `show/` endpoint with node detail views |
| [`src/hooks/graph-pull-worker.ts`](https://github.com/activeloopai/hivemind/blob/main/src/hooks/graph-pull-worker.ts) | Async worker for remote snapshot retrieval |
| [`src/graph/types.ts`](https://github.com/activeloopai/hivemind/blob/main/src/graph/types.ts) | Type definitions for `GraphSnapshot`, `GraphNode`, and `GraphEdge` |

## Summary

- **Build or pull first** – The VFS requires an existing snapshot; use `hivemind graph build` or `hivemind graph pull` before reads.
- **Stay within `/graph/`** – All virtual paths must use this root; traversal attempts like `../` are blocked by the `hasTraversal` guard.
- **Query before drilling** – Use `find/` or `query/` to get handles, then `show/<handle>` to inspect specific nodes.
- **Keep it fresh** – Rebuild the snapshot after code changes; the VFS does not auto-update.
- **Handle errors explicitly** – Check `GraphVfsResult.kind` for `"no-graph"` states and rebuild accordingly.

## Frequently Asked Questions

### How do I update the graph after editing my code?

You must manually rebuild the snapshot. Run `hivemind graph build` to regenerate the graph from your current checkout, or `hivemind graph pull` to fetch a teammate's version. The VFS in [`src/graph/vfs-handler.ts`](https://github.com/activeloopai/hivemind/blob/main/src/graph/vfs-handler.ts) does not watch for file changes automatically, so stale data is indicated by the timestamp in [`index.md`](https://github.com/activeloopai/hivemind/blob/main/index.md).

### Why does my `cat` command return "no-graph"?

This error originates from `loadSnapshotOrError` (lines 62-84) when the snapshot JSON is missing or corrupted. Ensure you have run `hivemind graph build` at least once in the current worktree. The `GraphVfsResult` type explicitly uses `"no-graph"` to signal this state, allowing scripts to trigger a rebuild before retrying.

### Can I write or modify files through the graph VFS?

No. The graph module is strictly read-only. According to the architecture in [`src/graph/vfs-handler.ts`](https://github.com/activeloopai/hivemind/blob/main/src/graph/vfs-handler.ts), renderers only synthesize textual views from the JSON snapshot. Attempting to redirect output into paths under `~/.deeplake/memory/graph/` will either fail or be ignored by the read-only enforcement.

### What is the difference between `find/` and `query/` endpoints?

The `find/<pattern>` endpoint in [`src/graph/render/find.ts`](https://github.com/activeloopai/hivemind/blob/main/src/graph/render/find.ts) performs substring matching and returns up to 50 results with handles. The `query/<pattern>` endpoint in [`src/graph/render/query.ts`](https://github.com/activeloopai/hivemind/blob/main/src/graph/render/query.ts) executes `find` first, then automatically expands the top 5 matches to show their 1-hop neighbors, providing immediate context without requiring separate `show/` commands.