How to Use Vim Inside VS Code: Setup and settings.json
This article covers how to get Vim key bindings inside VS Code, and how far you can take the configuration.
The short answer: search for “Vim” in the Extensions view, install the one published by vscodevim, and you have normal and insert modes plus hjkl movement straight away. No configuration file is required.
The extension is VSCodeVim, extension ID vscodevim.vim. This article covers the three-step install, then the settings worth knowing if you want to go further. Checked on VS Code 1.135.0 with VSCodeVim 1.32.4.
What VSCodeVim actually gives you
VSCodeVim reproduces Vim’s modes and key bindings inside the VS Code editor, while leaving the rest of VS Code intact.
Once installed, the status bar shows the current mode — NORMAL, INSERT and so on. Movement with hjkl, dd to delete a line, yy to yank: the basics behave as they do in Vim.
Press : to enter ex mode for file operations, or / to search. For anyone arriving at VS Code from Vim, this removes the single largest source of friction.
At the same time you keep VS Code’s completion, debugger, Git integration and every other extension. The trade is not “Vim or VS Code” — you get the editing model of one and the tooling of the other.
Installing it in three steps
Search the Extensions view, install, and open a file. There is no restart and no config file.
- Open View > Extensions from the menu bar
- Type “Vim” in the search box
- Install the one published by vscodevim
Several Vim-related extensions appear in the results. Check that the publisher is vscodevim before installing.
Open any file afterwards and the status bar shows the mode. Below is NORMAL mode.
Press i and it switches to INSERT.
If the mode indicator changes and hjkl moves the cursor, the install is done. If you have no strong opinions about key bindings, you can stop here.
Customising key bindings in settings.json
What used to live in your vimrc goes in settings.json instead. Every setting name starts with vim..
To open settings.json:
- Code > Settings > Settings from the menu bar
- Click the “Open Settings (JSON)” icon in the top right
Key bindings are set through vim.insertModeKeyBindings, vim.normalModeKeyBindings and vim.visualModeKeyBindings, one per mode.
{
// use the system clipboard
"vim.useSystemClipboard": true,
// highlight all search matches
"vim.hlsearch": true,
// enable easymotion
"vim.easymotion": true,
// search with * and # in visual mode
"vim.visualstar": true,
// ignore case when searching
"vim.ignorecase": true,
// incremental search
"vim.incsearch": true,
// enable CamelCaseMotion
"vim.camelCaseMotion.enable": true,
// set the leader key to backslash
"vim.leader": "\\",
// map jj to Esc in insert mode
"vim.insertModeKeyBindings": [
{
"before": ["j", "j"],
"after": ["<Esc>"]
}
]
}
Every setting above is valid in VSCodeVim 1.32.4. This is JSON, so a missing comma stops the entire file from loading — if a setting appears to have no effect, check for a syntax error before anything else.
When VSCodeVim steals a VS Code shortcut
Hand individual keys back to VS Code with vim.handleKeys.
To reproduce Vim faithfully, VSCodeVim captures Ctrl combinations such as Ctrl+f (page down in Vim). If you would rather keep VS Code’s find:
{
"vim.handleKeys": {
"<C-f>": false,
"<C-a>": false
}
}
Only the keys set to false revert to VS Code’s behaviour. Rather than disabling everything up front, add keys one at a time as you hit them.
To switch the whole extension off temporarily — handing the keyboard to someone during pairing, for instance — set vim.disableExtension to true.
If typing feels sluggish
Move VSCodeVim into its own process with extensions.experimental.affinity.
{
"extensions.experimental.affinity": {
"vscodevim.vim": 1
}
}
This is the performance setting recommended in VSCodeVim’s own documentation. The more extensions you have installed, the more difference it makes.
Nine Vim plugins it emulates
VSCodeVim reproduces more than key bindings. As of 1.32.4 it emulates nine commonly used Vim plugins.
▼Emulated plugins
| Plugin | What it does |
|---|---|
| vim-airline | Colours the status bar by mode |
| vim-easymotion | Jump anywhere on screen in a few keystrokes |
| vim-surround | Add, change or delete surrounding quotes, brackets and tags |
| vim-commentary | Comment lines and blocks out |
| vim-indent-object | Select by indentation level |
| vim-sneak | Jump to a two-character target |
| CamelCaseMotion | Move by camelCase word boundaries |
| Input Method | Switch input method when changing mode |
| ReplaceWithRegister | Replace a target with the register contents |
Most are off by default, so enable only the ones you want in settings.json.
Input Method is the one to know about if you type a non-Latin language. It switches the OS input method back when you leave insert mode, which removes the constant cycle of pressing Esc and then fixing the input mode by hand.
Decide how far to configure before you start
Run it with the defaults for a week, then add only the settings you actually reached for.
Vim configuration expands without limit if you let it. A large part of what Vim plugins used to provide — jumping to definitions, multi-cursor editing, fuzzy file search — is already in VS Code, so a config ported wholesale from a vimrc often duplicates features that are already there.
If you also use Vim in the terminal, installing Homebrew and Vim on a Mac covers that side. Keeping the key bindings aligned across both avoids the mistakes that come from switching between them.
If VS Code is still in English and you would rather work in Japanese, switching VS Code to Japanese on macOS covers it. For the extensions worth having alongside this one, see 7 VS Code extensions worth installing.