Learn Claude Code Mastery The DOs and DON'Ts of AI-Assisted Development

The DOs and DON'Ts of AI-Assisted Development

Intermediate 🕐 20 min Lesson 7 of 10
What you'll learn
  • Apply the junior developer mental model to set the right expectations for working with Claude Code
  • Use git commits and diff review as the core of a safe AI-assisted workflow
  • Write specific prompts that produce specific, verifiable results

The One Mental Model That Changes Everything

Most of the mistakes developers make with Claude Code come from having the wrong mental model. They think of it as an oracle that produces correct code on demand. They paste in a vague prompt, accept the output without reading it, and ship it. Then something breaks and they blame the AI.

The right mental model is this: Claude Code is a very smart junior developer.

Junior developers are fast, enthusiastic, and usually produce reasonable code. But they miss context you haven't given them. They make assumptions where they should have asked. They occasionally do more than you asked, or slightly less, or something adjacent to what you asked. Their work needs review before it ships.

Your job when working with Claude Code is not to do the coding — it is to assign tasks clearly, review the results carefully, give specific feedback, and maintain the overall direction. That is exactly what a good senior engineer does with a junior developer. It is pair programming, not outsourcing.

DO: Review Every Change Before Accepting

This is the non-negotiable rule. Never approve Claude's changes without reading the diff. The diff is how you catch:

  • Changes to files you did not expect Claude to touch
  • Deletions of code that seemed unrelated to the task
  • Hardcoded values where there should be configuration
  • Logic that looks right at a glance but has a subtle bug
  • Scope creep — Claude did more than you asked
git status       # Which files changed?
git diff         # Exactly what changed?
git diff --stat  # Summary view — useful for large changesets

This takes two minutes. Skipping it and then spending two hours debugging a production issue is not a trade-off worth making.

DO: Use Git as a Safety Net

Every time Claude makes a change, you have a decision: accept it immediately with a commit, or hold it and keep going. The answer should almost always be to commit at each logical step:

# Claude just fixed the auth bug
git diff                               # Review the fix
git add src/auth.ts                    # Stage only what you approve
git commit -m "fix: null check for expired session tokens"

# Claude is working on the next thing
# If something goes wrong, you can always: git reset --hard HEAD

Think of commits as save points in a video game. Every commit is a state you can return to. Without commits, the only direction is forward into broken code.

When working on a larger feature, tell Claude to commit incrementally: "Implement the user profile edit form, making a commit after each logical step." Now you can review the history commit by commit, and if one commit breaks something, you revert only that one.

DO: Write Specific Prompts

The single biggest driver of prompt quality is specificity. Vague prompts produce vague work. Specific prompts produce specific work.

Vague prompt Specific prompt
"Fix the bug" "Fix the TypeError 'Cannot read properties of null' on line 47 of src/auth.ts that occurs when the session token has expired"
"Add tests" "Write Jest unit tests for the validateEmail() function in src/utils/validation.ts. Cover: valid email formats, missing @ symbol, missing domain, empty string, and null input"
"Improve performance" "The fetchUserPosts() function in src/api/posts.ts is making a separate DB query for each post to fetch the author. Fix this with a single JOIN query"
"Clean up the code" "Refactor the 200-line processOrder() function in src/orders.ts into 4–5 smaller functions. Keep behaviour identical — run the tests after to confirm"
"Add logging" "Add structured JSON logging to every API route handler. Log: timestamp, HTTP method, path, response status code, and duration in ms. Use our logger from src/utils/logger.ts"

The formula: what to do + where it is + the constraint (keep tests passing, match existing patterns, do not change the interface).

DO: Ask Claude to Verify Its Own Work

Claude can run your tests. Make it do so. This step catches at least half the errors before you even look at the diff:

> After making the fix, run the test suite and confirm the failing test now passes without breaking any others.

> After the refactor, run: npm run typecheck and npm test. Report the results before showing me the diff.

