Contents

Claude Code Best Practices

Claude Code is most useful when you treat it like a fast teammate with terminal access, not an autonomous engineer you can stop supervising.

That sounds obvious, but most failures come from forgetting it:

  • too much scope
  • too little verification
  • too much trust in a long session
  • vague prompts against a large repo
  • asking for implementation before asking for understanding

If you use it in real repositories, the job is not “how do I make it do more.” The job is “how do I make it stay accurate long enough to be worth the speed.”

Start with a verification loop

The single best thing you can do is give Claude Code a way to prove itself wrong.

That usually means one or more of:

  • existing tests to run
  • a specific command that should pass
  • a screenshot or UI target
  • a diff to review
  • an error message to reproduce
  • an explicit acceptance checklist

Bad prompt:

implement token refresh

Better prompt:

implement token refresh for expired access tokens in src/auth/; do not change session storage format; run the auth tests after changes and show me the diff

Bad prompt:

make the dashboard match the design

Better prompt:

update the dashboard layout to match this screenshot; keep existing API calls unchanged; after changes, summarize remaining visual differences

Claude Code does better when it has something concrete to check. If it cannot verify, it will often settle for something that merely looks plausible.

Explore first, plan second, edit third

Jumping directly to code is usually where the tool starts solving the wrong problem.

A better default sequence is:

  1. explore
  2. plan
  3. implement
  4. verify
  5. review the diff

The important shift is that “read the repo first” should be a separate step, not an implied part of “go implement this.”

For example:

  • first: understand how auth works now
  • then: identify the change surface
  • then: propose the plan
  • then: implement only that plan

This catches a lot of avoidable nonsense: duplicate abstractions, wrong files, fighting local conventions, or changing more than necessary.

Use repository instructions, but keep them lean

A good CLAUDE.md or equivalent repo guidance file is valuable. A bloated one is not.

The file should contain things Claude Code cannot reliably infer from the repository itself:

  • commands to validate work
  • project-specific constraints
  • house rules that differ from defaults
  • directory responsibilities
  • migration or deployment cautions
  • patterns to copy and patterns to avoid

It should not try to restate the entire engineering handbook.

Useful guidance looks like this:

# Validation
- Run `pnpm test` for app code changes
- Run `pnpm lint` before finishing
- For schema changes, run `pnpm prisma generate`

# Constraints
- Do not change public API response shapes without explicit approval
- Prefer existing `src/lib/http.ts` helpers over adding new fetch wrappers
- Keep feature flags in `src/config/flags.ts`

# Repo conventions
- Integration tests live under `tests/integration/`
- New background jobs go under `src/jobs/`

Bad instruction files fail in two ways:

  1. too generic

    • “write clean code”
    • useless
  2. too noisy

    • pages of detail the tool will ignore once context gets crowded

Keep it short enough that it still has signal after a long session.

Narrow scope aggressively

Claude Code gets worse as the task boundary gets mushier.

If you say:

refactor the payment system

you are inviting drift.

If you say:

in src/payments/stripe.ts, extract retry handling into a small helper; do not change the public function signatures; run the payment unit tests after edits

you are much more likely to get something reviewable.

Ways to narrow scope:

  • point to exact files or directories
  • name what must not change
  • name the validation command
  • ask for one subtask at a time
  • split investigation from implementation
  • split refactor from behavior change

This is less glamorous than “end-to-end autonomy,” but it produces better work.

Manage context like a finite resource

Long sessions degrade. That is normal.

The signs are familiar:

  • it starts repeating assumptions as facts
  • it forgets a constraint from earlier
  • it edits adjacent code that was never in scope
  • it becomes overconfident about tooling or repo structure
  • it keeps patching around a mistake instead of resetting

When that starts happening, do not keep pushing the same thread. Reset the conversation or start a fresh session with a tighter brief.

A good rule of thumb:

  • one session per coherent task
  • clear context between unrelated tasks
  • if you have corrected it twice and it is still drifting, restart

It is usually cheaper to restate the problem cleanly than to rehabilitate a confused session.

References work better than abstractions

Claude Code responds better to concrete references than broad style requests.

Weak:

make the new component consistent with the rest of the app

Better:

implement the new settings panel using the same form pattern as src/components/ProfileForm.tsx; keep validation style aligned with that file

