Practical guide
Stop AI coding agents from changing unrelated files
A small fix should not become an unreviewed refactor. Define edit scope, inspect the diff and check the permissions that can enforce the boundary.
Written by the Kaplira teamKaplira makes a product for this problem. The guide also says what works without it.
The short answer
When a coding agent changes files outside your request, stop the run and compare its changes with an explicit list of allowed edits. Let it read related code, require a reason before it expands write scope, and review the actual patch before accepting it. A sentence saying “only change what is necessary” helps communicate intent, but does not enforce a file boundary.
Investigate the cause before widening the task
An unexpected file in a patch is a reason to investigate. First check whether the agent found the existing implementation and whether the request defined which files it could change. Creating a second implementation or cleaning up unrelated code can widen the task without fixing its original cause.
Before blaming the model, inspect the patch. A formatter, generated output or a shared dependency can explain apparently unrelated files. The distinction matters: a necessary dependency change needs an explanation; an opportunistic cleanup can usually wait.
Turn the request into an edit boundary
For an illustrative task, suppose a checkout form displays the wrong error message. A useful task instruction would be:
Goal: show the existing payment error when submission fails. Read: checkout, payment client and their callers as needed. Edit: CheckoutForm.tsx and its regression test. Preserve: payment API, shared styles and dependency versions. If another file must change, explain the dependency before editing it. Done: reproduce the error, apply the fix and verify the same journey.Replace the example paths with the ones in your repository. The point is to separate useful reading from permission to rewrite. An agent should be able to inspect a shared component without treating every improvement it notices as part of the task.
Require it to locate the existing implementation and name the files it expects to edit before the first change. If the fix really needs a shared component, update the boundary deliberately and include the affected callers in review.
Reproduce an unexpected change in a disposable repository
This is an original illustrative example, not a report about a particular agent. Run it in a new temporary directory, separate from your working repository. It simulates a payment-message fix that also changes a shared stylesheet:
mkdir scope-example cd scope-example git init -q mkdir src printf 'export const error = "Something went wrong";\n' > src/CheckoutForm.tsx printf 'body { margin: 0; }\n' > src/global.css git add src git -c user.name=Example -c user.email=example@example.invalid commit -qm 'Starting state' BASE_COMMIT=$(git rev-parse HEAD) printf 'export const error = "Payment failed";\n' > src/CheckoutForm.tsx printf 'body { margin: 8px; }\n' > src/global.css git diff --name-only "$BASE_COMMIT" -- .We executed this fixture. The comparison returned:
src/CheckoutForm.tsx src/global.cssIf only the checkout message was authorized, the stylesheet needs an explanation before acceptance. The output identifies the extra file; it does not decide whether that change is justified. Inspect its patch with
git diff "$BASE_COMMIT" -- src/global.css.The commit comparison also catches changes committed after the baseline. It does not include untracked files: inspect
git ls-files --others --exclude-standardseparately. In a real repository with existing local edits, record that starting state too; a baseline commit alone cannot distinguish those edits from the agent's work.Check what your tools actually enforce
Claude Code provides permission rules and PreToolUse hooks that can reject a tool call before it runs. They can support an edit boundary, but only for the operations and paths your configuration covers.
A restriction on an editor tool alone is incomplete if an allowed shell command can write the same file. Review shell access, scripts and generated files as well. Test the restriction with a harmless attempted edit to a disposable file outside the scope before relying on it.
If you cannot enforce a write boundary, use a separate checkout and review each patch before accepting it. Isolation makes recovery easier; it does not stop the agent from changing unrelated files inside that checkout. For the broader distinction between context and permissions, see coding agent permissions.
Review the delta against the starting state
Record existing local edits before the run so you do not attribute somebody else's work to the agent. These commands help inspect the state:
git status --short git diff --name-status git diff git diff --cachedUntracked files appear in status and need separate inspection. If the agent made commits, also compare the resulting branch against the commit from before the run; the working diff alone will miss committed changes.
For each unexpected file, ask whether the requested behavior depends on that edit. Check removed assertions, rewritten shared components, dependency changes and broad formatting separately. Preserve pre-existing work when removing unwanted edits; avoid a blanket reset of a dirty checkout.
The acceptance condition is a justified patch plus evidence that the requested behavior works. A green build does not answer whether the scope was appropriate.
Where Kaplira fits
For cooperative runs through its MCP protocol, Kaplira supplies a project change contract and reviews changed files against the declared scope. This makes a proposed expansion and the resulting review part of the run record instead of leaving them only in chat.
The executor must follow that protocol. Kaplira's contract is not an operating-system sandbox, and it does not make an unrestricted shell safe or guarantee correct code. Use executor permissions for actual access restrictions, then use the contract and review to assess what the run did. The evidence page explains the record and its limits.
Continue exploring
AI tests pass, but the feature is still broken
Passing AI-written tests can miss the real defect. Inspect mocks, protect the acceptance criteria and verify the user journey against the actual app.
CLAUDE.md ignored
Why rules get skipped, and how to put the ones that matter in front of the edit.
Repeated mistakes
Why a fix doesn’t stick between sessions, and how to attach the lesson to the file.
Try it on a project you already have.
Kaplira records decisions and known mistakes from each governed run, links them to the files they affect, and hands them to the next agent that touches those files. The desktop app is free, no signup is required, and the run record stays on your machine by default.
Kaplira does not replace your tests or human review, and it does not guarantee correct code. Read the run evidence and security boundaries to see what the record proves.