One Claude Code Tip a Day: Set a Change Budget Before Editing
Before Claude Code edits, give it a change budget: the files it may touch, the checks it must run, and the conditions that require stopping instead of expanding scope.
This post is part of the “One Claude Code Tip a Day” series — a daily guide to using Claude Code more effectively.
The real failure: a two-line fix becomes a tour of the repo
A familiar Claude Code failure starts with a modest bug: the settings page saves the user’s timezone but still renders UTC until the next reload. You ask Claude to fix it, the first explanation sounds reasonable, and five minutes later the diff touches a form hook, an API client, a date utility, a cache wrapper, and three snapshots. Some of those edits may be good. The problem is that the session no longer has a clear definition of “small.”
Today’s habit is to set a change budget before editing. A budget is not micromanagement. It is a contract for the first pass: which files may change, which commands prove the change, and what evidence should make Claude stop and ask for a second plan instead of widening the blast radius.
Give Claude the budget in the first prompt
For the timezone bug, I would not start with “fix the settings timezone issue.” I would start with a scoped prompt:
We have a bug where saving timezone in SettingsForm updates the server but the visible timezone label stays UTC until reload. First read SettingsForm.tsx, useUserSettings.ts, and timezone-label.test.tsx. Then propose a fix with this budget: at most two product files, no dependency changes, no snapshot rewrites, and one focused test. If you think the fix needs more files, stop and explain why before editing.
This prompt does three useful things. It names the suspected files, defines the maximum first-pass diff, and gives Claude permission to refuse the budget. That last part matters. A budget should create a pause, not a trap. If the stale label is actually caused by a normalized cache in a shared API layer, Claude should say so before touching half the frontend.
Ask for a pre-edit budget report
Before allowing the patch, make Claude restate the budget against the code it just read:
Before editing, show me: 1) the smallest state path that explains the stale label, 2) the exact files you intend to change, 3) the test command you will run, and 4) the condition that would make you stop instead of expanding the diff.
A strong answer is concrete: “SettingsForm calls saveSettings, but the label reads from useUserSettings().data, which is not updated after mutation. I will change useUserSettings.ts to update the query cache on success and add one test in timezone-label.test.tsx. I will run pnpm test timezone-label.test.tsx. If the mutation is shared by billing settings too, I will stop and ask before changing the API client.”
This is where the session starts to feel like a real pairing loop rather than autocomplete. Claude is not only proposing code; it is declaring the boundaries of the experiment.
Run the first pass like an experiment
Once the budget is accepted, keep the command sequence narrow. In Claude Code, the next instruction can be:
Apply only the budgeted change. Then show git diff --stat, the full diff for changed files, and the result of pnpm test timezone-label.test.tsx. Do not run broad formatting or update unrelated snapshots.
The point is not to avoid broad test suites forever. The point is to preserve signal during the first pass. If the focused test fails, you want to know whether the budgeted theory was wrong. If Claude also reformatted a directory or updated snapshots, the failure becomes muddy. Small budgets make small failures readable.
Second-pass correction when the budget is wrong
Sometimes the budget will fail. Suppose Claude changes the cache update, the focused test passes, but a manual browser check still shows UTC after saving. Do not immediately say “try again.” Force a second-pass correction:
The first-pass budget did not explain the browser behavior. Re-enter read-only mode. Inspect the network response, the component that renders the header timezone, and the client cache key. Do not edit. Tell me whether this is a second label path, a stale query key, or a test that covers the wrong UI.
Now the budget has done its job. It prevented the first theory from silently expanding. The next plan can have a larger budget if the evidence justifies it: maybe one extra component and one browser-level test. The important move is that scope expands because of inspection, not because Claude ran out of ideas inside the original patch.
Failure modes
The most common mistake is setting a fake budget that is really a command: “only change one file no matter what.” That encourages Claude to squeeze the fix into the wrong place. A good budget includes a stop condition. “If this needs the shared cache layer, stop and explain” is much safer than “never touch the cache layer.”
Another failure mode is measuring only file count. A one-file rewrite can be more dangerous than a three-file surgical patch. Include qualitative limits: no new abstractions, no dependency changes, no snapshot rewrites, no unrelated formatting, no public API changes unless approved.
Finally, do not skip verification because the diff stayed small. A budget is a guardrail, not evidence. The evidence is still the focused test, the diff review, and when relevant a browser or deployment check that reproduces the user-visible path.
Rule of thumb
Before Claude Code edits, define the smallest acceptable experiment: allowed files, forbidden categories of change, verification command, and the stop condition. If the first pass fits the budget and the evidence passes, you have a clean fix. If it does not, you have a clean reason to re-plan. Either outcome is better than waking up inside a diff that is too large to trust.