# Roo Code Diff Strategy System: How Multi-Search-Replace Handles File Edits

> Explore the Roo Code diff strategy system powered by Multi-Search-Replace. Learn how it efficiently handles file edits with sequential, fuzzy search-replace operations and indentation preservation.

- Repository: [Roo Code/Roo-Code](https://github.com/RooCodeInc/Roo-Code)
- Tags: internals
- Published: 2026-04-26

---

**The Roo Code diff strategy system implements a pluggable architecture centered on the `MultiSearchReplace` strategy, which processes any number of independent search-replace blocks in a single request, applying them sequentially with fuzzy matching and indentation preservation.**

Roo Code, an open-source AI coding assistant from RooCodeInc/Roo-Code, abstracts all file modifications behind a **diff strategy system**. This architecture delegates editing operations to strategy implementations that translate structured diff payloads into final file content. The system centers on the `DiffStrategy` interface, which the default `MultiSearchReplaceDiffStrategy` implements to handle complex multi-part edits.

## How the Diff Strategy System Works

At its core, the diff strategy system defines a contract through the `DiffStrategy` interface in [`src/shared/tools.ts`](https://github.com/RooCodeInc/Roo-Code/blob/main/src/shared/tools.ts). This interface requires three methods: `applyDiff`, `getName`, and `getProgressStatus`.

When a task executes, [`src/core/task/Task.ts`](https://github.com/RooCodeInc/Roo-Code/blob/main/src/core/task/Task.ts) instantiates the strategy and attaches it to the task context:

```typescript
this.diffStrategy = new MultiSearchReplaceDiffStrategy()

```

Every `apply_diff` tool call forwards its `diff` parameter to this strategy (line 534), which then handles the transformation logic independently of the task orchestration.

## Multi-Search-Replace Syntax and Structure

The `MultiSearchReplace` strategy expects a specific marker syntax derived from Git conflict notation but optimized for AI-generated edits:

```

<<<<<<< SEARCH
:start_line:5
-------
exact text to find
=======
replacement text
>>>>>>> REPLACE

```

The `:start_line:` directive is optional but recommended—it indicates where the search block is expected, enabling faster exact matching. Content can include escaped markers using a leading backslash when these sequences appear literally in code. Multiple blocks can be concatenated in a single request, and the strategy processes them **independently** and **in order of start line**, ensuring deterministic left-to-right application.

## Processing Multiple Search-Replace Operations

The `applyDiff` method in [`src/core/diff/strategies/multi-search-replace.ts`](https://github.com/RooCodeInc/Roo-Code/blob/main/src/core/diff/strategies/multi-search-replace.ts) handles multiple operations through a six-stage pipeline:

### Step 1: Parse and Sort Blocks

The strategy first extracts all search-replace blocks using a regex matcher (lines 289-293):

```typescript
matches = [...diffContent.matchAll(/(?:^|\n)(?<!\\)<<<<<<</g)]

```

It then sorts blocks by their `:start_line:` value. This sorting guarantees that later replacements see the effects of earlier edits, maintaining logical consistency when multiple changes affect the same file.

### Step 2: Locate Matches with Fallback Logic

For each block, the strategy attempts three matching approaches in sequence (lines 783-904, 997-1014, and 1019-1035):

1. **Exact Match**: When `:start_line:` is provided, verify content at that specific location
2. **Fuzzy Search**: If exact similarity falls below the configurable threshold, perform a buffered middle-out search within `BUFFER_LINES` (40 lines) of context  
3. **Aggressive Stripping**: Remove line numbers and retry matching if previous methods fail

### Step 3: Validation Guards

Before applying any change, the strategy validates the block (lines 38-57 and 51-67):

- Rejects identical search and replace content
- Blocks empty search strings  
- Validates marker sequencing through `validateMarkerSequencing`

### Step 4: Apply with Indentation Preservation

Upon validation, the strategy captures the original indentation of matched lines, then preserves relative indentation for each replacement line (lines 666-698). It builds a new `resultLines` array while maintaining a running `delta` to adjust indices for subsequent blocks (lines 506-508). This ensures replacement text maintains structural alignment with the original file regardless of the indentation present in the diff payload.

## Fuzzy Matching Implementation

The fuzzy matching system uses **Levenshtein distance** to calculate similarity:

**Similarity** = `1 - (distance / maxLength)`

This calculation resides in the `getSimilarity` function (lines 9-31). The `fuzzyThreshold` parameter defaults to 1.0 for exact matches but is configurable through the UI, which presents the scale as "0% → 1.0 (exact)". The `BUFFER_LINES` constant of 40 provides context windows before and after the supplied `:start_line:`, keeping search operations performant while accommodating minor code drift.

## Practical Example: Two Independent Replacements

Consider updating both a logging statement and a function return value in one request:

```typescript
const diff = `
<<<<<<< SEARCH
:start_line:12
-------
console.log("old value");
=======
console.log("new value");
>>>>>>> REPLACE

<<<<<<< SEARCH
:start_line:45
-------
function foo() { return 1; }
=======
function foo() { return 2; }
>>>>>>> REPLACE
`;

const { success, content, failParts } = await applyDiffTool({
  path: "src/example.ts",
  diff,
});

```

The first block updates line 12, while the second targets line 45. Because the strategy sorts by `start_line` and maintains a running `delta`, the second replacement automatically accounts for any line shifts caused by the first edit.

## Key Files in the Diff Strategy Subsystem

Understanding the complete architecture requires examining these specific files:

- **[`src/core/diff/strategies/multi-search-replace.ts`](https://github.com/RooCodeInc/Roo-Code/blob/main/src/core/diff/strategies/multi-search-replace.ts)**: Core implementation containing `MultiSearchReplaceDiffStrategy` with fuzzy matching, indentation preservation, and block processing logic

- **[`src/shared/tools.ts`](https://github.com/RooCodeInc/Roo-Code/blob/main/src/shared/tools.ts)**: Declares the `DiffStrategy` interface, registers available strategies, and defines the `apply_diff` tool contract

- **[`src/core/task/Task.ts`](https://github.com/RooCodeInc/Roo-Code/blob/main/src/core/task/Task.ts)**: Task orchestration that instantiates the diff strategy (line 534) and routes tool calls to the appropriate handler

- **[`src/webview-ui/src/utils/parseUnifiedDiff.ts`](https://github.com/RooCodeInc/Roo-Code/blob/main/src/webview-ui/src/utils/parseUnifiedDiff.ts)**: Frontend parser for unified diff format, enabling the UI to render pending edits

- **[`src/webview-ui/src/utils/highlightDiff.ts`](https://github.com/RooCodeInc/Roo-Code/blob/main/src/webview-ui/src/utils/highlightDiff.ts)**: Syntax highlighting component that uses the same marker conventions as the backend strategy

## Summary

- Roo Code implements a **pluggable diff strategy architecture** centered on the `DiffStrategy` interface
- The default `MultiSearchReplace` strategy handles **any number of search-replace blocks** in a single request
- Blocks are **sorted by start line** and applied sequentially with a running delta to maintain index accuracy  
- **Fuzzy matching** with configurable thresholds and 40-line buffering accommodates minor code drift
- **Indentation preservation** ensures replacement text maintains structural alignment with original code
- Per-block failure reporting enables granular error handling and targeted retry attempts

## Frequently Asked Questions

### What is the default diff strategy in Roo Code?

Roo Code uses the `MultiSearchReplaceDiffStrategy` as its default and currently only shipped implementation. According to the source code in [`src/core/task/Task.ts`](https://github.com/RooCodeInc/Roo-Code/blob/main/src/core/task/Task.ts), this strategy is instantiated for every task and handles all `apply_diff` tool invocations by implementing the `DiffStrategy` interface with `applyDiff`, `getName`, and `getProgressStatus` methods.

### How does Roo Code handle multiple search-replace blocks in one request?

The strategy parses all blocks using regex extraction, sorts them by their optional `:start_line:` directive, and processes them sequentially. It maintains a running `delta` variable that adjusts line indices for subsequent blocks, ensuring that earlier edits shift the target locations of later edits appropriately. This deterministic left-to-right application prevents conflicts when multiple changes affect the same file.

### What happens if the search text doesn't match exactly?

If exact matching fails or similarity falls below the `fuzzyThreshold`, the strategy falls back to a buffered middle-out fuzzy search within 40 lines of the specified start position. If that fails, it attempts an aggressive line-number stripping pass. The similarity calculation uses Levenshtein distance normalized by maximum length, configurable via the UI from 0% to 100% (1.0 exact).

### How does the diff strategy preserve code indentation?

During replacement, the strategy captures the original indentation of the matched search block, then applies that indentation to each line of the replacement content (lines 666-698 in [`multi-search-replace.ts`](https://github.com/RooCodeInc/Roo-Code/blob/main/multi-search-replace.ts)). This preserves the relative indentation structure, ensuring that inserted code maintains the same nesting level and alignment as the code it replaces, regardless of the indentation present in the diff payload itself.