How the Multi-Repo Registry Enables Cross-Repository Search in code-review-graph
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, the resolve_repo function (lines 84-99) implements a deterministic lookup strategy:
- Alias lookup – If the input matches a registered alias, return the stored absolute path immediately.
- Direct path resolution – If not an alias, treat the input as a filesystem path and validate existence.
- 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) 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:
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 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 incode_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.
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 →