How the Interactive Querying Mode Works in the code-graph-rag CLI

The cgr CLI provides an interactive querying mode that lets you ask natural-language questions about a codebase and receive answers in real time through a persistent REPL loop.

This interactive mode powers the core user experience of code-graph-rag (vitali87/code-graph-rag), transforming natural language into Cypher queries executed against a Memgraph knowledge graph. Understanding how this mode works helps you optimize your workflow when exploring unfamiliar codebases or debugging complex dependencies.


Overview of the Interactive Flow

The interactive querying mode follows a four-stage pipeline controlled by the start command in codebase_rag/cli.py:

Stage Action Source Location
Parse cgr start processes --ask-agent and flags; routes to async entry point codebase_rag/cli.py
Initialize main_async sets up the orchestrator and graph connection codebase_rag/main.py
Loop _run_interactive_loop runs the persistent REPL codebase_rag/main.py
Execute Cypher queries run against Memgraph; results render via Rich codebase_rag/services/graph_service.py

Each stage is implemented as an async function, ensuring the CLI remains responsive during LLM inference and graph queries.


Stage 1: CLI Entry Point and Argument Parsing

The start command in codebase_rag/cli.py defines the interactive querying interface. Key parameters include:

  • --ask-agent: Specifies the LLM that converts natural language to Cypher (or triggers the default REPL when omitted)
  • --interactive-setup: Launches a TUI for selecting directories to index before querying
  • --orchestrator: Configures the model that manages query planning

When --update-graph is absent and --ask-agent is present (or implied), the CLI invokes main_async rather than the batch indexing pipeline.


Stage 2: Asynchronous Initialization via main_async

The main_async function in codebase_rag/main.py coordinates the setup phase:


# Simplified flow based on source structure

async def main_async(
    repo_path: str,
    ask_agent: str | None,
    orchestrator: str,
    batch_size: int,
    # ... additional kwargs

):
    # 1. Load configuration via update_model_settings

    # 2. Establish Memgraph connection

    # 3. Delegate to interactive loop or single-shot handler

    if ask_agent:
        await _run_interactive_loop(...)
    else:
        await main_single_query(...)

This function resolves active projects, validates the target repository path, and prepares the Orchestrator model for Cypher generation.


Stage 3: The Interactive REPL in _run_interactive_loop

The core interactive querying mode lives in _run_interactive_loop within codebase_rag/main.py. This private async function implements a classic read-eval-print loop with graph-backed evaluation:

Loop Structure

async def _run_interactive_loop(
    target_repo_path: str,
    effective_batch_size: int,
    active_projects: list[str],
    ask_agent: str | None,
) -> None:
    """
    Persistent REPL for natural-language codebase queries.
    """
    # Initialize orchestrator and graph service

    orchestrator = load_model(ask_agent)
    graph = MemgraphIngestor.connect()
    
    while True:
        # 1. PROMPT: Capture user question

        try:
            question = typer.prompt("Ask about your codebase")
        except (EOFError, KeyboardInterrupt):
            print("\nExiting interactive mode.")
            break
            
        if not question.strip():
            continue
            
        # 2. GENERATE: Orchestrator produces Cypher

        cypher_query = await orchestrator.to_cypher(question)
        
        # 3. EXECUTE: Run against Memgraph

        results = graph.fetch_all(cypher_query)
        
        # 4. RENDER: Format as Rich table or JSON

        render_results(results)
        
        # 5. CONTINUE: Offer graceful exit

        if not typer.confirm("Ask another question?"):
            break

Key Design Decisions

  • typer.prompt provides cross-platform input handling with consistent styling
  • Graceful interruption: EOFError and KeyboardInterrupt (Ctrl-C) exit cleanly without stack traces
  • Empty input handling: Blank lines restart the loop rather than submitting wasteful queries
  • Confirmation prompts: The continuation check prevents accidental exits while maintaining discoverability

Stage 4: Query Execution and Result Rendering

The generated Cypher queries execute against Memgraph via the MemgraphIngestor.fetch_all method in codebase_rag/services/graph_service.py. Results flow through:

  1. Graph traversal: Node and relationship data retrieved from the knowledge graph
  2. Formatting layer: Rich tables for terminal display, or JSON for programmatic consumption (controlled by --output-format)
  3. Streaming: Partial results appear as they arrive when supported by the underlying model

Practical Usage Examples

Launch Persistent Interactive Session

cgr start --repo-path . --interactive-setup

The --interactive-setup flag opens a TUI for selecting which directories to index, then drops into the REPL.

Single Question Without REPL

cgr start --repo-path . --ask-agent "Which functions call process_data?"

Returns one answer and exits—ideal for shell scripts or CI pipelines.

JSON Output for Integration

cgr start --repo-path . \
    --ask-agent "List all classes inheriting from BaseModel" \
    --output-format json

Produces machine-parseable output instead of formatted tables.


Configuration and Performance Tuning

The interactive querying mode respects several configuration layers in codebase_rag/config.py:

Parameter Effect on Interactive Mode
effective_batch_size Controls chunking of large result sets in _run_interactive_loop
orchestrator model Determines Cypher generation quality and latency
active_projects Scopes the graph namespace for multi-repo workspaces

Adjust these via flags or environment variables to optimize for latency versus accuracy.


Error Handling and Edge Cases

The _run_interactive_loop function implements defensive patterns:

  • Invalid Cypher generation: The orchestrator may produce malformed queries; the loop catches execution errors and prompts for rephrasing
  • Empty result sets: Clearly distinguished from execution failures
  • Graph disconnection: Reconnection logic before query execution
  • Token limits: Large responses trigger pagination warnings

Summary

  • The cgr start command in codebase_rag/cli.py is the entry point for interactive querying mode, parsing --ask-agent and --interactive-setup flags
  • main_async in codebase_rag/main.py initializes the async runtime and routes to either the REPL or single-shot handler
  • _run_interactive_loop implements the persistent query-evaluate-render cycle using typer.prompt, orchestrator-driven Cypher generation, and MemgraphIngestor.fetch_all execution
  • Output formatting defaults to Rich tables but supports JSON via --output-format
  • Graceful exit via Ctrl-C or negative confirmation prevents data loss or orphaned processes

Frequently Asked Questions

How do I exit the interactive querying mode without killing the terminal?

Press Ctrl-C or answer "no" to the "Ask another question?" prompt. The _run_interactive_loop function catches KeyboardInterrupt and EOFError exceptions to exit cleanly without stack traces.

Can I use the interactive mode without indexing the graph first?

No. The interactive querying mode requires a populated Memgraph knowledge graph. Run cgr start --update-graph first, or use --interactive-setup which combines directory selection with initial indexing.

What happens if the orchestrator generates invalid Cypher?

The loop catches execution errors from MemgraphIngestor.fetch_all, displays a descriptive message, and returns to the prompt. Rephrase your question or check the --orchestrator model configuration if errors persist.

Is the interactive mode available in non-async contexts?

All entry points in codebase_rag/main.py use asyncio.run() wrappers internally. The CLI surface is synchronous, but main_async and _run_interactive_loop are implemented as async functions to support concurrent LLM streaming and graph queries.

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 →