One Claude Code Tip a Day: Draw the Dependency Boundary

Before Claude Code edits a shared module, make it map the callers, imports, tests, and no-touch edges. The boundary turns a risky refactor into a reviewable session.

One Claude Code Tip a Day: Draw the Dependency Boundary

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

A shared file is where otherwise good Claude Code sessions go sideways. You start with a harmless bug in a date formatter, a checkout component, or a small API client. Claude proposes a neat patch. The local test passes. Then review reveals that the same helper feeds a background job, a mobile screen, and an old admin page with different assumptions. The mistake was not asking Claude for a bigger patch. The mistake was editing before you drew the dependency boundary.

Today’s habit is simple: before Claude Code touches a shared module, make it identify what depends on that module and what must not change. This is not a grand architecture diagram. It is a tactical session artifact: callers, imports, tests, risky edges, and the exact verification commands that will prove the patch stayed inside the boundary.

The Real Failure: A Small Fix With Large Edges

Imagine a SaaS dashboard where invoices sometimes display one day early for users west of UTC. The tempting prompt is: `Fix the invoice date bug in src/billing/formatInvoiceDate.ts and run the tests.` Claude can probably find the formatter and patch it. But if that function also feeds CSV exports, webhook payloads, and a revenue report, you have not asked the question that matters: which behavior is shared contract, and which behavior is only UI presentation?

A better session starts read-only. Ask Claude to inspect before editing:

`Before changing anything, map the dependency boundary for src/billing/formatInvoiceDate.ts. List direct callers, important indirect flows, related tests, and any files you recommend not touching. Then propose the smallest safe change and the verification commands. Do not edit yet.`

That prompt forces Claude Code to spend the first pass on evidence. You want file paths, line numbers, grep results, import relationships, and uncertainty. If it answers with a generic paragraph, stop it and ask for the receipts: `Quote the files and commands you used. Mark anything you inferred but did not verify.`

What the Boundary Should Contain

A useful dependency boundary has five parts. First, the target file and the behavior you intend to change. Second, direct callers: components, services, jobs, tests, and scripts that import or execute the target. Third, risky edges: serialization formats, public APIs, database migrations, timezone conversions, caching, analytics, and anything customer-visible. Fourth, no-touch files: generated code, migrations, unrelated cleanup, or nearby modules that are tempting but outside the task. Fifth, verification: unit tests, integration tests, a focused shell check, and sometimes a browser or log inspection step.

In Claude Code, I like to make the output compact enough to paste into the next prompt:

`Create a boundary table with columns: file, relationship, risk, evidence, verification. Keep it under 20 rows. End with a recommended patch scope of three bullets or fewer.`

This format changes the conversation. Instead of debating whether Claude is smart enough to infer the codebase, you are asking it to create a checklist that review can falsify. If the table says only `InvoiceDate.tsx` calls the formatter and `rg formatInvoiceDate` later finds an export job, you caught the problem before the patch.

Then Let Claude Patch Against the Boundary

Once the boundary is credible, give Claude permission to edit, but keep the contract visible:

`Apply the smallest change that fixes the UTC display bug. Stay within the boundary above. Do not change CSV exports, webhook schemas, or report aggregation. After editing, run the listed checks and show the diff grouped by boundary row.`

The important phrase is `grouped by boundary row`. It prevents the common second failure mode: Claude fixes the bug, then opportunistically renames variables, cleans up nearby helpers, or updates unrelated snapshots. A boundary-aware diff review asks: which row justified this change? If no row justified it, revert or ask for a second pass.

For a frontend bug, the verification might include `npm test -- billing`, `npm run typecheck`, and a Playwright check for the invoice screen in a specific timezone. For a backend helper, it might include a unit test plus a log inspection from a staging job. For a deployment script, the boundary may include environment variables and rollback commands. The pattern is the same: callers first, patch second, proof last.

Second-Pass Correction: Ask What Escaped

After the first patch passes, do not immediately accept it. Use a second-pass prompt that looks for boundary leaks:

`Review your own diff against the dependency boundary. Name any caller not covered by tests, any behavior that changed outside the target bug, and any file touched without a boundary reason. If something is risky, propose a smaller patch or an extra verification step before we proceed.`

This is where Claude Code becomes most useful as a session partner. It may notice that a snapshot changed because the formatter also powers exports, or that it edited a shared utility when a presentation-layer wrapper would have been safer. The second pass is not ceremony; it is how you turn a fluent patch into a maintainable one.

Failure Modes

The boundary habit can fail in predictable ways. Claude may over-map the repo and waste time; constrain the table to direct callers plus obvious high-risk indirect paths. It may hallucinate relationships; require commands like `rg`, imports, tests, or file references as evidence. It may treat the boundary as permission to make a bigger architecture change; restate the smallest-change rule before editing. And sometimes the boundary reveals that the task is not safe for an autonomous patch yet. That is a successful outcome. You learned to ask for a design review, a product decision, or a staging experiment before code moved.

Rule of Thumb

If a file has more than one kind of caller, draw the dependency boundary before Claude Code edits it. The boundary should fit on one screen, cite evidence, name no-touch areas, and produce verification commands. When the diff arrives, every changed line should be explainable by that boundary. If it is not, ask for a smaller second pass. Claude Code is much better when the session has edges.