TL;DR: AI rewrites code you didn't ask it to touch for two separate reasons: your prompt never named what's off-limits, and you asked for a full file back instead of a diff. Scope the change explicitly and ask for a diff, not a rewrite, and the edit becomes something you can actually review.
Why Does AI Rewrite Code I Didn't Ask It to Touch?
Two things are usually stacked on top of each other, and treating them as one fuzzy problem is why "just be more specific" only half works. Either your prompt never told the model what counts as out of scope, or you asked it to hand back a whole file instead of a change, which forces a full rewrite even when the actual edit is three lines. Neither is the model being careless. Both are a direct result of what the prompt did and didn't specify.
The classic complaint, "ChatGPT rewrites the whole file for a one-line fix," is really two separate bugs wearing the same symptom. Fix the wrong one and you'll keep getting surprised. Fix both and the problem mostly disappears.
Why Doesn't It Know Which Code Is Off-Limits?
Because nothing told it. A language model doesn't have a native concept of "this is your file, these are your rules." It infers the scope of a task from whatever is visible in the prompt and the instruction attached to it. Say "fix the bug in calculateShipping" without adding a boundary, and the model has to guess what "fix" means: does it include the one broken line, the whole function, the file's import order, or the variable name it thinks is unclear? Each of those is individually a plausible reading of "make this better." Stacked together, they're an unreviewable diff.
This is scope creep from the model's own habits, not disobedience. Models are trained to be thorough and helpful across the whole response, and a rewrite request gives them the entire file as material to be thorough about, not just the three lines you actually meant.
A realistic version of this: you ask for a null-check fix inside getUserProfile, and the returned file also renames a variable it found unclear, adds a type annotation to an unrelated helper two functions down, and tweaks a log message's wording. None of those edits are wrong on their own. None of them were part of the request either, and nothing marks them as separate from the fix you asked for. You'd only catch them by reading every line of the response against every line of the original, which is the exact task a full rewrite makes tedious enough that most people skip it.
This is the same job a Role, Task, Format, and Constraints structure does for any prompt, not just a code one: naming the constraint turns an assumption into an instruction. See Free Prompt Enhancer: Paste a Prompt, Get a Better One for a tool that inserts that structure automatically instead of relying on you to remember it every time.
Why Does It Rewrite the Whole File Instead of Showing the Change?
Because you asked for a file, and a file is what generation produces: every line, regenerated, whether it changed or not. Even with a perfectly scoped instruction, "paste me the fixed version" only leaves one output shape available. The model can't hand back "just the diff" unless you ask for that shape specifically, so formatting quirks, quote-style changes, and whitespace normalization ride along with the real fix, invisible until you compare the two files byte by byte yourself.
The open-source coding assistant Aider makes this explicit in its own documentation. Its default "whole" edit format returns complete copies of the entire file, which the docs describe as slow and costly "because the LLM has to return the entire file even if just a few lines are edited" (verified at Aider's edit formats documentation, accessed August 26, 2026). Aider built alternative formats, search-and-replace blocks and unified diffs, specifically to avoid full-file regeneration. Its "udiff" format exists because whole-file formats caused GPT-4 Turbo models to develop the opposite bad habit: eliding untouched sections behind a lazy "// original code here" placeholder instead of reproducing them faithfully, the same underlying issue in a different costume: the model was never asked to identify only the delta (same source, accessed August 26, 2026). Paste a response like that back into your file without reading it closely and the placeholder comment doesn't restore the code it's standing in for. It deletes it, silently, because a comment isn't the code.
Asking for a diff changes the task the model is actually doing. "Produce a file" and "identify what changed" are different generation problems: the second one asks for a structured output shape instead of freeform text, and that narrower shape is easier to check. Anything that shows up in a diff unambiguously changed. There's no scanning forty identical-looking lines to find the one that didn't need to.
Bad prompt:
"Here's the file. Fix the bug where shipping cost is calculated wrong.
Give me the corrected version."
Better prompt:
"Only modify the calculateShipping function in checkout.js.
Do not touch imports, other functions, formatting, or comments elsewhere.
Return your answer as a unified diff (lines starting with - for removed,
+ for added), not the full file."
A unified diff for that fix looks like this, and it's the whole point: every changed line is visible without you having to hunt for it.
- return basePrice * 1.1;
+ return basePrice * shippingMultiplier;
This is also why coding-focused editors increasingly show a diff by default instead of just overwriting the file on disk. GitHub Copilot Edits in Visual Studio lets you accept or reject changes per hunk with Tab and Alt+Delete, jump between proposals with F8, or accept an entire file at once with a checkbox next to its name, and a 2026 update added a single review summary across every file an edit touches instead of switching between them one by one (verified at Microsoft's Copilot Edits documentation, accessed August 26, 2026). Cursor renders the same change as a color-coded diff, red for removed lines and green for added ones, so a deletion that shouldn't have happened is visible before you accept anything (verified at Cursor's reviewing and testing guide, accessed August 26, 2026). Neither tool eliminates the underlying tendency. Both just make it something you can catch instead of something buried in a wall of unchanged text.
Does This Get Worse Inside Agentic Tools That Edit Multiple Files?
Yes, because the same two failures compound instead of cancel out. A single reply that rewrites one file is one thing to review. An agent turned loose across a codebase with a vague instruction, "clean up the checkout flow," can decide on its own that three other files are in scope, and it will make that decision with the same generous, be-helpful judgment described above, just applied file by file instead of line by line.
The fix scales the same way: set the boundary before the work starts instead of reviewing the damage after. Claude Code's permission system requires approval before any file edit or write by default in its standard mode, and supports fine-grained rules scoped to specific paths, so you can restrict which directories an agent is even allowed to open before a single change happens (verified at Claude Code's permissions documentation, accessed August 26, 2026). Cursor's agent mode lets you interrupt and redirect mid-task the moment it heads toward files or changes you didn't intend, rather than waiting for it to finish and hoping the diff is small enough to catch everything (same Cursor source as above, accessed August 26, 2026).
Picture the same failing-test task handed to an agent instead of a chat window: "make the checkout test pass." Left unscoped, the agent might patch the function the test actually covers, and also touch a shared fixture file, adjust an unrelated CI config it decided looked stale, and delete a helper function it flagged as dead code. Every one of those moves might be defensible in isolation. Stacked into one unreviewed run across four files, they're a code review problem you didn't sign up for. A working-directory restriction or a stated file allowlist turns that from "discover it later" into "the agent can't do that without asking."
If the task itself is a refactor, this matters even more, because "refactor" implies touching related code by definition; see 25 AI Prompts for Refactoring Legacy Code (Safely) for prompts that name that boundary explicitly instead of leaving it to the model's judgment. And once a diff exists, reading it well enough to actually catch what's wrong with it is its own separate skill; see How to Prompt for a Genuinely Useful Code Review for how to get a review that goes past a rubber stamp.
| Workflow | Shows a diff by default | Scoped to specific files by default | Where unwanted changes hide |
|---|---|---|---|
| Copy-pasted file into a chat window | No | No | Anywhere in the returned file |
| IDE inline edit (Cursor, Copilot Edits) | Yes, per hunk | No, unless the prompt scopes it | Files outside the one you opened |
| Agentic multi-file tool (Claude Code, Cursor Agent) | Yes, per file or hunk | Yes, if permissions are configured first | Directories you didn't restrict upfront |
The Two-Part Fix, as a Prompt You Can Reuse
Name the boundary and demand the output shape that makes a violation visible. Both parts matter; either one alone still leaves a gap. A scoped instruction with a full-file response still hides a rogue rename in 200 unchanged lines. An unscoped instruction with a diff still lets the model decide three functions needed "cleanup" it never returns as separate, clearly-flagged edits, since it considers all of it part of the one task.
Scope: Only modify [function/file/line range].
Boundary: Do not touch imports, other functions, formatting, naming, or
comments anywhere else in the file.
Output: Return the change as a unified diff, not the full file. If the
fix requires touching more than [scope], stop and explain why before
making the change.
That last line matters as much as the first two. It converts "the model decided to expand scope" into "the model has to ask first," which is the difference between a surprise and a decision you made on purpose.
The stakes here aren't abstract. Stack Overflow's 2025 Developer Survey found that 45% of developers name "AI solutions that are almost right, but not quite" as their single biggest frustration with AI tools, and 66% say they now spend more time fixing that almost-right code than fixing code they wrote themselves (verified at Stack Overflow's 2025 survey results, accessed August 26, 2026). An unreviewed rewrite is exactly how "almost right" hides. The three lines you asked for are correct. The fourth line, the one you never asked about and never saw flagged as a separate change, is what breaks the build an hour later.
Scope instructions and diff requests aren't a workaround for a broken tool. They're guardrails that turn "the model decided" into "you decided, and can check." That's the whole fix, and it costs one extra sentence in the prompt.
This is one of several places where the gap between what you meant and what the model actually does costs real time. See also why AI ignores your word count and why ChatGPT forgets what you told it for two more versions of the same underlying lesson: an unstated assumption is not an instruction.
Stop rewriting prompts. Start shipping.
Works with ChatGPT, Claude, Gemini, Grok, Midjourney, Ideogram, Veo3 & Kling. 5.0★ on the Chrome Web Store.
Create An Account