# How to Use Refactoring Tools for Symbol Renaming in code-review-graph

> Safely rename symbols in code-review-graph using a graph-backed workflow. Preview changes, inspect IDs, and apply edits with powerful refactoring tools.

- Repository: [Tirth Kanani/code-review-graph](https://github.com/tirth8205/code-review-graph)
- Tags: how-to-guide
- Published: 2026-08-07

---

**Use the three-step graph-backed workflow in `code-review-graph` to safely rename symbols: preview the changes with `rename_preview()`, inspect the generated `refactor_id`, and apply edits via `apply_refactor()` with optional dry-run support.**

The `code-review-graph` repository provides **graph-backed refactoring tools** that enable safe, accurate symbol renaming across entire Python codebases. Unlike simple text replacement, these tools leverage the repository's knowledge graph to track every definition, call site, and import relationship. This guide explains how to use refactoring tools for symbol renaming in code-review-graph through both the CLI and Python API.

## The Three-Step Graph-Backed Workflow

The refactoring implementation in [`code_review_graph/refactor.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/refactor.py) follows a strict preview-then-apply pattern to prevent accidental modifications.

### Step 1: Preview the Rename

The `rename_preview()` function traverses the knowledge graph to locate the symbol definition and all reachable references. It constructs a list of edits targeting **CALLS**, **IMPORTS_FROM**, and **REFERENCES** edges that static search tools often miss.

According to the source code in [`code_review_graph/refactor.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/refactor.py) (lines 73-85), this function:
- Queries the graph store for the symbol's definition node
- Collects all inbound edges to determine affected files
- Stores the pending operation in a thread-safe `_pending_refactors` dictionary
- Returns a JSON object containing a unique `refactor_id`, edit list, and statistics

### Step 2: Inspect the Preview

Each preview receives a unique identifier (e.g., `a1b2c3d4`) that persists for **600 seconds** (`REFACTOR_EXPIRY_SECONDS = 600`). The preview JSON includes:
- The list of files to be modified
- Line-by-line edit coordinates
- Safety validation status (path traversal checks at lines 53-57)

### Step 3: Apply the Rename

Supply the `refactor_id` to `apply_refactor()` to execute the edits. As implemented in [`code_review_graph/refactor.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/refactor.py) (lines 86-95), this function:
- Validates the `refactor_id` exists in `_pending_refactors`
- Writes changes to source files (or returns diffs if `dry_run=True`)
- Automatically clears the preview from memory after successful application (lines 14-22)

## Why Graph-Backed Refactoring Matters

**Accuracy** – The knowledge graph captures dynamic import relationships and cross-module references that grep-based tools cannot resolve.

**Safety** – The 10-minute expiry window and path traversal validation (lines 53-57) prevent stale or malicious refactor operations from executing.

**Dry-Run Support** – Set `dry_run=True` in `apply_refactor()` (lines 34-42) to receive unified diffs without modifying disk, enabling code review before committing changes.

## CLI Implementation

The command-line interface in [`code_review_graph/cli.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/cli.py) exposes the refactoring workflow through two sub-commands.

The `refactor` sub-command (lines 42-46 and 92-99) forwards requests to `refactor_func(mode="rename", ...)` in [`code_review_graph/tools/refactor_tools.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/tools/refactor_tools.py). The `apply_refactor` sub-command invokes `apply_refactor_func()` (lines 33-38) to execute pending operations.

## Code Examples

### CLI Workflow

Generate a preview and apply the rename through the terminal:

```bash

# Step 1 – Preview the rename operation

code-review-graph refactor rename \
  --old-name helper \
  --new-name new_helper

# Response includes refactor_id for the next step

{
  "status": "ok",
  "summary": "Rename preview: helper -> new_helper, 5 edit(s). Use apply_refactor_tool(refactor_id='a1b2c3d4') to apply.",
  "refactor_id": "a1b2c3d4",
  "edits": [ … ]
}

```

```bash

# Step 2 – Review changes without writing (dry-run)

code-review-graph apply_refactor a1b2c3d4 --dry-run

# Step 3 – Execute the rename

code-review-graph apply_refactor a1b2c3d4

```

### Python API

Use the core functions directly from scripts or notebooks:

```python
from code_review_graph.refactor import rename_preview, apply_refactor
from code_review_graph.graph import GraphStore, find_project_root

# Initialize the graph store

root = find_project_root()
store = GraphStore(root)

# 1️⃣ Generate preview

preview = rename_preview(store, old_name="helper", new_name="new_helper")
if preview is None:
    raise RuntimeError("Symbol not found in graph")
print(f"Preview ID: {preview['refactor_id']} – {len(preview['edits'])} edits")

# 2️⃣ Dry-run to inspect diffs

dry = apply_refactor(preview['refactor_id'], root, dry_run=True)
print(dry['diffs']['src/module.py'])

# 3️⃣ Apply changes

result = apply_refactor(preview['refactor_id'], root, dry_run=False)
print(f"Applied {result['applied']} edit(s) to {len(result['files_modified'])} file(s)")

```

### Programmatic Wrapper

For tool integration, use the convenience functions in [`refactor_tools.py`](https://github.com/tirth8205/code-review-graph/blob/main/refactor_tools.py):

```python
from code_review_graph.tools.refactor_tools import refactor_func, apply_refactor_func

# Preview via wrapper

preview = refactor_func(mode="rename", old_name="helper", new_name="new_helper")
refactor_id = preview["refactor_id"]

# Dry-run then apply

apply_refactor_func(refactor_id, dry_run=True)
apply_refactor_func(refactor_id)

```

## Summary

- **Core Implementation**: `rename_preview()` and `apply_refactor()` live in [`code_review_graph/refactor.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/refactor.py), using a thread-safe `_pending_refactors` cache with 600-second expiry.
- **Graph Accuracy**: The tool analyzes **CALLS**, **IMPORTS_FROM**, and **REFERENCES** edges to find all symbol occurrences, including dynamic imports.
- **Safety Features**: Path traversal validation and mandatory preview steps prevent unauthorized or accidental file modifications.
- **CLI Integration**: [`code_review_graph/cli.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/cli.py) exposes `refactor` and `apply_refactor` commands that delegate to [`refactor_tools.py`](https://github.com/tirth8205/code-review-graph/blob/main/refactor_tools.py) wrappers.
- **Dry-Run Support**: Both the API and CLI support `dry_run` mode to preview unified diffs before committing changes.

## Frequently Asked Questions

### How does the graph improve renaming accuracy compared to text search?

The knowledge graph tracks semantic relationships through **CALLS**, **IMPORTS_FROM**, and **REFERENCES** edges. According to the [`code_review_graph/refactor.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/refactor.py) implementation, `rename_preview()` traverses these edges to locate definition sites and all consuming code, capturing dynamic imports and cross-module usage that static grep patterns would miss.

### What is the refactor_id and how long does it remain valid?

The `refactor_id` is a unique identifier generated during the preview phase and stored in `_pending_refactors`. As defined by `REFACTOR_EXPIRY_SECONDS = 600` in the source, previews expire after 10 minutes. The ID must be supplied to `apply_refactor()` within this window before the cache entry is invalidated.

### Can I review changes before modifying source files?

Yes. Both the Python API and CLI support dry-run mode. In [`code_review_graph/refactor.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/refactor.py) (lines 34-42), setting `dry_run=True` in `apply_refactor()` returns unified diffs without writing to disk. The CLI exposes this via the `--dry-run` flag on the `apply_refactor` sub-command.

### Which source files contain the core refactoring logic?

The primary logic resides in [`code_review_graph/refactor.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/refactor.py) (functions `rename_preview` and `apply_refactor`). CLI command definitions are in [`code_review_graph/cli.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/cli.py) (lines 42-46 and 92-99), while convenience wrappers are implemented in [`code_review_graph/tools/refactor_tools.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/tools/refactor_tools.py) (lines 33-38). Graph store utilities are imported from [`code_review_graph/graph.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/graph.py).