A practical migration guide for developers coming from Visual Studio Code. ▶ Interactive Tutorial
d3w, ci", yap)Almost every VS Code feature has a Neovim equivalent — LSP, debugging, Git, file explorer, fuzzy finding, auto-completion, themes. It just requires intentional configuration rather than a GUI marketplace.
The biggest hurdle is not learning shortcuts — it is understanding modal editing. VS Code is always in "insert mode." Neovim is not.
Neovim commands compose like a language:
| dw | delete word |
| ci" | change inside " |
| yap | yank around paragraph |
| >i{ | indent inside { |
| 3dj | delete 3 lines down |
. repeats your last change. This replaces a huge amount of what VS Code multi-cursor is used for.
-- Change first occurrence manually,
-- then move to next with n or f,
-- then press . to repeat the change.
You spend most time in Normal mode, actively navigating, copying, deleting, and transforming text — without typing new characters. It feels slow at first; it becomes faster than any GUI workflow.
Know these before you open a real file in Neovim.
Press Esc to ensure you are in Normal mode, then type :q! and hit Enter to quit without saving, or :wq to save and quit.
Press i to enter Insert mode — the status line will say INSERT. Type normally. Press Esc to go back to Normal mode.
u undoes in Normal mode. Ctrl+r redoes. No Ctrl+Z needed. The undo history is a tree — nothing is ever truly lost.
:w + Enter writes the file. Many configs map Ctrl+s to :w for muscle-memory comfort during the transition.
Arrow keys work. Once comfortable, use hjkl for left/down/up/right. Add w/b for word jumps, 0/$ for line start/end.
Press Esc repeatedly until the mode indicator shows Normal. Then type : and use the command line. :help keyword opens the built-in manual.
Direct translation of your VS Code shortcuts. Plugin required means you need a plugin from the recommended setup below.
| Action | VS Code | Neovim | Notes |
|---|---|---|---|
| Open file (fuzzy) | Ctrl+P | <leader>ff | Telescope plugin; leader is often Space |
| Command palette | Ctrl+Shift+P | : (command line) | All commands are typed; use Tab to autocomplete |
| Search in file | Ctrl+F | / then pattern | n/N for next/prev; regex supported |
| Search across files | Ctrl+Shift+F | <leader>fg | Telescope live_grep; uses ripgrep |
| Find and replace | Ctrl+H | :%s/old/new/gc |
g=all occurrences, c=confirm each |
| Go to definition | F12 | gd | Requires LSP attached |
| Peek / hover docs | Ctrl+K Ctrl+I | K | Requires LSP; opens floating window |
| Rename symbol | F2 | <leader>rn | LSP rename; updates all references |
| Code action / quick fix | Ctrl+. | <leader>ca | LSP code action |
| Format document | Shift+Alt+F | <leader>f | LSP format; or conform.nvim |
| Toggle file explorer | Ctrl+B | <leader>e | nvim-tree or neo-tree plugin |
| Split editor right | Ctrl+\ | :vsp or Ctrl+wv |
Navigate splits with Ctrl+w + hjkl |
| Toggle terminal | Ctrl+` | <leader>t or :term |
toggleterm.nvim for VS Code-like UX |
| Close tab / buffer | Ctrl+W | :bd or <leader>x |
Neovim has buffers, not tabs |
| Switch between open files | Ctrl+Tab | <leader>fb | Telescope buffers; or :bnext / :bprev |
| Multi-cursor select word | Ctrl+D | * then cgn | Search word, change, then . to repeat |
| Comment line | Ctrl+/ | gcc | Comment.nvim; gc+motion for range |
| Copy line up/down | Shift+Alt+↑/↓ | yyp / yyP | Yank line, paste below/above |
| Move line up/down | Alt+↑/↓ | :m .+1 / :m .-2 | Map to Alt+j/k in your config |
| Git diff / source control | Source Control panel | <leader>gg | Lazygit or fugitive.vim |
| Inline git blame | GitLens extension | virtual text via gitsigns.nvim | Appears automatically on current line |
| Indent / outdent | Tab / Shift+Tab | >> / << | In Normal mode; > in Visual for selection |
| Select all | Ctrl+A | ggVG | Go to top, visual line, go to bottom |
Don't build a config from scratch on day one. Start with kickstart.nvim — a single-file, well-commented config that sets up LSP, Telescope, Treesitter, and sensible defaults.
github.com/nvim-lua/kickstart.nvim — clone it, read every line, and modify from there. It is intentionally small and educational.
# Back up any existing config
mv ~/.config/nvim ~/.config/nvim.bak
# Clone kickstart
git clone https://github.com/nvim-lua/kickstart.nvim \
~/.config/nvim
nvim
lazy.nvim will install all plugins automatically. Wait for it to finish, then restart Neovim.
-- In init.lua, find the servers table:
servers = {
-- Add your languages:
pyright = {}, -- Python
ts_ls = {}, -- TypeScript
rust_analyzer = {}, -- Rust
}
mason.nvim (included) installs the LSP binaries automatically.
Every feature you relied on in VS Code has a Neovim counterpart.
Built-in via language-specific extensions (Pylance, Volar, etc.)
Configures the built-in LSP client. mason.nvim installs the same language servers VS Code uses.
Built-in completion UI from the language extension.
Completion engine that aggregates LSP, snippets, buffer words, and path completions into one popup.
Fuzzy file finder built-in.
Fuzzy finder for files, buffers, grep, LSP symbols, git commits, help pages, and more. Highly extensible.
Tree-view file browser with drag-and-drop.
Keyboard-driven file tree. neo-tree also shows git status and buffer list in the same sidebar.
Inline blame, hunk staging, git history per line.
gitsigns handles inline blame and hunk navigation. lazygit (in a float) or fugitive covers staging, commits, and history.
Panel at the bottom, multiple terminals via tabs.
Floating or split terminal that toggles with a keybind. Supports multiple named terminals.
Inline error/warning text next to the offending line.
Neovim shows virtual text inline by default. trouble.nvim gives you a VS Code-style Problems panel.
Format-on-save via extension settings.
Runs any formatter (prettier, black, stylua, gofmt) on save. Configured per filetype in Lua.
Colors matching brackets in different colours.
vim.opt.termguicolors = true and Neovim 0.9+ have native rainbow bracket highlighting via Treesitter.
Renames closing HTML/JSX tag when you edit the opening tag.
Treesitter-powered — accurately handles nested and self-closing tags.
A realistic pace for building Neovim fluency without burning out.
You were in Normal mode without knowing it. Always watch the mode indicator in the status line. Press Esc intentionally before every command.
Set vim.opt.clipboard = 'unnamedplus' to sync with the system clipboard, and install xclip or wl-clipboard on Linux. Kickstart does this for you.
Run :LspInfo to see which servers are attached. Run :Mason to install missing servers. Make sure the project has a root marker (package.json, pyproject.toml, etc.).
Your terminal must support true colour. Add export TERM=xterm-256color or better, use a terminal that sets COLORTERM=truecolor (Kitty, Alacritty, WezTerm, iTerm2).
There is no settings UI. All configuration is in ~/.config/nvim/init.lua. Open it with :e $MYVIMRC from anywhere.
In Normal/Visual mode, Neovim uses its own registers. y yanks, p pastes. For system clipboard interop, prefix with "+: "+y / "+p. Or set unnamedplus (see above).