Sanity

Vibe Coding with AI: How I Use Claude, Cursor, and Copilot to Build Faster

I've been leaning hard into AI-assisted development — Claude, Cursor, GitHub Copilot. Here's my honest take on what 'vibe coding' actually looks like day-to-day, what works, and where you still need your brain.

June 26, 202610 min readMuhammad Zohaib Ramzan
A developer using AI coding tools in a modern code editor with autocomplete suggestions

There’s a term floating around developer circles right now: vibe coding. The first time I heard it I rolled my eyes a little. It sounded like a euphemism for “winging it with ChatGPT.” But after spending the better part of a year leaning hard into AI-assisted development, I’ve come around. Vibe coding, done right, isn’t about switching your brain off. It’s about changing where you spend your mental energy.

This post is my honest account of how I actually use Claude, Cursor, and GitHub Copilot day-to-day — the workflows that genuinely save me time, the prompting tricks that took me a while to figure out, and the places where I’ve learned (sometimes the hard way) that AI still needs a human in the loop.

What “Vibe Coding” Actually Means to Me

Andrej Karpathy coined the phrase and described it as fully giving in to the AI — barely reading the code, just vibing. That’s a fun experiment, but it’s not how I work. My version is more pragmatic: I use AI to handle the mechanical parts of programming so I can focus on the meaningful parts.

Think about how much of a typical coding session is genuinely creative problem-solving versus writing boilerplate, looking up API signatures, or reformatting data structures. For me, honestly, it was probably 30% creative and 70% mechanical. AI has flipped that ratio. Now I spend most of my time thinking about what to build and why, and I let the tools handle a lot of the how.

That shift feels significant. Not because the code writes itself — it doesn’t, not reliably — but because the friction of going from idea to working prototype has dropped dramatically.

The Toolkit: Claude, Cursor, and Copilot

I use three tools regularly, and they each have a distinct role in my workflow. Treating them as interchangeable is a mistake.

Claude

Claude is my thinking partner. When I’m facing a genuinely hard problem — designing a data model, figuring out the right abstraction, or debugging something subtle — I open a Claude conversation and talk it through. Claude is exceptional at reasoning about tradeoffs. I’ll paste in a schema and ask “what are the failure modes here?” or describe a feature and ask “what am I not thinking about?” The responses are thoughtful in a way that feels qualitatively different from a search engine.

I also use Claude for long-context tasks: reviewing a whole module, summarising a codebase I’ve just inherited, or generating comprehensive documentation. The large context window is genuinely useful, not just a marketing bullet point.

Cursor

Cursor is where I actually write code. It’s a VS Code fork with AI baked deeply into the editor — not bolted on. The Cmd+K inline edit and the Composer (multi-file agent) are the two features I use constantly. Composer is particularly powerful: I can describe a feature in plain English, point it at the relevant files, and watch it make coordinated changes across the codebase. It’s not always right, but it’s almost always a useful starting point.

The other thing Cursor does well is context. It indexes your codebase so that when you ask it to “add error handling like we do in the auth module,” it actually knows what that means. That kind of project-aware assistance is a step change from generic autocomplete.

GitHub Copilot

Copilot is the background hum. It’s autocomplete on steroids, and after a while you stop noticing it consciously — you just find yourself writing code faster. It’s best at pattern completion: once it sees the shape of what you’re doing, it fills in the rest. Writing a series of similar functions, mapping over data, writing test cases that follow an established pattern — Copilot shines here.

I think of it as the tool that handles the last mile of code generation. Claude and Cursor help me figure out what to write; Copilot helps me write it quickly.

Prompting Strategies That Actually Work

Bad prompts get bad code. This took me longer to internalise than I’d like to admit.

Be specific about constraints, not just goals. “Write a function to fetch user data” is a weak prompt. “Write a TypeScript async function that fetches user data from /api/users/:id, handles 404 and 500 errors separately, and returns a typed User | null” is much better. The more constraints you give, the less the model has to guess.

Provide context aggressively. Paste in the relevant types, the existing function signatures, the error you’re seeing. AI models don’t have your codebase in their head — you have to bring the relevant pieces to them. In Cursor this is partly automated, but in Claude I do it manually and it’s worth the effort.

Ask for reasoning, not just output. When I’m unsure about an approach, I’ll ask Claude to explain why it’s recommending a particular pattern before I ask it to write the code. This catches misunderstandings early and often teaches me something.

Iterate in small steps. Don’t ask for a complete feature in one prompt. Ask for the data layer, review it, then ask for the UI, review it, then ask for the tests. Each step is a checkpoint where you can catch drift before it compounds.

Use negative constraints. “Don’t use any external libraries,” “don’t modify the existing interface,” “don’t add comments” — telling the model what not to do is just as important as telling it what to do.

What AI Genuinely Excels At

Let me be concrete about where these tools earn their keep.

