After three months of daily use, here's what I learned about getting the most out of Cursor for AI-assisted development. This guide focuses on practical tips that significantly impact productivity.

You may not be ready to try Cursor yet if you have any doubts on the talent on the Cursor team, or the necessity of a fork, or what it can add on top of Copilot at all. If so, you may first want to check out some demo videos, and this podcast.

This post assumes you are currently using VS Code, considering Cursor, and are writing in the JavaScript/TypeScript ecosystem.

If you're using other languages, this post can easily be adapted to your situation.

If you're using another Editor (Vim, Emacs, etc), I understand the friction of trying Cursor is much higher. For VS Code users there is basically no friction, because Cursor is a fork of VS Code. After you import settings, just the icon is different basically. But if you are coming from let's say Vim, it's a big change. And I can understand you'd rather take a pass, or wait until there is a Cursor equivalent for that editor.

But, maybe you don't have to. You could still point Cursor to your codebase and use it exclusively for prompting in Composer. So all the AI assisted coding happens there, but as soon as you're done, ready to clean up or to just hack yourself again, you switch back to your daily driver (be it Vim, Emacs, or whatever). It beats copy pasting context & suggestions back and forth between your editor and browsers, that's for sure. So you could just regard Cursor as the window into the LLM-assisted coding world, without having to learn anything but typing English in the Composer window and hitting accept.

Back to the VS Code users thinking to switch to Cursor fully, it's good to mention that you don't need this post. You can install Cursor and it will immediately bring benefit writing code due to very powerful tab completion. It's there without having to learn anything. Just hit tab if you like some suggestion that automatically appears. But, if you want a headstart to get the most out of Cursor, this post is for you.

🎯 Setup

Your effectiveness with Cursor starts with proper setup and breaking old habits. The biggest hurdle isn't learning Cursor, it's unlearning to start VS Code. I'm not kidding. You won't notice because you'll be your usual happy normal productive working on problems. This is the hardest part. So help yourself and delete or misplace VS Code so that you don't automatically start it and another entire day goes by without giving Cursor a shot.

  • Download Cursor from the website
  • Pay for the subscription, $20/mo it's worth it (tho there is a free trial)
  • In Cursor Settings -> Beta -> Composer -> Enable
  • Disable all models except Anthropic claude-3-5-sonnet-20241022 (best at the time of writing, update as needed)
  • Import VS Code settings, you now basically have your old VS Code back since Cursor is a fork of it
  • Move the old VS Code to a backup location
  • Update terminal aliases (code or whatever you used in the Terminal, now opens Cursor)

🚀 How I use it:

  1. Use tab a lot, contrary to VS Code, Cursor Tab can propose to jump to other lines, as well as multi-line edits
  2. For small refactorings: select a few lines, hit CMD+K, describe desired changes, CMD+SHIFT+ENTER to accept
  3. For larger scope changes (entire files, multiple files): Open Composer (CMD+SHIFT+I). Add relevant files and documentation URLs with @. Describe changes. Hit CMD+ENTER to submit to the LLM, then CMD+SHIFT+ENTER to accept its proposal
  4. For brand new projects or subprojects, you can create a new throwaway (VS Code) Workspace, even inside an existing project, and then reference all of its files with @codebase
  5. You can mention Markdown files and ask to update. For instance:
The desired state is in @PLAN.md. Please update the @codebase to match

Or:

Make sure @README.md reflects the current state of the @codebase

You can have Cursor write a PLAN.md first, really iterate and do a good job on that, then keep @PLAN.md-mentioning it in your prompts for guidance. Then your prompts can remain shorter while the LLM has full context.

There also is Cursor Chat, some folks are very happy with it for single file changes, will try that but haven't yet writing this post, for me it's 75% Composer, 15% Tab, 5% CMD+K (Edit), 5% AI Fix In Chat (when there is a type or linting error, inside the modal there is this button, and often times it will work to fix it).

Part of Cursor's magic is that they can reliably apply the LLMs suggestions to your codebase. Having LLMs output correct patch diffs is notoriously hard as it must keep track of all line numbers and small changes. Cursor solves this with their own AI that takes LLM suggestions and cleanly applies them to your codebase, it interacts with your language server to make sure formatting is taken care of. And since a short time, you can opt into a beta that does iterations until type issues are also resolved.

🔧 Development Flow

AI-assisted development shifts from typing to reviewing. Your role becomes more strategic: guiding the AI rather than writing every line. You will have to correct the LLM a lot, you'll grow an intuition for better prompts while doing this. Ultimately, even if you end up throwing more than half of the generated code away, you'll still be able to get massive productivity gains out of this, if you are willing to work this way.

Doesn't have to be black/white though. You can always dive back in and do text manipulations yourself. Even for entire days. But having the ability to jump back to LLM-assisted dev is powerful, even if just for those times when you're low on creative energy to write the code yourself.

