How to Configure Capture Selection for Relationship Types in Code-Graph-RAG
Set the CGR_CAPTURE environment variable in your .env file or export it directly to enable, disable, or mix relationship type groups (like calls, io, types) using + prefixes, - prefixes, all, or none tokens.
Configuring capture selection for relationship types in Code-Graph-RAG lets you control which edges appear in your Neo4j-style code graph. This is essential for keeping graph sizes manageable and focusing analysis on relevant relationships. The system organizes relationship types into named capture groups and provides a flexible token-based API for runtime selection.
Understanding Capture Groups
Relationship types in Code-Graph-RAG are grouped logically in codebase_rag/constants/graph.py. The CAPTURE_GROUP_RELS dictionary (lines 79-86) defines these mappings:
| Capture Group | Relationship Types |
|---|---|
| structure | CONTAINS_PACKAGE, DEFINES, CONTAINS_MODULE, CONTAINS_CLASS, CONTAINS_FUNCTION |
| calls | CALLS, REFERENCES, INSTANTIATES |
| types | INHERITS, IMPLEMENTS, MIXIN, OVERRIDES |
| imports | IMPORTS, EXPORTS, RE_EXPORTS |
| io | READS_FROM, WRITES_TO, FLOWS_TO, EXPOSES, RESOLVES_TO |
| findings | HAS_SMELL, HAS_VULNERABILITY, HAS_BUG, HAS_PERFORMANCE_ISSUE |
Source: graph.py#L79-L86
By default, only four groups are enabled: structure, calls, types, and imports. The io and findings groups are excluded unless explicitly requested.
How Capture Selection Works
The selection engine lives in codebase_rag/capture.py. Understanding its mechanics helps you construct precise capture specifications.
Token Resolution
The _resolve_token function (lines 70-78) handles individual tokens:
- First, it checks if the token matches a capture group name (e.g.,
io) and returns all relationships in that group - If no group matches, it checks for a single relationship type (e.g.,
writes_to)
Source: capture.py#L70-L78
Processing Rules in resolve_capture
The main resolve_capture function (lines 88-115) processes tokens left-to-right with these semantics:
none— clears all relationships (empty set)all— enables every relationship type (_ALL_RELS)+prefixor no prefix — adds relationships-prefix— removes relationships- Unknown tokens — generates a warning, continues processing
Source: capture.py#L88-L115
The split_spec function (lines 18-30) parses raw strings by splitting on commas, semicolons, or spaces.
Source: capture.py#L18-L30
Soft Dependencies
Some relationships require companions to be meaningful. The _SOFT_DEPENDENCIES dict (lines 13-15) warns if OVERRIDES is enabled without INHERITS:
_SOFT_DEPENDENCIES = {cs.RelationshipType.OVERRIDES: cs.RelationshipType.INHERITS}
Source: capture.py#L13-L15
Environment-Based Configuration
The default_capture() function (lines 33-37) reads CGR_CAPTURE from your environment:
def default_capture() -> CaptureSelection:
from .config import settings
return resolve_capture(split_spec(settings.CGR_CAPTURE))
Source: capture.py#L33-L37
Set this in your .env file or shell:
# .env
CGR_CAPTURE=all,-io
Practical Configuration Examples
Enable Only Specific Groups
# Structure and calls only, nothing else
CGR_CAPTURE=none,structure,calls
Exclude a Single Relationship from an Enabled Group
# All default relationships except FINDINGS group, minus WRITES_TO specifically
CGR_CAPTURE=all,-findings,-writes_to
Complex Mixed Selection
# Start empty, add IO group, remove it entirely, then add back just FLOWS_TO
CGR_CAPTURE=none,io,-io,flows_to
This sequence demonstrates left-to-right evaluation: the final set contains only FLOWS_TO.
Programmatic API Usage
from codebase_rag.capture import resolve_capture, split_spec, default_capture
from codebase_rag.graph_loader import load_graph
# Method 1: Direct token construction
tokens = split_spec("calls,reads_from,writes_to")
selection = resolve_capture(tokens)
print(selection.enabled_rels)
# {RelationshipType.CALLS, RelationshipType.REFERENCES,
# RelationshipType.INSTANTIATES, RelationshipType.READS_FROM,
# RelationshipType.WRITES_TO}
# Method 2: Use environment-driven default
graph = load_graph(
project_path="my_project",
capture=default_capture() # Reads CGR_CAPTURE env var
)
Integration with Graph Loading
When codebase_rag/graph_loader.py builds your graph, it applies the CaptureSelection to filter edges before persistence. Only relationships in CaptureSelection.enabled_rels are written to Neo4j, along with their associated node labels. This keeps query performance high and storage costs low for large codebases.
Key Source Files
| File | Purpose |
|---|---|
codebase_rag/constants/graph.py |
RelationshipType enum, CaptureGroup enum, CAPTURE_GROUP_RELS mapping |
codebase_rag/capture.py |
Token parsing (split_spec), resolution (_resolve_token, resolve_capture), default capture (default_capture) |
codebase_rag/config.py |
Settings object containing CGR_CAPTURE environment binding |
codebase_rag/graph_loader.py |
Consumes CaptureSelection to filter edges during graph construction |
Summary
- Capture groups organize relationship types into logical sets defined in
constants/graph.py - Token syntax uses
all,none, group names, and individual types with+/-prefixes - Left-to-right evaluation allows complex additive and subtractive specifications
- Environment variable
CGR_CAPTUREdrives default capture selection viadefault_capture() - Soft dependencies warn when companion relationships are missing
Frequently Asked Questions
What is the default capture configuration in Code-Graph-RAG?
The default enables structure, calls, types, and imports groups. This is defined by DEFAULT_CAPTURE_GROUPS in the constants module. The io and findings groups are excluded by default to minimize graph size and focus on structural and call relationships.
Can I enable individual relationships without using capture groups?
Yes. Tokens that don't match group names are checked against individual RelationshipType values. For example, CGR_CAPTURE=none,calls,-instantiates,writes_to enables CALLS and REFERENCES from the calls group, excludes INSTANTIATES, and adds the single WRITES_TO relationship from the IO group.
What happens if I specify conflicting tokens like io,-io,io?
The left-to-right evaluation applies each operation sequentially. io enables all IO relationships, -io removes them all, and the final io re-enables them. The effective result is the IO group being enabled. This sequential semantics lets you build complex selections through explicit overrides.
How do I verify which relationships are actually enabled?
Inspect the enabled_rels attribute of the CaptureSelection object. When using the programmatic API, print selection.enabled_rels after calling resolve_capture(). The set contains the RelationshipType enum values that will be included in your graph.
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 →