# How Cross‑Repository Search Works in Code Review Graph: VS Code Knowledge Graph Deep Dive

> Discover how Code Review Graph performs cross-repository search. Learn how VS Code's knowledge graph unifies and queries indexed code across multiple repositories efficiently.

- Repository: [Tirth Kanani/code-review-graph](https://github.com/tirth8205/code-review-graph)
- Tags: deep-dive
- Published: 2026-07-20

---

**The Code Review Graph extension enables cross‑repository search by maintaining a unified SQLite database of code graph nodes across all registered repositories, performing a single LIKE query against the combined index, and resolving results back to absolute file paths in the workspace.**

Cross‑repository search is a core feature of the `tirth8205/code-review-graph` extension, which builds a searchable knowledge graph for every repository registered in a VS Code workspace. When you register a repository, the extension indexes its functions, classes, files, and types into a local database, allowing you to search across all repos simultaneously from a single QuickPick interface.

## The Architecture of Cross‑Repository Search

The extension treats your entire workspace as a single searchable corpus rather than isolated silos. It achieves this through a two‑layer architecture that separates data persistence from UI interaction.

### Repository Registration and Indexing

When you register a repository through the workspace, the extension creates (or updates) a dedicated SQLite database for that repository. A background watcher populates the `nodes` table with **graph nodes**—entities like functions, classes, tests, and types. Each node records its `kind`, `name`, `filePath`, and line numbers exactly as they appear in the source tree. This indexing happens for every registered repository independently, ensuring that all codebases contribute to the global index.

### The Unified SQLite Database Schema

Unlike multi‑tenant systems that partition data by repository, the extension stores all nodes in a single logical table. In [`src/backend/sqlite.ts`](https://github.com/tirth8205/code-review-graph/blob/main/src/backend/sqlite.ts), the `searchNodes` method builds a simple SQL query that scans the `nodes` table without filtering by repository origin. This design choice means one query can return matches from any indexed repository, enabling true cross‑repository search capabilities.

## How the Search Query Works

The search UI is implemented in [`src/features/search.ts`](https://github.com/tirth8205/code-review-graph/blob/main/src/features/search.ts). Triggering the `codeReviewGraph.search` command opens a VS Code QuickPick that debounces keystrokes and calls the SQLite reader on every input change.

Inside [`src/features/search.ts`](https://github.com/tirth8205/code-review-graph/blob/main/src/features/search.ts) (lines 68‑71), the extension executes:

```typescript
const results = reader.searchNodes(value, 20);

```

The `searchNodes` implementation in [`src/backend/sqlite.ts`](https://github.com/tirth8205/code-review-graph/blob/main/src/backend/sqlite.ts) (lines 302‑307) constructs a `LIKE '%query%'` clause against the `name` column:

```typescript
// Conceptual implementation from sqlite.ts
public searchNodes(query: string, limit: number): GraphNode[] {
  const sql = `
    SELECT * FROM nodes 
    WHERE name LIKE '%' || ? || '%' 
    LIMIT ?
  `;
  return this.db.all(sql, [query, limit]);
}

```

Because this query runs against the unified node set, the result set naturally contains matches from **every registered repository** that has been indexed, not just the currently active one.

## From Query to File Navigation

When you select a result from the QuickPick, the extension must resolve the stored relative path to an absolute path on disk. The `navigateToNode` function (lines 52‑62 in [`src/features/search.ts`](https://github.com/tirth8205/code-review-graph/blob/main/src/features/search.ts)) uses the current workspace root to transform the relative `filePath` stored in the database into an absolute URI.

This resolution works regardless of which repository owns the file because the node’s `filePath` is stored exactly as it appears in that repo’s source tree. The extension then opens the file at the indicated line number using VS Code’s standard document API.

## Implementation Examples

### Triggering Cross‑Repository Search Programmatically

You can invoke the search UI from any VS Code extension or keybinding:

```typescript
// Execute the search command from the command palette
await vscode.commands.executeCommand('codeReviewGraph.search');

```

### Querying the SQLite Reader Directly

For custom tooling, instantiate the `SqliteReader` and call `searchNodes` to retrieve `GraphNode` objects from all indexed repositories:

```typescript
import { SqliteReader } from './backend/sqlite';

// Reader instantiated for the current workspace
const reader = new SqliteReader();
const query = 'auth';
const limit = 10;

// Returns GraphNode[] from *all* registered repositories
const results = reader.searchNodes(query, limit);

results.forEach(node => {
  console.log(`${node.kind}: ${node.name} – ${node.filePath}:${node.lineStart}`);
});

```

### Manual Navigation to a Node

If you already have a node object from a previous query, navigate to it programmatically:

```typescript
import * as vscode from 'vscode';
import { navigateToNode } from './features/search';

// `node` obtained from previous searchNodes call
const workspaceRoot = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath;
await navigateToNode(node, workspaceRoot);

```

## Summary

Cross‑repository search in Code Review Graph works through a unified indexing strategy:

- **Unified Database**: All registered repositories populate a single SQLite `nodes` table with graph entities.
- **Global Queries**: The `searchNodes` method in [`src/backend/sqlite.ts`](https://github.com/tirth8205/code-review-graph/blob/main/src/backend/sqlite.ts) runs an unfiltered `LIKE` query against the combined index.
- **Live UI**: The QuickPick in [`src/features/search.ts`](https://github.com/tirth8205/code-review-graph/blob/main/src/features/search.ts) debounces input and queries all repos in real time.
- **Path Resolution**: Results are resolved from relative database paths to absolute workspace files for seamless navigation.

## Frequently Asked Questions

### How does the extension handle repositories with conflicting file paths?

The extension stores the full relative path from each repository root, including the repository directory structure. When resolving to an absolute path, it uses the workspace folder associated with that repository, ensuring that [`src/utils.ts`](https://github.com/tirth8205/code-review-graph/blob/main/src/utils.ts) in Repo A opens separately from [`src/utils.ts`](https://github.com/tirth8205/code-review-graph/blob/main/src/utils.ts) in Repo B.

### Is there a performance limit to how many repositories can be indexed?

The current implementation uses a simple SQLite `LIKE` query without Full‑Text Search (FTS) extensions. While the query scans all nodes, the limit parameter (default 20) caps the result set. Performance depends on total node count across all repos, but the lack of repository‑level filtering means query time scales with total graph size, not repository count.

### Can I search by node type or kind?

The `searchNodes` method currently filters only by name using the `LIKE` operator. The database schema stores `kind` (function, class, etc.) in a separate column, but the default implementation in [`src/backend/sqlite.ts`](https://github.com/tirth8205/code-review-graph/blob/main/src/backend/sqlite.ts) does not expose kind‑based filtering in the main search interface. You would need to extend the SQL query to include `AND kind = ?` clauses for type‑specific searches.

### What happens if a repository is removed from the workspace?

The extension maintains the SQLite database file for that repository until explicitly cleared. If the repository is removed from the workspace but the database persists, the search may return stale results. Re‑registering the repository or manually deleting its database file ensures the index stays synchronized with the actual workspace state.