12 Cursor Tips From Knowing It to Being Good at It
A year of writing code in Cursor, roughly 30 mistakes made along the way, and 12 tips that will visibly make you faster. From the basic shortcuts and Composer to the @codebase index and .cursorrules customization — every tip comes with a code example, and they all work whether you’re new or experienced.
※ This article is based on Cursor’s 2025-2026 feature set; the UI may change with new versions. You can cross-check every action against Cursor’s official docs.
First, one mindset shift
Cursor isn’t “VS Code with AI.” It’s “an AI that writes code using your codebase as context.”
That distinction matters — you’ll find that how well you use it doesn’t come down to “how good your prompts are,” it comes down to “how accurate the context you give it is.”
Of the 12 tips below, 8 are about “how to give it the right context.”
The basics — the 4 you should use every day
01 Use Cmd+K to edit a snippet — don’t select everything and ask the AI to rewrite it
The most common beginner mistake: select a big chunk, hit Cmd+K, type “optimize this.”
The result — the AI changes things you didn’t want changed.
The right way: select the smallest range possible and write a specific instruction.
// Wrong — the whole function is selected
"optimize this"
// Right — only the problematic line is selected
"change this forEach to a map and return a new array"
The smaller the range, the less the AI touches things by mistake.
02 Use Cmd+L to open Chat and ask questions — don’t tell it to edit directly
Chat and Edit are two different things:
- Chat (Cmd+L): ask questions, discuss direction, explain code
- Edit (Cmd+K): edit the code directly
The flow: first use Cmd+L to discuss “how to do it,” confirm the direction, then use Cmd+K to make the change.
Telling the AI to just edit is the fastest way to wreck an entire file.
03 Use Tab to accept autocomplete, Esc to reject it
A lot of people don’t realize this — hitting Tab to accept or Esc to reject both get sent back to Cursor as signals.
That’s not the same as “your Cursor is personalizing itself to you in real time” — Cursor doesn’t claim that. The more accurate description: your accept/reject is one signal among many, aggregated across all users, used to iteratively improve the Tab model — not a live, per-user customization.
Still worth hitting both deliberately — the more accurate you are, the clearer you’ll get on what suggestions are actually worth keeping.
04 Switch to Composer for cross-file changes
Cmd+K edits “one file”; Composer (Cmd+I) changes “an entire feature.”
When to use Composer:
- Adding a new feature that touches 3-5 files
- Refactoring a module while changing both backend and frontend
- Converting a component from a class to a hook
The key — when Composer is open, use @ to specify which files it should look at. Don’t, and it’ll just guess.
Context management — the 4 advanced ones
05 Make good use of @ to specify context
This is Cursor’s most powerful feature, and the one most people overlook.
A few key @ usages:
@filename— use this file’s contents as context@codebase— index the whole project; the AI finds the relevant code itself@docs— reference official docs (the ones you’ve set up)
One more thing: as of Cursor 2.0 (Oct 2025), the manual @web and @git symbols have been removed — the Agent now decides on its own when to search the web or check git commits/diffs, so you don’t need to type them anymore.
Example:
"@auth.ts @user.ts add OTP to the login flow,
referencing @docs/twilio for the SMS API"
This is 5x better than “please help me add OTP” — because the AI knows which files to look at and which API to follow.
06 Use .cursor/rules/ (or .cursorrules) to teach it your coding style
Create a .cursor/rules/ directory in your project root with .mdc rule files inside (or simply use an AGENTS.md / CLAUDE.md at the root), and Cursor will automatically pull them into every prompt. The older approach was a single .cursorrules file — that format has been marked legacy and deprecated by Cursor, and migrating to the newer format is recommended, though the idea is the same, so the example below still uses the old format:
Example:
// .cursorrules (legacy format, officially deprecated by Cursor — migrate to .cursor/rules/*.mdc)
# Project Conventions
- Use TypeScript strict mode
- Prefer functional components over class components
- Use named exports, no default exports
- All API calls go through `lib/api.ts`
- Tailwind classes go in `className`, no inline styles
# Code Style
- No semicolons
- Single quotes
- 2-space indent
# Testing
- Every new function needs at least 1 unit test
- Use Vitest, not Jest
# Forbidden
- Don't use `any` ─ use `unknown` instead
- Don't use `console.log` in committed code ─ use logger
With this rule file in place, the code the AI writes will be consistent with your project’s style — no more fixing it every single time.
07 Restrict which files the AI is allowed to touch
There are files you don’t want the AI touching — things like schema migrations, env config, test fixtures.
Add them to .cursorignore:
// .cursorignore
*.env*
migrations/
__fixtures__/
secrets/
*.lock
The AI won’t index these files, and it won’t go changing them on its own.
08 Use @symbol to reference a specific function / class
Don’t paste an entire function to the AI — reference it with @symbol:
"write tests for `@calculateTax`,
covering edge cases including negative input and zero"
The AI will automatically pull in that function’s full implementation as context — no copy-pasting needed.
Advanced mindset — the 4 that separate engineers from vibe coders
09 When writing a prompt, state the why before the what
The difference is huge:
// Ordinary prompt
"add a button that calls an API when clicked"
// Good prompt
"Users report they can't find the export feature.
I want to add an export button on the settings page
that calls the /api/export endpoint when clicked,
shows progress, and downloads a CSV when done.
Follow the UX pattern in @ImportModal.tsx"
The benefits of stating the why:
- The AI knows it’s a “user pain point” and will proactively add error handling
- The AI knows the UX expectation and will proactively add a loading state
- The AI knows your context and won’t produce something that contradicts your existing patterns
10 Treat the AI as a conversation partner, not an output tool
One habit that changed how I use Cursor — before any big change, I discuss the approach with it first using Cmd+L.
The flow:
- I propose an approach: “I’m thinking of switching auth to JWT — what are the pitfalls?”
- The AI lists 5 trade-offs
- I push back: “How would you handle #3?”
- The AI answers, and I add more context
- Once we reach consensus, only then do I open Composer and start
That 10-minute conversation saves you the 2 hours of “realizing halfway through that the direction was wrong.”
11 Take small, fast steps — don’t cram a ton into one prompt
A lot of people prompt like this:
"build me a complete blog system:
- user login
- post CRUD
- comments
- subscriptions
- newsletter
- admin dashboard"
The result — 80% of what the AI produces is junk, and you have to pull it apart yourself.
The right way — ask it to do one small thing at a time:
- First: “build the user schema + register / login API”
- review, adjust, commit
- Then: “build the post model + CRUD API”
- review, adjust, commit
- …
One small step at a time, reviewing every step. That way the final result is 90% you’re OK with, not 80% you have to throw away.
12 Teach it to say “I’m not sure”
The AI’s biggest problem isn’t “making mistakes” — it’s “not knowing it’s wrong” and handing you confident-sounding wrong answers.
Add this to your rules file (.cursor/rules/*.mdc, or the legacy .cursorrules) — I find the effect noticeable:
# Communication
- If you're not sure about something, say "I'm not sure"
- If you need more context, ASK before writing code
- Never invent library APIs ─ if you don't know if a method exists, say so
- Cite the file/line you're referring to when making claims
With this rule in place, the AI asks you when it’s unsure instead of just making things up.
Finally — don’t treat Cursor as a god
Cursor is a tool, not a senior engineer. Its value — depends on what kind of context and instructions you give it.
People who use it well find themselves focusing more on “defining the problem, designing the solution, making decisions” — writing code becomes the least time-consuming part.
People who use it badly find themselves becoming a “paste whatever the AI gives me” mover — and 6 months later the codebase is a ruin they can’t even understand.
Cursor gives you speed.
Your engineering discipline gives you direction.
Speed without direction is a car crash.
Further reading — Engineers in the AI Era series
FAQ
- What's the difference between Cmd+K, Cmd+L, and Composer, and which should I use?
- Cmd+K edits a small snippet in one file, Cmd+L opens Chat to ask questions and discuss direction without editing, and Composer handles an entire feature across multiple files. The article suggests discussing with Cmd+L first to confirm the direction, then editing with Cmd+K or Composer.
- Can I still use .cursorrules, or has it been deprecated?
- It still works, but Cursor has marked it as legacy and deprecated. The recommended approach is a .cursor/rules/ directory with .mdc files, or a single AGENTS.md or CLAUDE.md. The idea is the same, keeping the AI's code consistent with your project's coding style.
- Should I ask Cursor to build an entire feature in a single prompt?
- No. Cram too much in and about 80% of what the AI produces is junk you have to pull apart yourself. The article recommends small, fast steps: ask for one small thing, then review, adjust, and commit before the next, so the final result is around 90% you're OK with.
Building something and stuck?
Get the field notes every two weeks, or reach me directly on LINE.