Three months in, in my experience, for best results:

  • Context is king! Too much may confuse, too little and there aren't enough data points to meaningfully extrapolate the next steps for the LLM. You realize a lot of context was in your mind, and you need to share just enough to let the LLM work efficiently.
  • Use common tech (Next.js, React, Tailwind, shadcn/ui)
  • Add API documentation links in prompts
  • Use TypeScript instead of JavaScript, types are meaningful context to guide the LLM, and to check the generated code against
  • Use tooling that allow you to quickly test the LLMs changes. For example:
    • Switch from ESLint to Biome
    • Switch from Jest to Vitest, and keep it in watch mode so you instantly see breakage
  • Don't let the LLM write tests until you are happy with the core functionallity, then pin it down with tests, writing tests too early can confuse the LLM and you while you're still making big changes every iteration

Leverage Version Control, a lot:

  • Always start a branch first
  • Commit working code frequently
  • Reset the working directory if you're unhappy with the recent changes, then prompt with a new idea for approach/context

⚠️ Common Pitfalls, .cursorrules

Success with Cursor requires catching issues early. Watch for:

  • Outdated file paths after renames, it may require restarting Cursor to fix
  • Framework version mismatches (Next.js 13 vs 14)
  • If Claude goes down, Cursor will automatically switch us over to GPT-4o, your results will drastically deteriorate and it's better to switch back to manual coding until Claude is back, make sure you notice (there is a little indicator about this when writing prompts)
  • When you copy paste lines from a Terminal or code tab into a prompt, Cursor may add it as a reference. This may not be immediately clear to a beginner. What's more, if you're iterating and feeding errors, at the time of writing Cursor won't let you submit empty text areas. And references don't count towards a prompt, so you end up pasting an error and typing an obligatory: "still not working", just to be able to submit it.

To help some of the above issues, like version mismatches, you can create a .cursorrules in the root of your Workspace that mentions for instance:

- Favor Next.js 14 over 13
- Don't use the pages router
- Favor `contentGapItemSchema = z.object()` over `ContentGapItemSchema = z.object()`
- Favor `async run() {` over `run = async () => {` inside ES6 classes
- Favor `from './PosterboyCommand.ts'` over `from './PosterboyCommand'`
- Favor `return ideas.filter(isPresent)` over `ideas.filter((idea): idea is Idea => idea !== null)`
- Favor `if (!(err instanceof Error)) { throw new Error(`Was thrown a non-error: ${err}`) }` inside
  `catch` blocks to ensure the `error` is always an instance of `Error`
- Favor using real paths (`../lib/schemas.ts`) over aliases (`@/app/lib/schemas`).
- Favor using `.tsx` over `.jsx`.
- Favor `for (const comment of comments) {` over `comments.forEach((comment) => {`
- Do not touch `.env` files!
- Favor `satisfies` over `as`, consider `as` a sin
- Favor `unknown` over `any`, consider `any` a sin
- Favor validating data with Zod over using `any` or custom type guards
- Favor Yarn (4) over npm

The actual .cursorrules is dependent on your project and taste of course.

I wouldn't recommend blindly adding a bunch of stuff there, as it just grows the context, which may be unrelated to the very thing you are asking, which means less focus, and worse results. As with great design:

Perfection is achieved not when there is nothing left to add, but when there is nothing left to take away - Antoine de Saint-Exupery

Similary, for the best results, we want to become masters of context management, and remove things that resemble noise for the task at hand.

In this vain I'd recommend starting with a minimal .cursorrules and then grow it with the things you actually run into as you are using Cursor with your codebase. Also note that if you switch models within Cursor, some rules may not apply anymore.

💡 Pro Workflows

Maximize productivity by working smart:

  • Use separate Cursor Notepads for different projects, you can add common context in each of them and save retyping a bunch of @ mentions if you switch between them.
  • Work during AI generation. Work on two projects at the same time, or find a low brainload task to do while the AI does its thing.
  • Select the correct model in your prompt window. Default to the latest Claude Sonnet. Only when it struggles, you can escape to o1-preview at the time of writing by OpenAI. It is slow, expensive, requires buying separate credits at Cursor, but, it can sometimes give more profound suggestions when Claude Sonnet struggles (rarer since the latest update)

🎮 Daily Practice

Credits in Cursor Settings

The key to productivity is maintaining good habits:

  • Check Cursor credits regularly, you may be throttled if you burn through them too quickly. While updating this post I'm at 450/500 fast requests and just 11 days into the month. Time to buy more credits! Last month I topped up twice bringing my bill to $60. Very much worth it tho, I shipped three major projects at Transloadit.
  • Watch for model availability, if a new Sonnet comes out, you want to upgrade
  • Keep context lean, yet comprehensive
  • Review generated code thoroughly, augmented with automation where possible (fast linting, fast tests, always open and running in watch mode)
  • Use .cursorrules to help with common pitfalls or desired coding styles

If you have tips that I didn't cover please reply to this tweet and I'll update the post.