Weak:

use the existing way we do jobs

Better:

follow the enqueue and retry pattern used in src/jobs/sendDigest.ts

Reference files do two things:

  1. they reduce guessing
  2. they reduce “creative” architecture you did not ask for

That is usually what you want in a real repo.

Permissions and sandboxing are workflow decisions, not just security settings

Permission prompts can be annoying, but removing them blindly is not maturity. It is just moving the risk.

Think about modes in terms of task type.

High-trust, low-risk tasks

Reasonable candidates for looser permissions:

  • formatting
  • linting
  • unit test runs
  • read-heavy exploration
  • code search
  • local documentation changes

Higher-risk tasks

Keep tighter control for:

  • anything destructive
  • dependency upgrades
  • Git history manipulation
  • credential or environment changes
  • deployment commands
  • schema migrations
  • file moves across the repo
  • writing commits or opening PRs on your behalf

Sandboxing has a tradeoff too. More safety often means less ability to verify realistically. That can be fine for exploration, but painful for tasks that depend on real command execution.

Use the mode that matches the task. Do not set one global habit and forget about it.

Ask for diffs before asking for commits

Claude Code can help write commits, but asking for a commit too early is a common mistake.

The better sequence is:

  1. implement
  2. run verification
  3. inspect diff
  4. optionally ask for a commit message or commit

Even if the code is correct, the diff may still be wrong in scope:

  • unrelated formatting
  • accidental rename churn
  • incidental cleanup
  • config file changes you did not want
  • test fixture rewrites that obscure the real change

A useful prompt is:

show me the diff first and summarize the files changed by purpose

That forces a pause before history gets written.

If you do ask for a commit, constrain the message:

write a commit message focused on the auth timeout fix only; do not mention unrelated refactors

Use Claude Code to reason, not just to write

A lot of value comes from asking it to inspect and explain before it edits anything.

Good uses:

  • summarize how a subsystem is structured
  • identify where a config value flows
  • compare two implementations
  • trace a bug path from logs to code
  • explain why a test is flaky
  • review a diff for risk

This is often safer and more valuable than jumping straight to code generation, especially in unfamiliar repos.

In practice, the “analysis first” usage is where trust usually starts.

Break multi-part work into explicit checkpoints

For medium or large tasks, give it stopping points.

Example:

  1. inspect auth flow
  2. propose files to change
  3. wait for confirmation point
  4. implement backend only
  5. run tests
  6. summarize diff
  7. then handle frontend wiring

Even if you are not literally confirming at every step, the structure itself helps. Claude Code does better when the work has shape.

This is especially important for refactors, migrations, and cross-cutting changes.

Watch for long-session repair loops

A common failure mode looks like this:

  • first implementation is wrong
  • second tries to patch around the first
  • third introduces compatibility code for both wrong versions
  • now the diff is twice the size and half the clarity

When you see that pattern, stop and reset.

Ask for:

  • a short summary of intended behavior
  • a clean implementation plan
  • a fresh edit pass based on current files only

Do not let a confused session build sediment.

Good prompts specify negatives

One of the simplest ways to improve results is to say what must not happen.

Examples:

  • do not change public API shapes
  • do not rename files
  • do not touch migrations
  • do not add new dependencies
  • do not modify unrelated tests
  • do not convert this to a different state management pattern

These constraints matter because Claude Code often tries to improve adjacent code while it is in the area. Sometimes that is helpful. Often it is just scope creep.

Treat generated work like teammate work

The right review standard is not “the AI wrote it.” It is “would I accept this from a strong but hurried teammate?”

That means checking:

  • correctness
  • scope control
  • test coverage
  • adherence to repo conventions
  • rollback clarity
  • operational impact

The tool is fast. Your job is to supply taste, boundaries, and final judgment.

A practical operating model

If you want one repeatable way to use Claude Code in real repos, this is a good default:

  1. give it the smallest useful scope
  2. point it at the relevant files
  3. define what must not change
  4. define how it should verify
  5. ask for a plan before edits on non-trivial work
  6. reset when context gets muddy
  7. inspect diff before commit or PR
  8. trust it as a contributor, not as authority

That is enough to get most of the upside without inviting the worst failure modes.