Best Tips for Working With Cursor AI

Plan before you prompt

The single biggest improvement you can make. Before dropping a big task into Cursor, sketch out what you actually want — which files will be touched, what the function signatures look like, what the expected behaviour is. Even a rough outline in a comment block at the top of your prompt dramatically improves the output. Cursor is very good at executing a clear plan. It’s less good at figuring out the plan itself.

Write tests first, then implementation

This one sounds like extra work but it pays back immediately. Tell Cursor: “Write failing tests for this feature first, then implement the code, then run the tests and fix anything that fails.” You get two things from this — a guarantee that the code actually does what you asked, and a natural brake on hallucinations. If it writes tests that match your spec and then writes code that passes them, you’ve got something real. If the tests don’t match what you wanted, you catch it before the code is written.

Give it context explicitly — don’t make it guess

Use @filename, @folder, or paste in your schema and types directly. Cursor can search your codebase but it’s much better when you point it at exactly the right things. If you’re building a new endpoint, paste in the existing one you want it to match. If you’re working with a database model, drop the schema in. The more specific the input, the more specific the output.

Set up a .cursorrules file for your project

This is a file in your project root that tells Cursor how to behave — your preferred patterns, libraries, conventions, architecture decisions. It’s like a persistent system prompt that applies to everything in the repo. Without it you’re re-explaining the same things every session. With it, Cursor already knows to use async/await instead of promises, to follow your folder structure, to add JSDoc to functions, to use your preferred test setup. Teams that set this up properly get much more consistent output across the whole codebase.

Break big tasks into stages

Asking for too much at once is one of the most common ways to get mediocre output. “Build me a full authentication system” will get you something generic. “Set up the User model with the fields in this schema, then we’ll add the auth endpoints” gets you something grounded in your actual project. Do it in stages — each one focused, each one reviewable before moving on.

When it goes wrong, roll back — don’t patch

This is probably the most important habit to build. When Cursor goes down a bad path, the instinct is to keep prompting it back toward what you wanted. That usually makes things worse. The better move is to restore a checkpoint, take a step back, figure out why the prompt produced the wrong result, and try a different approach. Cursor has checkpoint restoration built into the chat history — use it. And commit often so rolling back doesn’t cost you more than a few minutes of work.

Use it for the stuff that slows you down, not the stuff that challenges you

Boilerplate. Tests for code you already understand. Wiring up a third-party SDK. Converting REST handlers to async. Generating TypeScript types from a JSON response. This is where Cursor saves the most time with the least risk. The architecture decisions, the data modelling, the tricky edge cases — those still need you. The more you use Cursor for the low-judgment work, the more headspace you have for the high-judgment stuff.

Ask it to audit your own code

One of the more underused things you can do — paste in a function or a module and ask Cursor to look for security issues, missing error handling, edge cases, or performance problems. It won’t catch everything, but it catches enough to be worth doing before a PR. Particularly good for things like: unsanitised inputs, unprotected routes, missing auth checks, N+1 queries.