Code Generation & Debugging with Claude Code
Claude Code in VS Code is a full coding partner. It reads your files, writes and edits code, runs tests, and reviews changes — all from the chat panel or with inline edits via Ctrl+K. This module covers what Claude can do with code, the languages and frameworks it handles best, and practical patterns for code generation, debugging, refactoring, testing, and review.
| Task | How to do it in Claude Code | Tip |
|---|---|---|
| Write a new function | Place cursor where you want it → Ctrl+K → describe what it should do | Mention the signature and edge cases you care about |
| Debug an error | Paste the error + stack trace in chat, or @ the file and say "line 42 is failing with…" | Ask Claude to explain why, not just fix — you'll learn faster |
| Code review | "Review @pr-changes.ts for security, performance, and readability. Rate each 1–10." | Use Opus for complex security reviews; Sonnet for routine checks |
| Refactor | "Refactor @orders.ts for readability. Do not change behaviour. Add JSDoc comments." | Review the diff before accepting — Claude is thorough but not always conservative |
| Write tests | "Write Jest tests for @cart.ts. Cover the happy path plus empty cart and invalid product ID." | Ask for tests before the implementation to drive TDD |
| Explain unfamiliar code | "Explain @legacy-auth.js line by line. I'm not familiar with this pattern." | Follow up with "what would you change and why?" for a free design review |
When Claude proposes an edit, VS Code shows a diff before you accept. Read it. Claude is accurate but not infallible — especially for niche library APIs or code paths it cannot fully see without being given all the relevant files.
Language and Framework Support
Claude generates high-quality code across many languages, but quality varies by language. Here is an honest assessment based on real-world usage:
| Tier | Languages | Quality Level |
|---|---|---|
| Tier 1 — Excellent | Python, TypeScript/JavaScript, Rust, Go, Java, C# | Production-quality code with proper error handling, idiomatic patterns, and awareness of ecosystem conventions. Claude keeps up with recent library versions. |
| Tier 2 — Very Good | C/C++, PHP, Ruby, Swift, Kotlin, Scala, SQL | Strong code generation with occasional minor style issues. May use slightly outdated patterns for less common frameworks. |
| Tier 3 — Good | Elixir, Haskell, OCaml, Lua, R, MATLAB, Shell/Bash | Functional and correct but may not follow all community conventions. Best used with examples of your project's style. |
| Tier 4 — Adequate | Assembly, COBOL, Fortran, Perl, Prolog, Verilog | Can generate working code but may need more human review. Provide more context and examples for best results. |
Claude knows major frameworks well: React, Next.js, Express, Django, Flask, FastAPI, Spring Boot, Rails, Vue, Angular, Svelte, Tailwind CSS, Prisma, SQLAlchemy, and many more. For newer or less common frameworks, provide documentation or examples in your prompt — Claude learns fast from in-context examples.
Code Generation Patterns
Scaffold Then Detail
For complex features, ask Claude to generate the skeleton first (interfaces, function signatures, module structure), review it, then fill in the implementations. This prevents Claude from making wrong assumptions about your architecture and gives you a checkpoint before the bulk of code is written.
Test-First Development
Ask Claude to write tests before the implementation: "Write Jest tests for a function that calculates shipping cost based on weight, destination country, and shipping speed. The function doesn't exist yet." Then: "Now write the function that passes these tests." This produces better-specified code.
Code with Context
Always attach related files when generating code. If you want a new API endpoint, @ the existing endpoints so Claude matches the patterns. If you want a new component, @ similar components. Claude produces more consistent, idiomatic code when it can see your existing codebase style.
Specify Constraints Upfront
"Write this in TypeScript strict mode. No any types. Handle all error cases with try/catch. Maximum function length: 30 lines. Add JSDoc comments." Constraints in the prompt produce better code than asking Claude to fix issues after the fact.
Debugging with Claude Code
Debugging is one of Claude's strongest use cases. Here is how to get the best results:
Provide the Full Error
Copy the complete error message and stack trace — not just the first line. Claude uses the full trace to identify the root cause. If the error is in the terminal, just ask Claude to "run the tests" and it will read the output automatically.
Attach All Related Files
The most common debugging failure is Claude not seeing the file where the actual bug lives. If @orders.ts calls a function from @utils.ts, attach both. If there is a config file involved, attach that too. More context = better diagnosis.
Describe Expected vs Actual
"I expect this function to return the discounted price (28 * 0.9 = 25.20) but it returns 28. The discount code is valid — I checked the database." Giving Claude both the expected and actual behaviour narrows the search space dramatically.
Ask "Why" Before "Fix"
Start with "Why is this happening?" rather than "Fix this." Understanding the cause prevents the same class of bug from recurring. If you just ask for a fix, Claude might patch the symptom without addressing the root cause.
Use Claude to Run Diagnostic Commands
Ask Claude to check things: "Run npm test and show me which tests fail." "Check if the Stripe webhook secret is set in the environment." "Query the database for order #4821 and show me the discount field." Claude can execute these commands and interpret the results.
Refactoring with Claude
Claude is an excellent refactoring partner, but you need to be explicit about what to change and what to preserve:
You:
Refactor @orders.ts with these goals:
1. Extract the discount calculation into a separate pure function
2. Replace the nested if/else block (lines 45-78) with a switch or map
3. Add TypeScript types for all function parameters and return values
4. Add JSDoc comments to each exported function
Constraints:
- Do NOT change any external behaviour — all existing tests must still pass
- Do NOT rename any exported functions (other modules import them)
- Do NOT add new dependencies
After the refactor, list every change you made and why.
Claude sometimes refactors more aggressively than asked — renaming variables, reorganising code structure, or changing patterns that were intentionally written a certain way. Always specify what NOT to change. Review the diff carefully. If Claude makes an unwanted change, reject the diff and ask it to redo with a more specific constraint.
Test Generation
Claude generates excellent tests when given the right prompt structure:
You:
Write Jest tests for @cart.ts. Use describe/it blocks.
Cover these scenarios:
- Happy path: add item, update quantity, remove item, calculate total
- Edge cases: empty cart, quantity of 0, negative quantity
- Error cases: invalid product ID, product not found, stock exceeded
- Boundary: maximum cart size (50 items), maximum quantity per item (99)
- Concurrency: two simultaneous addItem calls with the same product
For each test:
- Use descriptive test names that explain the expected behaviour
- Include arrange/act/assert comments
- Use test fixtures, not inline data
- Mock the database layer using jest.mock()
| Test Type | When to Ask Claude | Tip |
|---|---|---|
| Unit tests | For individual functions and methods | Attach the source file and any types/interfaces it depends on |
| Integration tests | For API endpoints and database interactions | Provide the schema and example request/response payloads |
| E2E tests | For user flows (Playwright, Cypress) | Describe the flow step by step; attach the page components |
| Snapshot tests | For UI components with complex rendering | Specify which props combinations to snapshot |
| Property-based tests | For functions with mathematical properties | Describe the invariants the function should maintain |
Code Review with Claude
Claude's code review capabilities are particularly strong because it can hold the full context of multiple files simultaneously and check for cross-file issues that humans often miss.
You:
Review these files for our upcoming PR:
@webhook-handler.ts @order-processor.ts @types/order.ts
Review criteria (check each):
1. SECURITY: Input validation, authentication, injection vulnerabilities
2. ERROR HANDLING: Are all failure modes handled? Are errors logged?
3. PERFORMANCE: N+1 queries, unnecessary allocations, O(n^2) algorithms
4. TYPES: Are types complete? Any implicit `any`?
5. READABILITY: Clear naming, appropriate comments, no magic numbers
6. TESTS: Is the code testable? What test cases are missing?
For each issue found, provide:
- Severity: Critical / High / Medium / Low
- File and line number
- Problem description (one sentence)
- Suggested fix (code snippet)
At the end, give an overall "merge readiness" rating:
Ready / Needs Minor Changes / Needs Major Changes / Block
Inline Editing with Ctrl+K
Select the Code
Highlight the lines you want Claude to change — or place your cursor at an insertion point for new code.
Press Ctrl+K
A small inline prompt bar appears. Type your instruction: "Add null check for userId" or "Rewrite this loop as a .map() call".
Review the Diff
Claude shows the proposed change highlighted in the editor. Green = added, red = removed.
Accept or Reject
Press Tab to accept the change, or Escape to discard it. You can also edit Claude's suggestion before accepting.
Multi-File Editing
One of Claude Code's most powerful features is the ability to edit multiple files in a single operation. This is essential for changes that span components — like adding a feature that touches the UI, API, database, and tests.
You: Add a "wishlist" feature to ThreadCo's store: 1. @types/product.ts — add a WishlistItem type 2. @api/wishlist.ts — create GET/POST/DELETE endpoints 3. @components/ProductCard.tsx — add a heart icon toggle 4. @__tests__/wishlist.test.ts — write tests for the API endpoints Use the same patterns as @api/cart.ts and @components/CartButton.tsx for consistency. Include error handling. Do not modify any existing tests or endpoints. Claude reads all referenced files, creates/edits 4 files, and maintains consistency across all of them because it can see the existing patterns.
When asking Claude to create new files, always @ an existing file that follows the pattern you want. Claude will match the style, error handling approach, naming conventions, and structure. This is more effective than describing the pattern in words — "make it like @cart.ts" communicates more information than 50 words of description.
The Complete Debugging Workflow
Here is the step-by-step debugging workflow that works best with Claude Code:
| Step | Action | Example |
|---|---|---|
| 1. Reproduce | Ask Claude to run the failing code and capture the error | "Run npm test for @cart.test.ts and show me the failures" |
| 2. Diagnose | Share the error output and ask Claude to identify the root cause | "Why is this throwing a null reference? Walk me through the code path" |
| 3. Hypothesise | Ask Claude to list possible causes ranked by likelihood | "List 3 possible causes. For each, how would we verify it?" |
| 4. Fix | Ask Claude to implement the fix | "Fix the root cause. Don't just add a null check — fix why it's null" |
| 5. Verify | Ask Claude to run the tests again | "Run the tests again. Did it fix all failures?" |
| 6. Prevent | Ask Claude to add tests that catch this class of bug | "Write a test that would have caught this bug before it shipped" |
This workflow mirrors how experienced engineers debug, with Claude handling the mechanical work (running commands, reading outputs, tracing code paths) while you make the strategic decisions (which hypothesis to pursue, whether the fix is appropriate, what tests to add).
Honest Limitations of AI Code Generation
Niche Libraries
Claude may have outdated knowledge of rapidly-evolving or less popular libraries. If you are using a niche framework, attach its documentation or recent changelog. Claude learns quickly from in-context docs.
Complex State Management
Code that involves intricate state machines, race conditions, or distributed system coordination requires extra scrutiny. Claude can generate the code, but subtle concurrency bugs are the hardest class of errors for any AI to catch. Test thoroughly.
Large-Scale Architecture
Claude can reason about architecture within the context window, but it cannot see your entire production system. For microservices spanning 50 repositories, provide architecture diagrams or summaries rather than expecting Claude to infer the full system from a few files.
Build and Deploy Configurations
Docker, Kubernetes, CI/CD pipelines, and cloud infrastructure configs are areas where Claude is helpful but where small errors have outsized consequences. Always test deployment changes in a staging environment before production — never deploy Claude-generated infra config directly.
ThreadCo: Reviewing the Webhook Handler
You (in Claude Code chat): Review @webhook-handler.ts for security issues. Focus on: input validation, authentication, and anything that could be exploited by a malicious POST request. Rate each issue: Critical / High / Medium / Low. Claude responds: CRITICAL: Missing Stripe signature verification (line 14). Any HTTP client can send fake webhook events. Add: const sig = req.headers['stripe-signature']; stripe.webhooks.constructEvent(payload, sig, process.env.STRIPE_SECRET); HIGH: Raw body not preserved — signature verification will fail because body-parser is consuming the stream before verification. ...
Hands-On Exercises
Pick a function you need to write. Ask Claude to write the tests first (without the implementation). Review the test cases — are they comprehensive? Do they cover edge cases? Then ask Claude to write the implementation that passes the tests. Run the tests. How many pass on the first try?
Take a file from your project that handles user input (a form handler, API endpoint, or webhook). Ask Claude to review it for security issues using the structured review format from this module. Did Claude find anything you hadn't noticed? Verify each finding — is it a real issue or a false positive?
Choose a function in your codebase that you've been meaning to refactor. Ask Claude to refactor it with explicit constraints: what to change, what NOT to change, and how to preserve behaviour. Review the diff line by line. Did Claude respect all constraints? Run the tests to verify behaviour is preserved.
Find or create a bug in a test file. Give Claude only the error message and the source file — do not tell it where the bug is. Ask Claude to identify and fix the bug. Track how many turns it takes and what additional files Claude requests. This reveals the information Claude needs for effective debugging.
Find the most complex file in your codebase — one that new team members struggle with. Ask Claude to explain it: first a high-level overview, then a line-by-line walkthrough. Ask follow-up questions until you are satisfied the explanation is complete and accurate. Save Claude's explanation as onboarding documentation for your team.