I spent my first month with Claude Code getting mediocre results. I’d type something vague, get something vague back, and then blame the tool. Turns out the tool was fine. My prompts were garbage.
Most developers use Claude Code like a search engine. They type “fix this bug” or “add authentication” and wonder why the output misses the mark. But Claude Code isn’t Google. It’s more like a junior developer sitting next to you. The more context you give, the better the work you get back.
After months of daily use, I’ve landed on a set of prompts that consistently deliver. Not sometimes. Consistently. Here’s exactly what I type and why each one works.
Bug Fixing Prompts
This is where I see the biggest gap between good and bad prompts. Bad bug reports frustrate human developers. They frustrate Claude Code too.
Don’t do this:
This doesn't work
I’ve typed this exact thing before. You know what Claude Code does? It guesses which file you’re talking about, guesses what “doesn’t work” means, and writes a fix for a problem you might not even have. It’s not helpful.
Here’s what I actually type:
Read src/api/auth.ts — the refresh token logic fails when the token expires exactly at midnight. Fix it and run the tests.
Three things make this work. First, I give the exact file. No guessing. Second, I describe the specific behavior that’s broken, not just “it’s broken.” Third, I include a verification step — run the tests. That last part is huge. Claude Code will actually run the tests and tell you if the fix worked.
I used to skip the verification step because I figured I’d check it myself. Don’t do that. Let Claude Code close the loop. It catches things you’d miss.
Feature Building Prompts
Building features is where vague prompts cost you the most time. You’ll get something back, realize it’s not what you wanted, and spend longer fixing it than if you’d just written it yourself.
Don’t do this:
Add user profiles
What does “user profiles” even mean? A page? An API endpoint? A database table? All of the above? Claude Code will pick one interpretation and run with it. Probably not the one you wanted.
Here’s what I actually type:
Add a GET /api/users/:id endpoint that returns the user's profile with their last 5 projects. Use the existing Prisma client in src/lib/db.ts.
This works because it’s specific about the endpoint, specific about the data shape (profile plus last 5 projects), and it points to existing code that should be used. That last part matters a lot. Without it, Claude Code might create a new database connection or use a different ORM entirely.
When I’m building something bigger, I break it into multiple prompts. One for the API endpoint. One for the frontend component. One for the tests. Each prompt is small, specific, and self-contained. I tried doing everything in one massive prompt once. Never again.
Refactoring Prompts
Refactoring is where Claude Code genuinely shines, but only if you set the right constraints.
Here’s what I type:
This file is 400 lines. Split it into smaller modules without changing any behavior. Run tests after to make sure nothing broke.
Two things matter here. The clear goal — split it up. And the safety constraint — don’t change behavior, prove it with tests. Without that second part, Claude Code might “improve” your code while refactoring it, introducing subtle behavior changes that break things three weeks later.
I also use this one a lot:
The handlePayment function in src/services/payment.ts is doing too much. Extract the validation logic into a separate function in the same file. Keep the same exports.
“Keep the same exports” is a constraint I always include now. I learned this the hard way when a refactor changed the module’s public API and broke six other files that imported from it.
Testing Prompts
Writing tests is one of the things I genuinely hate doing manually. Claude Code is great at it, but only if you tell it what to test.
Here’s what I type:
Write unit tests for src/utils/pricing.ts. Cover edge cases: zero quantity, negative prices, and discounts over 100%.
The key is specifying the edge cases you care about. If you just say “write tests for this file,” you’ll get happy-path tests that don’t catch real bugs. I’ve been burned by that enough times.
Another one I use weekly:
There's no test coverage for the error handling in src/api/orders.ts. Write tests that verify each error case returns the correct status code and error message.
This is specific about what’s missing (error handling tests) and what to verify (status codes and messages). Claude Code nails this every time because there’s no ambiguity about what “done” looks like.
For integration tests, I give even more context:
Write an integration test for the checkout flow. Create a user, add two items to cart, apply a discount code, and complete the purchase. Use the test helpers in src/test/helpers.ts.
Pointing to existing test helpers prevents Claude Code from reinventing your test setup. Trust me on this one.
Code Review Prompts
I started using Claude Code for code reviews about three months ago. It won’t replace a human reviewer, but it catches things humans miss — especially security issues.
Here’s what I type:
Review the last commit for security issues, performance problems, and logic errors. Ignore style.
That “ignore style” part is critical. Without it, half the review will be about naming conventions and missing semicolons. I don’t need an AI to tell me about formatting. I have ESLint for that.
For deeper reviews, I use:
Read through src/api/ and flag any endpoints that don't validate input or don't check authentication. List each one with the file and line number.
This found two unprotected endpoints in a project I’d been working on for months. I felt embarrassed and grateful at the same time.
Git Prompts
These are short but they save me real time every single day.
Commit messages:
Look at the staged changes and write a commit message. Focus on why, not what.
I used to write commit messages like “update auth logic” which tells you nothing. Claude Code writes messages like “Fix token refresh failing for users in UTC+ timezones” because it actually reads the diff and understands the intent. Way better than anything I’d write at 6pm on a Friday.
PR descriptions:
Create a PR description from the commits on this branch vs main.
This one’s a time saver. It reads all the commits, summarizes the changes, and formats it nicely. I usually edit it slightly, but it gets me 90% there.
Understanding changes:
What changed in the last 3 commits? Give me a plain English summary, not a diff.
I use this when I come back to a project after a few days and need to remember where I left off. Works perfectly.
Learning and Understanding Prompts
These are the prompts I use when I join a new project or need to understand code I didn’t write.
Here’s what I type:
Explain how the auth middleware in src/middleware/auth.ts works. I'm new to this codebase.
That “I’m new to this codebase” bit changes the response. Without it, Claude Code assumes you have context and skips the basics. With it, you get a thorough explanation that connects the dots.
For impact analysis, this is my go-to:
What would break if I removed the cache layer in src/lib/cache.ts?
This saved me once from ripping out a cache that three different services depended on. Claude Code traced the dependency chain and told me exactly what would fail. Would’ve taken me an hour to figure that out manually.
Another one I use when onboarding:
Map out the request lifecycle for POST /api/orders. Start from the route handler and follow it through middleware, validation, database calls, and response.
This gives you a complete picture of how a request flows through the system. It’s like having an architect walk you through the codebase.
The Anti-Patterns
Some prompts never work well, no matter how you phrase them. I’ve tried.
Too vague:
Make this better
Better how? Faster? More readable? More maintainable? Claude Code will guess and it’ll guess wrong.
Too long:
If your prompt is more than a paragraph, you’re probably asking for too much at once. Break it up. Claude Code handles focused tasks well and sprawling tasks poorly.
Asking for architecture opinions without context:
Should I use microservices or a monolith?
You’ll get a generic answer because there’s no context to give a specific one. You wouldn’t ask a new team member this question on their first day. Don’t ask Claude Code either.
Mixing concerns:
Fix the login bug, add password reset, and also refactor the user model while you're at it.
Pick one. Do it well. Move on to the next.
What Makes a Good Prompt
Every prompt I rely on has three things in common.
It’s specific. Not “fix the bug” but “fix the midnight token expiry bug in src/api/auth.ts.”
It’s actionable. Not “think about how to improve performance” but “add caching to the getUserById query using Redis.”
It includes a way to verify the result. Not just “write the code” but “write the code and run the tests” or “write the code and show me the output.”
That’s it. Get those three things right and Claude Code becomes a genuinely useful part of your workflow. Not a magic box that writes code for you. A tool that does exactly what you ask, as long as you ask well.