Boilerplate and scaffolding. Setting up a new Next.js route with the right file structure, writing a Zod schema from a TypeScript type, generating a REST client from an OpenAPI spec — this stuff is tedious and error-prone when done by hand. AI handles it well and fast.

Refactoring. “Rename this variable throughout the file and update all the related comments” or “extract this logic into a reusable hook” — Cursor’s Composer is excellent at this. It understands the semantic intent, not just the text.

Test generation. Given a function, AI can generate a solid first pass at unit tests covering the happy path and obvious edge cases. I still review and extend them, but starting from something is much faster than starting from nothing.

Documentation. JSDoc comments, README sections, inline explanations — AI writes decent documentation quickly. I use it to generate a first draft and then edit for accuracy and tone.

Translating between formats. Converting a JSON structure to TypeScript types, transforming a SQL query to a Prisma query, adapting code from one framework’s idioms to another — these translation tasks are exactly what language models are good at.

Where You Still Need to Think

This is the part I wish more vibe coding evangelists talked about.

Architecture decisions. AI will confidently suggest an architecture. It might even be a good one. But it doesn’t know your team’s skill level, your deployment constraints, your existing technical debt, or your product roadmap. These decisions require judgment that comes from context the model doesn’t have. Use AI as a sounding board, not an oracle.

Debugging subtle bugs. AI is great at spotting obvious bugs. It’s much weaker at the subtle ones — race conditions, off-by-one errors in complex state machines, issues that only manifest under specific data conditions. For these, you need to understand the code deeply. If you’ve been vibe coding without reading the output carefully, you won’t have that understanding when you need it.

Security. I’ve seen AI-generated code with SQL injection vulnerabilities, insecure direct object references, and missing authentication checks. Not because the model is malicious, but because it’s optimising for “working code” not “secure code” unless you explicitly ask. Always review AI-generated code that touches auth, data access, or user input.

Data modelling. This is particularly relevant if you’re working with Sanity or any content platform. Getting the schema right — the relationships, the validation rules, the field types — requires understanding your content strategy and how editors will actually use the system. AI can help you think through options, but the decisions have real long-term consequences that require human judgment.

Practical Productivity Tips

Here are the concrete habits that have made the biggest difference for me.

Keep a context file. I maintain a CONTEXT.md in the root of each project that describes the tech stack, key conventions, and any non-obvious decisions. I paste this into Claude at the start of any significant conversation. It takes five minutes to write and saves hours of re-explaining.

Review every diff before accepting. In Cursor, it’s tempting to just hit “Accept All” when the Composer produces a big change. Resist this. Read the diff. You’ll catch mistakes, learn from the patterns the model uses, and maintain the mental model of your own codebase.

Use iterative prompting for complex features. Break big features into a sequence of small, reviewable steps. Each step should produce something you can test or at least read and understand. This keeps you in control and makes it easy to course-correct.

Don’t fight the context window. When a conversation gets long and the model starts losing track of earlier context, start a new one. Summarise what you’ve established so far and continue fresh. Fighting a degraded context is a waste of time.

Commit frequently. When you’re moving fast with AI assistance, it’s easy to accumulate a lot of changes before committing. Don’t. Small, frequent commits mean you can roll back cleanly if an AI-generated change turns out to be wrong in a way you didn’t notice immediately.

My Honest Take: Hype vs. Reality

Okay, let’s be real for a moment.

The hype says AI will replace developers. The counter-hype says it’s all hallucinations and you can’t trust any of it. Neither is right.

What’s actually true, from my experience: AI has made me meaningfully faster at the parts of development I found tedious, and it hasn’t made me worse at the parts that require real thinking. If anything, having more time to think has made me better at the hard parts.

But I’ve also seen what happens when developers lean on AI without building the underlying skills. The code looks fine until something goes wrong, and then there’s no mental model to debug from. Vibe coding without understanding is a trap. The tools are most powerful in the hands of someone who could write the code themselves — they just don’t have to anymore.

My day-to-day has genuinely changed. I ship faster. I explore more ideas because the cost of a prototype has dropped. I write more tests because generating them is no longer a chore. These are real, measurable improvements.

What hasn’t changed: the hard thinking. The architecture discussions. The code reviews. The debugging sessions at 11pm when something is broken in production. AI is a great collaborator for those moments, but it’s not a replacement for showing up with your brain engaged.

Where This Is All Heading

I think we’re still in the early innings. The tools are improving fast — context windows are growing, models are getting better at reasoning about code, and the editor integrations are becoming more seamless. The gap between “describe a feature” and “working, tested, deployed feature” is going to keep shrinking.

What I’m watching for: better support for long-running, multi-step tasks; tighter integration with testing and CI pipelines; and models that are genuinely good at not doing things — knowing when to ask a clarifying question rather than confidently generating something wrong.

For now, my advice is simple: pick up the tools, use them seriously for a few weeks, and pay attention to where they help and where they don’t. The developers who figure out how to work with AI effectively are going to have a real edge. Not because AI writes the code for them, but because they’ve freed up the cognitive bandwidth to do the work that actually matters.