How the GitNexus Rename Tool Performs Multi-File Refactoring Using Graph and Text Search

The GitNexus rename tool executes multi-file refactoring by first querying the knowledge graph for high-confidence symbol relationships, then running ripgrep to discover additional references via regex text search, tagging each edit with graph or text_search confidence levels before optionally applying changes in a preview-safe workflow.

The GitNexus rename tool provides a safe, coordinated approach to refactoring symbols across entire repositories by combining semantic graph analysis with brute-force text search. Unlike simple find-and-replace operations, this tool leverages the knowledge graph built during indexing to identify precise relationships while using ripgrep to catch edge cases like string literals or dynamic imports. Understanding how GitNexus handles multi-file refactoring using graph and text search helps developers confidently rename functions, classes, and variables without breaking downstream dependencies.

Tool Declaration and Schema Definition

The tool's interface and user guidance are defined in src/mcp/tools.ts, which specifies the JSON schema and behavioral contract. The schema requires new_name as the only mandatory parameter while allowing either symbol_name (string lookup) or symbol_uid (direct UID from prior tool results) for target identification.

Key parameters include:

  • dry_run: Boolean defaulting to true, enabling safe preview mode
  • file_path: Optional disambiguator for common symbol names
  • repo: Optional repository handle for multi-repo environments

The description explicitly tags each confidence level: graph for knowledge graph matches and text_search for regex-discovered references, advising users to review text_search results carefully.

Two-Phase Discovery Architecture

The implementation in src/mcp/local/local-backend.ts (lines 1151-1314) operates through complementary discovery phases to maximize reference coverage while maintaining precision.

Phase 1: Graph-Based Reference Discovery (High Confidence)

The tool first invokes the context lookup method to resolve the target symbol and fetch its incoming graph edges (calls, imports, extends, implements). This phase processes:

  1. The symbol's definition location
  2. All documented relationships from the knowledge graph

Edits collected during this phase receive the graph confidence tag. The implementation stores these in a Map<string, { file_path, edits[] }> keyed by file path, adding only the first occurrence per file to avoid duplicates. This logic spans lines 1121-1247 in local-backend.ts.

// Definition edit (high-confidence)
if (sym.filePath && sym.startLine) { … addEdit(..., 'graph'); }

// Incoming references from graph (callers, imports, extends, implements)
for (const ref of allIncoming) { … addEdit(..., 'graph'); }

Phase 2: Text Search for Missed References (Lower Confidence)

To catch dynamic imports, string literals, or undocumented call sites, the tool executes a repository-wide ripgrep search. The implementation in lines 1250-1284 constructs the following command:

const rgArgs = [
  '-l',
  '--type-add', 'code:*.{ts,tsx,js,jsx,py,go,rs,java,c,h,cpp,cc,cxx,hpp,hxx,hh,cs,php,swift}',
  '-t', 'code',
  `\\b${oldName}\\b`,
  '.',
];
const output = execFileSync('rg', rgArgs, { 
  cwd: repo.repoPath, 
  encoding: 'utf-8', 
  timeout: 5000 
});

The tool skips files already modified via graph edits (if (graphFiles.has(normalizedFile)) continue;), then performs line-by-line regex scans on remaining files. Matches receive the text_search confidence tag, indicating lower certainty requiring manual review.

Safety Mechanisms and Preview Mode

Before processing, assertSafePath (lines 71-78) validates that all file paths remain within the repository root, preventing path-traversal attacks. The rename logic also validates that new_name differs from the old name (lines 97-99), returning an error if they match.

The preview versus apply logic (lines 1304-1314) respects the dry_run parameter:

  • When dry_run: true (default): Returns a structured report without writing changes
  • When dry_run: false: Reads each file, applies global regex replacement (new RegExp(\\b${oldName}\\b, 'g')), and writes back to disk

The return object includes:

  • files_affected: Count of distinct files touched
  • graph_edits vs text_search_edits: Breakdown by confidence
  • changes: Array of edit details with line numbers and confidence tags
  • applied: Boolean indicating whether files were modified

Error Handling and Edge Cases

The implementation handles several failure modes explicitly:

Situation Response
Neither symbol_name nor symbol_uid provided Returns error: "Either symbol_name or symbol_uid is required" (lines 67-69)
Symbol not found or ambiguous Propagates the lookup result for caller resolution
Identical old and new names Returns error: "New name is the same as the current name" (lines 97-99)
Path traversal attempt Throws "Path traversal blocked" via assertSafePath

Test Coverage Validation

The tool's contract is verified through unit tests in two key files:

These tests ensure the implementation respects the schema defined in src/mcp/tools.ts and maintains the expected dispatch behavior.

Practical Usage Examples

await backend.callTool('rename', {
  symbol_name: 'fetchUser',
  new_name: 'retrieveUser',
  dry_run: true,  // Safe preview mode
});

Expected response structure:

{
  "status": "success",
  "old_name": "fetchUser",
  "new_name": "retrieveUser",
  "files_affected": 3,
  "total_edits": 5,
  "graph_edits": 2,
  "text_search_edits": 3,
  "changes": [
    {
      "file_path": "src/services/user.ts",
      "edits": [
        {
          "line": 12,
          "old_text": "function fetchUser(id) {",
          "new_text": "function retrieveUser(id) {",
          "confidence": "graph"
        }
      ]
    }
  ],
  "applied": false
}

Applying the Refactor

After reviewing the preview, apply changes by setting dry_run: false:

await backend.callTool('rename', {
  symbol_uid: 'func:fetchUser',
  new_name: 'retrieveUser',
  dry_run: false,
});

Post-execution, verify no unintended side effects occurred:

await backend.callTool('detect_changes', { repo: 'my-repo' });

Summary

  • Graph-based discovery provides high-confidence edits by analyzing knowledge graph relationships (calls, imports, inheritance) defined during indexing.
  • Text search supplementation uses ripgrep with word-boundary regex to catch dynamic or undocumented references, tagged with lower confidence for manual review.
  • Safety-first design requires explicit opt-in (dry_run: false) to modify files and includes path-traversal protection via assertSafePath.
  • Comprehensive metadata returns detailed edit reports distinguishing between graph and text_search confidence levels, enabling informed validation before application.
  • Source locations include src/mcp/tools.ts for schema definition and src/mcp/local/local-backend.ts (lines 1151-1314) for the core implementation.

Frequently Asked Questions

What distinguishes graph confidence from text_search confidence in GitNexus?

Graph confidence indicates the reference was discovered through the knowledge graph's semantic relationships (function calls, imports, class inheritance), offering high certainty that the symbol represents the actual code entity being renamed. Text_search confidence indicates the reference was found via regex pattern matching against the raw source code, which may include string literals, comments, or dynamic references that require human verification before acceptance.

How does the rename tool prevent security vulnerabilities?

The tool implements assertSafePath validation (lines 71-78 of local-backend.ts) to ensure all file paths remain within the repository root directory, blocking path-traversal attacks. Additionally, the default dry_run: true setting prevents accidental file modifications until the user explicitly reviews and approves the proposed changes.

Can I preview changes before modifying files?

Yes, the dry_run parameter defaults to true, causing the tool to return a complete report of proposed edits—including file paths, line numbers, old and new text, and confidence tags—without writing any changes to disk. Set dry_run: false only after validating the preview output matches your intended refactoring scope.

What should I do after executing a rename operation?

Run the detect_changes tool immediately after applying a rename (when dry_run: false) to verify no unexpected side effects or broken references occurred. This follow-up step validates the integrity of the codebase after the multi-file refactoring is complete.

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 →