After almost ten years on JetBrains IDEs, I moved to Cursor on top of VS Code. Here's what broke, what stuck, and the few extensions that made the switch worth it.
It was a Wednesday at the creator-economy platform I was working at, mid-feature, three tabs deep into a Rails controller, when I realized I’d been in Cursor for a full day and hadn’t reached for RubyMine once. That was the moment I knew the switch was actually going to stick.
For almost ten years I’d been a JetBrains person. RubyMine, PhpStorm, PyCharm, WebStorm, Rider, RustRover, IntelliJ. I had custom keymaps that felt like muscle memory and a quiet smugness about engineers who ran VS Code. JetBrains came with batteries included. It just worked.
I’d tried VS Code a handful of times over the years. Every time the same thing happened. I’d install ten extensions, the editor would slow to a crawl, something would conflict with something else, and I’d be back in RubyMine within a day. I wasn’t being stubborn. I was being efficient.
Then Cursor showed up.
I don’t switch tools for fun. I switch when the new thing does something the old thing can’t, and the gap is wide enough to pay back the migration cost. Cursor was that gap. The composer, the in-line edits, the way it threads context across files. None of that was reachable from JetBrains at the time. AI Assistant was there, but it wasn’t even close. I was working across many repositories at the time, on a Rails monolith plus React surfaces, plus the occasional Python script for the branded-mobile-app pipeline. Faster context-loading across files isn’t a nice-to-have at that scale. It’s the job.
So I gave myself three days. If I couldn’t get a Cursor setup that felt at least 80% as comfortable as RubyMine in three days, I’d go back. No ego attached.
Day one was rough. Day three I finally had something usable. Most of those days went into figuring out which extensions to install, which to uninstall, and which were silently fighting each other. Below are the four that did the heavy lifting. I run about 38 extensions total now, but if you stripped the install down to these four, Cursor would still feel like a real IDE.
The GitHub Pull Requests extension is the one I missed least obviously and use most. Reviewing PRs without leaving the editor, leaving comments inline against the diff, generating commit messages with AI, opening a PR straight from the branch. In JetBrains I’d flip between the IDE and the GitHub web UI ten times a day. Now I don’t. My settings.json for it is roughly:
{
"githubPullRequests.pullBranch": "always",
"githubPullRequests.defaultMergeMethod": "squash",
"githubPullRequests.fileListLayout": "tree",
"githubPullRequests.experimental.chat": true,
"githubPullRequests.notifications": "pullRequests",
"githubPullRequests.terminalLinksHandler": "github"
}
Nothing exotic. The pullBranch: "always" is the one that matters when you’re hopping branches constantly.
The Ruby LSP extension is from Shopify, and it’s the closest thing VS Code has to RubyMine’s intelligence. Go-to-definition, find references, format on save, inline diagnostics. On our older Rails repos it occasionally chokes on metaprogramming heavy files, but on the modern ones it’s quick and accurate. My config:
{
"rubyLsp.enabledFeatures": {
"documentHighlights": true,
"documentSymbols": true,
"foldingRanges": true,
"selectionRanges": true,
"semanticHighlighting": true,
"formatting": true,
"diagnostics": true,
"codeActions": true,
"hover": true,
"inlayHint": true
},
"rubyLsp.formatter": "rubocop",
"rubyLsp.rubyVersionManager": { "identifier": "rbenv" }
}
The day Ruby LSP started reliably resolving Rails associations was the day I stopped opening RubyMine “just for this one search”.
Inline test runs were the thing I really didn’t want to lose. RubyMine’s gutter “run this single test” button is one of the small things that makes Rails work tolerable. The Rails Test Runner extension brings that back. Right-click a test, run it. Run the file. Run with coverage. That’s it. That’s all I needed.
For databases I’m using the Database Client JDBC extension. It handles dev, staging, and production connections, exports to JSON or CSV in one click, and Cursor’s AI helps me write SQL against the schema. It’s not as polished as JetBrains DataGrip. It’s close enough. And the AI assist when writing a query against a 200-column table I’ve never seen before is a real productivity unlock.
The story I tell when people ask if the switch was clean: on the second day I lost half an hour of work because two extensions fought over format-on-save. Solargraph was trying to format a Ruby file at the same time Ruby LSP was. Whichever lost the race silently reverted my edits. I saved, the file looked right, I saved again, suddenly half my diff was gone.
First fix was the wrong one. I disabled format-on-save entirely and decided I’d just run rubocop -A from the terminal. That worked, but it killed the muscle memory that makes the editor feel like an editor.
Real fix: I uninstalled Solargraph. Ruby LSP is the modern path. There’s no good reason to run both. Then I pinned the formatter explicitly per language in settings.json:
{
"editor.formatOnSave": true,
"[ruby]": {
"editor.defaultFormatter": "Shopify.ruby-lsp",
"editor.formatOnSave": true
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true
},
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}
The lesson, and this is true for any VS Code-style editor, is that “install everything that looks useful” is a trap. Pick one tool per job and pin it.
I won’t pretend the keymap transition was painless. RubyMine’s “find usages” was Alt+F7. In VS Code-land that’s Shift+Alt+F12 by default, which my hand refuses to do. So I rebound the things I use ten times a day to where my hand expects them:
[
{ "key": "alt+f7", "command": "references-view.findReferences" },
{ "key": "ctrl+b", "command": "editor.action.revealDefinition",
"when": "editorTextFocus" },
{ "key": "ctrl+shift+a", "command": "workbench.action.showCommands" },
{ "key": "shift shift", "command": "workbench.action.quickOpen" }
]
The “double-shift to search everywhere” binding alone bought me back maybe half my IntelliJ comfort. There’s a “JetBrains IDE Keymap” extension that does most of this for you, but I prefer rebinding the five or six I actually use and learning the rest in the new shape.
The JetBrains debugger. Refactor rename across a full Rails monolith. The structural search and replace. Cursor catches up on some of these via AI, but not all. If I were doing heavy Rust work I’d probably still run RustRover for the debugger alone. For Rails and TypeScript at the scale I’m working at, Cursor wins.
Thanks for reading. If you’ve got thoughts, send them my way.