# Managing Multiple Projects in a Shared Graph with cgr CLI

> Effectively manage multiple projects in a shared graph using cgr CLI project namespaces. Isolate codebases while enabling cross-project queries and incremental updates.

- Repository: [Vitali Avagyan/code-graph-rag](https://github.com/vitali87/code-graph-rag)
- Tags: how-to-guide
- Published: 2026-08-15

---

**The cgr CLI uses project namespaces to isolate multiple codebases within a single graph database while preserving cross-project query capabilities and enabling incremental updates.**

Code-Graph-RAG (`cgr`) is an open-source tool that builds language-agnostic code graphs for retrieval-augmented generation. The `cgr` command-line interface allows you to capture, store, and query source code from **multiple projects** within a single shared graph without conflicts. This guide explains how the project namespace system works and how to manage multi-project workflows using commands defined in [`codebase_rag/main.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/main.py).

---

## How Project Namespaces Work in cgr

Every node and edge in a cgr graph carries a **project attribute** that identifies its originating codebase. When you run `cgr capture`, the CLI extracts this value from the `--project` flag and attaches it to all captured entities via decorators in [`codebase_rag/decorators.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/decorators.py).

The architecture separates concerns across three layers:

1. **Capture Layer** ([`codebase_rag/capture.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/capture.py)) — Parses source files using Tree-Sitter and produces normalized `Node` and `Edge` objects.

2. **Graph-Update Layer** ([`codebase_rag/graph_updater.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/graph_updater.py)) — Persists captured data to the backing database (Memgraph by default), merges duplicates based on signature + project, and ensures idempotent updates.

3. **Query Layer** ([`codebase_rag/graph_loader.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/graph_loader.py) and CLI commands in [`codebase_rag/main.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/main.py)) — Loads graph data for read operations with optional project filtering.

This design means **projects coexist peacefully**: same-named functions from different codebases remain distinct because their `project` attributes differ, yet you can still query across all projects when needed.

---

## Adding Projects to a Shared Graph

### Capturing Your First Project

Initialize the graph with any codebase by specifying a unique project name:

```bash
cgr capture ./my-api --project my-api

```

The `capture` sub-command in [`codebase_rag/main.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/main.py) forwards the path to [`codebase_rag/capture.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/capture.py), which walks the directory, parses supported files, and yields entities. The `GraphUpdater` class in [`codebase_rag/graph_updater.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/graph_updater.py) then writes these to the database with `project: "my-api"` labels.

### Adding Subsequent Projects

Capture additional codebases using different `--project` values:

```bash
cgr capture ./shared-lib --project shared-lib
cgr capture ./legacy-service --project legacy-service

```

Each invocation creates or updates only the nodes and edges belonging to that project. Existing data from other projects remains untouched.

### Incremental Updates for Existing Projects

Re-running capture on the same project updates changed entities without duplicating unchanged ones:

```bash
cgr capture ./my-api --project my-api

```

The deduplication logic in [`codebase_rag/graph_updater.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/graph_updater.py) matches nodes by their composite key (symbol signature + project) and performs **MERGE** operations rather than blind inserts.

---

## Querying Across and Within Projects

### Project-Agnostic Queries (All Projects)

Omit project constraints to search the entire graph:

```bash
cgr query "MATCH (f:Function) RETURN f.name, f.project ORDER BY f.project"

```

This executes through the query handler in [`codebase_rag/main.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/main.py), which passes the Cypher statement to [`codebase_rag/graph_loader.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/graph_loader.py) for execution against Memgraph.

### Project-Specific Isolation

Filter results to a single project using Cypher `WHERE` clauses:

```bash
cgr query "MATCH (f:Function) WHERE f.project = 'my-api' RETURN f.name, f.file_path"

```

Or combine with other predicates:

```bash
cgr query "
  MATCH (f:Function)
  WHERE f.project = 'shared-lib' AND f.name CONTAINS 'validate'
  RETURN f.name, f.docstring
"

```

### Cross-Project Relationship Analysis

The project attribute on edges enables powerful cross-project queries. Find calls that span project boundaries:

```bash
cgr query "
  MATCH (caller:Function)-[c:CALLS]->(callee:Function)
  WHERE caller.project <> callee.project
  RETURN caller.name, caller.project, callee.name, callee.project
"

```

Or locate which projects depend on `shared-lib` functions:

```bash
cgr query "
  MATCH (consumer:Function)-[:CALLS]->(lib:Function {project: 'shared-lib'})
  RETURN DISTINCT consumer.project AS dependent_project, count(*) AS call_count
  ORDER BY call_count DESC
"

```

---

## Core Implementation Files

Understanding these source files helps troubleshoot multi-project issues and extend cgr functionality:

- [`codebase_rag/main.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/main.py) — Defines CLI entry points including `capture`, `query`, and `serve` sub-commands. Parses `--project` arguments and orchestrates calls to capture and update layers.

- [`codebase_rag/graph_updater.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/graph_updater.py) — Contains `GraphUpdater` class with `update_graph()` method that handles node/edge persistence, project attribute injection, and merge-on-conflict logic.

- [`codebase_rag/graph_loader.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/graph_loader.py) — Provides `GraphLoader` class for read-only graph access with helper methods for project-scoped queries.

- [`codebase_rag/capture.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/capture.py) — Implements `capture_directory()` and language-specific capture functions that produce intermediate representations before graph persistence.

- [`codebase_rag/decorators.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/decorators.py) — Supplies `@with_project` decorator that attaches project metadata to captured entities during the capture pipeline.

---

## Best Practices for Multi-Project Graphs

1. **Use consistent project naming** — Choose stable identifiers (repository names or package names) since the project attribute becomes part of node identities. Avoid spaces and special characters that complicate Cypher queries.

2. **Document project relationships** — The cross-project query patterns above help visualize architecture. Consider scheduling periodic queries to detect unwanted coupling between systems.

3. **Separate staging and production captures** — Use project names like `my-api-staging` and `my-api-prod` if you need to compare code graphs across environments.

4. **Monitor graph growth** — Each project adds nodes and edges. Use `cgr query "MATCH (n) RETURN count(n)"` periodically to track size and plan database capacity.

---

## Summary

- The `cgr capture --project <name>` command isolates each codebase using a project namespace attribute on every node and edge.

- Multiple projects coexist in one shared graph without collision, enabling both isolated per-project queries and cross-project relationship analysis.

- Incremental updates are automatic—re-capturing a project merges changes without duplicating existing data, handled by [`codebase_rag/graph_updater.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/graph_updater.py).

- The `cgr query` command accepts any Cypher, with `WHERE f.project = '...'` clauses providing fine-grained isolation when needed.

- Cross-project edges (CALLS, IMPORTS, etc.) retain source and target project attributes, making boundary-spanning analysis straightforward.

---

## Frequently Asked Questions

### How does cgr prevent name collisions between functions in different projects?

Every captured entity receives a `project` attribute via decorators in [`codebase_rag/decorators.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/decorators.py). The `GraphUpdater` in [`codebase_rag/graph_updater.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/graph_updater.py) uses this attribute as part of the merge key, so `my-api/utils.py:parse()` and `shared-lib/utils.py:parse()` remain distinct nodes despite identical local names.

### Can I remove a single project without affecting others?

As of the current implementation, cgr does not include a dedicated `remove` sub-command. You can delete project-specific nodes manually using Cypher: `cgr query "MATCH (n {project: 'old-project'}) DETACH DELETE n"`. Full project lifecycle management may be added in future releases.

### What happens if I capture the same directory with two different project names?

cgr treats these as separate projects—nodes and edges are duplicated with different `project` values. Query both with `WHERE n.project IN ['name-a', 'name-b']` or deduplicate downstream. Avoid this pattern unless you intentionally need multiple views of identical code.

### Does the project attribute affect query performance?

No significant impact. The `project` property is indexed by default in [`codebase_rag/graph_updater.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/graph_updater.py) setup routines, making `WHERE f.project = '...'` filters efficient even in graphs containing millions of nodes across dozens of projects.