One Claude Code Tip a Day: Make Claude Predict the Diff

Before Claude Code edits, ask it to predict the diff: files, shape, tests, and no-touch areas. Then compare the real git diff to that forecast before accepting the patch.

Editorial illustration of a developer comparing a predicted code diff with an actual patch and test results in an AI coding workflow.

This post is part of the “One Claude Code Tip a Day” series — a daily guide to using Claude Code more effectively.

The failure: the patch looks reasonable until the diff surprises you

A common Claude Code failure does not look dramatic. You ask for a small fix: the billing page should keep the Apply Coupon button disabled while a request is in flight. Claude reads a hook, edits the button component, adds a test, and reports success. The explanation sounds tidy. Then you run `git diff --stat` and discover a helper rename, a copy tweak, a test fixture rewrite, and a new loading prop threaded through three components. None of those edits are obviously wrong, but the original task no longer has a clean review boundary.

Today’s habit is to make Claude predict the diff before it edits. Not the implementation in prose. The diff. Ask for the files it expects to touch, the kind of changes in each file, the files it explicitly should not touch, and the verification command that will prove the patch. That forecast becomes the contract for the rest of the session.

The prompt: turn intent into a reviewable forecast

After the read-only investigation, pause before the first write. Use a prompt like this:

Prompt: `Before editing, predict the diff. List: 1) files you expect to modify, 2) one-sentence reason for each file, 3) files you inspected but will not touch, 4) the smallest test or command that should prove the fix, and 5) what would make you stop and ask before widening the patch. Do not edit yet.`

This is more useful than asking for a plan because it forces Claude Code to name the artifact you will review later. A plan can hide behind abstractions: update state handling, improve tests, clean up naming. A diff forecast has to say: `src/billing/CouponForm.tsx`, one guard around the submit state; `src/billing/useCoupon.ts`, reset state in the conflict branch; `tests/billing-coupon.spec.ts`, one regression case. If Claude cannot forecast the diff, it has not understood the seam well enough to edit.

A real workflow: coupon state bug in a frontend app

Imagine the bug report says: after a failed coupon request, the button stays disabled until refresh. Start with read-only analysis: `Inspect the coupon form, coupon hook, and existing tests. Do not edit. Identify the state transition that keeps the button disabled.` Claude finds `CouponForm.tsx`, `useCouponMutation.ts`, and a Playwright spec. Good. Now ask for the diff forecast.

A strong answer might say the production change should be inside the mutation hook, not the button component, because the disabled state comes from `isApplying`. The forecast should name one regression test and one no-touch area: pricing calculations should not change. Then you allow the edit: `Apply only the forecasted production change and regression test. If you need another file, stop and explain why before editing.`

After Claude edits, do not accept the success message. Run the focused command through Claude Code’s shell tool, for example `!pnpm test -- billing-coupon` or `!pnpm playwright test tests/billing-coupon.spec.ts`. The point is not that this exact command fits every stack. The point is that the command was predicted before the patch, so success proves the named behavior rather than a convenient adjacent check.

Compare the forecast to the actual diff

Now make the second pass mechanical. Run `!git diff --stat` and then `!git diff`. Ask:

Prompt: `Compare the actual diff to your pre-edit diff forecast. For each changed file, mark it as forecasted, justified widening, or scope creep. Identify any changed line that does not directly support the bug fix or the regression test. If something widened, explain the evidence that forced it.`

This prompt changes the social dynamic of the session. Claude is no longer selling you the patch; it is auditing the patch against a prior commitment. If the diff added a styling tweak because the button looked awkward in a screenshot, that may be useful, but it is not part of the coupon-state fix. Revert it or split it. If Claude touched pricing helpers because the test fixture used a shared factory, it must show why the fixture could not be adjusted locally. The forecast gives you leverage to keep the change small without arguing from taste.

Failure modes

The first failure mode is writing a forecast that is too vague. `I will update the coupon logic and tests` is not a diff forecast. It should name paths, change shapes, and proof. The second is treating the forecast as a prison. Sometimes evidence forces a wider patch. That is fine, but Claude should stop at the widening point, explain the new evidence, and ask for permission to continue.

The third failure mode is skipping the no-touch list. A forecast without no-touch files only describes where edits may happen; it does not protect nearby code. For a billing bug, no-touch might include tax calculation, checkout copy, or API client retry policy. For a deployment bug, no-touch might include Terraform modules outside the failing service. Naming boundaries makes accidental cleanup visible.

Rule of thumb

Use a diff forecast whenever the task sounds small but sits near shared code: auth state, billing flows, route loaders, deployment scripts, design-system components, and test factories. My rule is simple: if I would be annoyed to review a surprise third file, I ask Claude to predict the diff first. The forecast does not make Claude perfect. It makes the session inspectable: intent before edit, evidence after edit, and a clear reason for every line that crossed the boundary.