How Cross‑Repository Search Works in Code Review Graph: VS Code Knowledge Graph Deep Dive
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, 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. 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 (lines 68‑71), the extension executes:
const results = reader.searchNodes(value, 20);
The searchNodes implementation in src/backend/sqlite.ts (lines 302‑307) constructs a LIKE '%query%' clause against the name column:
// 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) 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:
// 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:
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:
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
nodestable with graph entities. - Global Queries: The
searchNodesmethod insrc/backend/sqlite.tsruns an unfilteredLIKEquery against the combined index. - Live UI: The QuickPick in
src/features/search.tsdebounces 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 in Repo A opens separately from 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 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.
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 →