# How the Multi-Repo Registry Enables Cross-Repository Search in code-review-graph

> Discover how code-review-graph's multi-repo registry facilitates cross-repository search. Learn how it maps aliases to paths for simultaneous querying across SQLite databases.

- Repository: [Tirth Kanani/code-review-graph](https://github.com/tirth8205/code-review-graph)
- Tags: how-to-guide
- Published: 2026-07-18

---

**The multi-repo registry in code-review-graph enables cross-repository search by maintaining a central JSON registry at `~/.code-review-graph/registry.json` that maps repository aliases to absolute paths, allowing the `resolve_repo` function and `ConnectionPool` to route queries across multiple independent SQLite graph databases simultaneously.**

The code-review-graph project provides a graph-based analysis layer for code repositories. To support workflows that span multiple codebases, the multi-repo registry acts as a directory service that eliminates the need for hardcoded paths. By tracking repository locations, aliases, and external data directories in a single registry file, the system transparently resolves abstract identifiers to concrete graph database connections.

## Registry Architecture and Resolution Strategy

### The Central Registry Store

The registry persists as `~/.code-review-graph/registry.json`. Each entry records a repository's absolute path, an optional alias for shorthand reference, and an optional external data directory. This structure decouples repository identity from filesystem location, enabling symbolic access to projects regardless of their physical directory names.

### Three-Step Repository Resolution

In [`code_review_graph/registry.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/registry.py), the `resolve_repo` function (lines 84-99) implements a deterministic lookup strategy:

1. **Alias lookup** – If the input matches a registered alias, return the stored absolute path immediately.
2. **Direct path resolution** – If not an alias, treat the input as a filesystem path and validate existence.
3. **Current working directory fallback** – If no argument is provided, default to the process's CWD.

This hierarchy ensures that scripts can reference repositories symbolically via alias or explicitly via path without modifying calling code.

## Connection Management for Distributed Graphs

### The ConnectionPool LRU Cache

Cross-repository search requires maintaining concurrent connections to multiple SQLite databases. The `ConnectionPool` class (lines 221-267 in [`code_review_graph/registry.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/registry.py)) implements an LRU (Least Recently Used) cache that retains open connections to graph databases. When the pool reaches its size limit, it evicts the least-recently-used connection to accommodate new repositories. This design allows a single process to query dozens of repositories without exhausting file descriptors.

### Database File Discovery

Once `resolve_repo` identifies a repository's absolute path, the system locates the graph database at `<repo_path>/.code-review-graph/db.sqlite`. The connection pool maps these file paths to persistent SQLite connections, ensuring that repeated queries to the same repository reuse the existing handle rather than reopening the file.

## Querying Across Repositories

To execute a search across multiple registered repositories, iterate over `Registry.list_repos()` and aggregate results from each connection:

```python
from pathlib import Path
from code_review_graph.registry import Registry, ConnectionPool, resolve_repo

# Initialize registry and connection pool

reg = Registry()
pool = ConnectionPool(max_size=5)

def search_across_repos(sql: str, *params):
    """Execute SQL query across all registered repositories."""
    results = []
    
    for entry in reg.list_repos():
        # Resolve alias to absolute path

        repo_path = resolve_repo(reg, entry.get("alias"))
        if not repo_path:
            continue
            
        # Locate the graph database file

        db_file = Path(repo_path) / ".code-review-graph" / "db.sqlite"
        
        # Acquire cached connection from pool

        conn = pool.get(str(db_file))
        
        # Execute query and collect results

        cursor = conn.execute(sql, params)
        results.extend([dict(row) for row in cursor.fetchall()])
        
    return results

# Search for all nodes labeled "function_def" across every registered repo

function_definitions = search_across_repos(
    "SELECT * FROM nodes WHERE label = ?", "function_def"
)

```

This pattern leverages the registry as a service discovery layer, enabling tools to treat collections of independent repositories as a unified searchable corpus.

## CLI Integration via registry_tools.py

The [`code_review_graph/tools/registry_tools.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/tools/registry_tools.py) module exposes these capabilities through command-line interfaces. Commands like `code-review-graph registry register` and `code-review-graph registry list` manipulate the underlying JSON registry, while search tools utilize `resolve_repo` and the connection pool to execute cross-repository queries without requiring users to specify absolute paths manually.

## Summary

- The **multi-repo registry** stores repository metadata in `~/.code-review-graph/registry.json`, mapping aliases to absolute paths and optional external data directories.
- **`resolve_repo`** (lines 84-99 in [`code_review_graph/registry.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/registry.py)) implements a three-tier resolution strategy: alias lookup, direct path validation, and CWD fallback.
- The **`ConnectionPool`** (lines 221-267) provides an LRU cache of SQLite connections, enabling concurrent access to multiple repository graph databases without file handle exhaustion.
- **Cross-repository search** is achieved by iterating over `Registry.list_repos()`, resolving each entry to its database file, and executing queries against pooled connections.

## Frequently Asked Questions

### How does the registry handle repository relocations?

When a repository moves on the filesystem, the stored absolute path in `~/.code-review-graph/registry.json` becomes stale. Users must run the registration command again to update the path, or manually edit the registry file. The `resolve_repo` function validates path existence during step two of its resolution process, returning `None` for invalid paths to prevent runtime errors.

### What is the maximum number of repositories the ConnectionPool can handle simultaneously?

The `ConnectionPool` constructor accepts a `max_size` parameter that limits the number of open SQLite connections maintained in memory. While the JSON registry can track an unlimited number of registered repositories, the pool only keeps the `max_size` most recently accessed databases open. Subsequent queries to evicted repositories incur a reconnection penalty when the pool reopens their SQLite files.

### Can the registry reference repositories on network-mounted storage?

Yes, the registry stores absolute filesystem paths without restriction. As long as the path is accessible from the current execution context and resolves to a valid directory containing `.code-review-graph/db.sqlite`, the `resolve_repo` function and `ConnectionPool` operate identically on local, NFS, or other mounted volumes. The abstraction layer treats all paths uniformly once resolved.

### How does cross-repository search avoid naming conflicts between repositories?

Each repository maintains its own isolated SQLite database file. The `ConnectionPool` routes queries to specific file paths returned by `resolve_repo`, ensuring that graph nodes from different repositories never mix in the same SQL connection. Results are aggregated in Python memory only after retrieval from individual database cursors, preserving strict repository boundaries during the search process.