> Write the migration, then verify the schema with:
  SHOW COLUMNS FROM users;
  and confirm it matches what you expected.

Claude catching its own mistakes reduces your review load and gives you higher confidence in what you are approving.

DO: Encode Corrections in CLAUDE.md

When Claude makes a mistake and you correct it, the natural instinct is to move on. Resist it. Ask: "Should this go in CLAUDE.md?"

If the correction is something Claude would need to know in future sessions — a non-obvious convention, a project-specific pattern, a common mistake to avoid — it belongs in CLAUDE.md. Open /memory and add it immediately while the context is fresh.

The goal is to never correct the same thing twice. Every correction that stays only in chat is a correction you will make again next week.

DON'T: Let Claude Push to Main

Add this to your deny rules and never remove it:

"deny": ["Bash(git push *)"]

Always push yourself. The 30 seconds between reviewing git log and running git push is where you catch the commit message that says "fix" when it should say "feat", the file you staged accidentally, the branch you meant to rebase first. Claude does not have the context to make these judgment calls. You do.

DON'T: Accept Changes You Did Not Read

"Looks good" after a two-second scan of a 200-line diff is not a review. It is a hope. Hopes do not catch logic errors, security vulnerabilities, or subtle data corruption bugs.

If a diff is too large to review comfortably, that is feedback about the task. Break it into smaller pieces. Ask Claude to implement in stages and commit each stage. Never let "it would take too long to review" become the reason you skip reviewing.

DON'T: Give Claude Vague Approval

When Claude proposes a plan or approach, do not just say "sounds good, do it." Push back on specifics. Ask about edge cases. Check whether it handles the error case. If you do not understand the approach, say so and ask Claude to explain it differently before proceeding.

You are the senior engineer. You are responsible for the decision. "I trusted the AI" is not a satisfying explanation when something fails in production.

The 8-Point Review Checklist

Before approving any significant change, run through these eight questions:

  1. Correctness — Does the logic actually do what was asked? Not "does it look like it does" — trace through an example.
  2. Style — Does it match the rest of the codebase in indentation, naming, and structure?
  3. Efficiency — Any obvious N+1 queries, nested loops on large datasets, or unnecessary re-renders?
  4. Completeness — Did it address the full requirement, or only the obvious case?
  5. Edge cases — What happens with null, empty, very large input, or an error from an external service?
  6. Tests — Do the tests pass? Is the new code tested, or only the happy path?
  7. Side effects — Could this change break something else in the codebase?
  8. Security — Any user input going directly into a query? Any secrets in the output? Any new dependency from npm?

If any of these fail, do not approve. Tell Claude specifically what is wrong and ask it to fix that before you review again.

When to Use Claude Code vs. Think It Through Yourself

x
Task Approach Why
Rename a variable across 30 files Claude Code Mechanical, automatable, easy to verify
Write tests for existing code Claude Code Formulaic, can verify immediately by running them
Fix a bug with a clear error message Claude Code Concrete problem, testable result
Complex architectural decisions You first, then Claude for input Requires business context and judgment Claude does not have
Security-sensitive authentication code You + Claude, careful review Too risky to automate; every line matters
Exploring an unfamiliar codebase Claude Code to explore, you to understand Claude can map it; you need to build the mental model
API design and data modelling You design, Claude implements Architecture decisions require knowledge Claude does not have

The pattern: use Claude Code for well-defined implementation tasks with clear success criteria. Use your own judgment for decisions that require context about your business, your users, or your long-term architecture.

Key takeaways
  • Mental model: Claude is a smart junior developer — fast, capable, and needing review before shipping
  • Never approve a diff you have not read — git diff is the most important command in your AI workflow
  • Commit at each logical step: every commit is a save point you can return to
  • Specific prompts (error message + file + constraint) get specific results; vague prompts get vague work
  • Encode every correction into CLAUDE.md — never correct the same thing twice