How to Perform Cross-Repository Search Across Multiple Registered Repositories

The code-review-graph VS Code extension enables unified cross-repository search by maintaining a SQLite-backed knowledge graph that indexes all files from registered workspaces, allowing single queries to aggregate results across every added repository.

The code-review-graph extension transforms scattered codebases into a unified, searchable knowledge graph directly inside VS Code. By registering multiple repositories in your workspace, you unlock the ability to perform cross-repo search across all of them simultaneously without switching contexts. This article explains the architecture and implementation details of this feature based on the actual source code in tirth8205/code-review-graph.

Architecture of the Cross-Repository Search System

The Unified SQLite Knowledge Graph

At the core of the search capability lies a local SQLite database managed by src/backend/sqlite.ts. When a repository is opened, the extension stores a parsed representation of each file, tagging every entry with a unique repository identifier (repo_id). This design allows the system to distinguish which files belong to which registered repositories while maintaining a single, queryable index.

Repository Registration via the Onboarding Flow

Before a repository becomes searchable, it must be registered through the onboarding system implemented in src/onboarding/installer.ts. The installer records the absolute path of each repository in the repos table and triggers an initial indexing run. Only repositories present in this table are considered during cross-repo search operations.

export async function registerRepo(rootPath: string) {
  const db = await getDb();
  db.run('INSERT OR IGNORE INTO repos (path, name) VALUES (?, ?)', [rootPath, path.basename(rootPath)]);
  // Kick off an initial indexing run
  await indexRepository(rootPath);
}

Executing Cross-Repository Search Queries

The Search Implementation in search.ts

The actual query logic resides in src/features/search.ts. When a user submits a search term, the backend executes a SQL query that filters the files table based on the repo_id column, ensuring results are aggregated only from currently registered repositories.

export async function searchAcrossRepos(query: string): Promise<SearchResult[]> {
  // The SQLite helper lives in src/backend/sqlite.ts
  const db = await getDb();
  const stmt = db.prepare(`
    SELECT file_path AS filePath, repo_name AS repoName
    FROM files
    WHERE repo_id IN (SELECT id FROM repos)   -- all registered repos
      AND content LIKE ?
    LIMIT 100
  `);
  return stmt.all(`%${query}%`);
}

Triggering Search from the VS Code Interface

The extension exposes a command palette entry that invokes the search functionality. This command collects the user input and routes it to the backend via the extension's RPC channel, as implemented in src/features/search.ts.

// Triggered by the command palette entry "Code Review Graph: Search"
vscode.commands.registerCommand('codeReviewGraph.search', async () => {
  const query = await vscode.window.showInputBox({ prompt: 'Search all registered repos' });
  if (!query) { return; }

  // Send query to the backend (handled in src/features/search.ts)
  const results = await vscode.window.withProgress(
    { location: vscode.ProgressLocation.Notification, title: `Searching for "${query}"` },
    () => rpc.invoke('searchAcrossRepos', query)
  );

  // Show results in a quick‑pick list
  const item = await vscode.window.showQuickPick(
    results.map(r => ({ label: r.filePath, description: r.repoName }))
  );
  if (item) { vscode.workspace.openTextDocument(item.label).then(doc => vscode.window.showTextDocument(doc)); }
});

Maintaining the Search Index Across Repositories

Real-Time Updates with the File Watcher

To keep search results current without full re-scans, src/backend/watcher.ts monitors the file system for changes within all registered repositories. When files are modified, added, or deleted, the watcher incrementally updates the SQLite index, ensuring the cross-repo search reflects the latest codebase state.

Performance Optimizations

The extension creates a database index on the (repo_id, content) columns to accelerate cross-repo look-ups. This indexing strategy allows the SQL engine to quickly narrow down results to specific repositories before performing content matching, significantly improving query performance across large multi-repository workspaces.

Summary

  • The extension stores file metadata and content in a local SQLite database (src/backend/sqlite.ts) tagged with repository identifiers.
  • Repositories must be registered via src/onboarding/installer.ts to be included in the searchable graph.
  • Cross-repo queries are executed in src/features/search.ts using SQL that filters by registered repository IDs.
  • Real-time synchronization is handled by src/backend/watcher.ts through incremental indexing.
  • Database indexing on (repo_id, content) ensures fast search performance across multiple registered repositories.

Frequently Asked Questions

To include a new repository, use the onboarding command provided by the extension. The registerRepo function in src/onboarding/installer.ts inserts the repository path into the database and triggers an initial indexing run, making it immediately searchable alongside your other registered repositories.

Does the search index update automatically when files change?

Yes. The src/backend/watcher.ts module monitors all registered repositories for file system events. It incrementally updates the SQLite index when files are modified, added, or removed, ensuring cross-repo search results remain current without requiring manual refreshes.

What happens if I have ten repositories registered? Will search be slow?

The extension optimizes for multi-repository workflows by creating a composite index on (repo_id, content). This allows the query engine to first filter by repository ID before scanning content, maintaining fast performance even when searching across numerous large codebases.

Can I search using regular expressions or just simple text matching?

Based on the current implementation in src/features/search.ts, the search utilizes SQL LIKE patterns for content matching. While the architecture supports extending to full-text search indexes, the default behavior uses wildcard matching against the indexed content column.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →