⭐️ Vim for Visual Studio Code
Latest commit 27711cf Oct 14, 2018
Failed to load latest commit information.
.github Update: force prettier project Aug 1, 2018
.vscode Code cleanup Sep 6, 2018
build fix prettier Aug 9, 2018
images Update Readme. Attempt to make it more succint and add point about `u… Oct 28, 2016
src Merge branch 'master' into relative-command-ranges Oct 11, 2018
test Merge branch 'master' into relative-command-ranges Oct 11, 2018
typings fix: move to npm for typings Feb 4, 2018
.github_changelog_generator bump version Oct 2, 2018
.gitignore feat: cache changelog to limit number of GH api calls Jul 15, 2018
.travis.yml fix: enable prettier for md Jul 29, 2018
.vscodeignore update prettier. use travis docker Jan 31, 2018
CHANGELOG.md bump version Oct 14, 2018
CODE_OF_CONDUCT.md fix: enable prettier for md Jul 29, 2018
LICENSE refactor taskqueue Oct 13, 2017
README.md feat: implement 'changeWordIncludesWhitespace' option Oct 10, 2018
ROADMAP.md Fix type in ROADMAP.md Aug 22, 2018
STYLE.md fix: enable prettier for md Jul 29, 2018
appveyor.yml Makes all tests pass on Windows (#1939) Aug 13, 2017
extension.ts Merge pull request #3103 from captaincaius/active-text-editor-eventha… Oct 9, 2018
gulpfile.js bump version Aug 27, 2018
package-lock.json bump version Oct 14, 2018
package.json bump version Oct 14, 2018
renovate.json Update renovate.json Mar 30, 2018
tsconfig.json feat: use winston/winston-console-for-electron for logging Jun 10, 2018
tslint.json fix: fix 'no-use-before-declare' requires type information lint warni… May 24, 2018



Vim emulation for Visual Studio Code

http://aka.ms/vscodevim https://travis-ci.org/VSCodeVim/Vim https://vscodevim-slackin.azurewebsites.net

VSCodeVim is a Vim emulator for Visual Studio Code.

  • 🚚 For a full list of supported Vim features, please refer to our roadmap.
  • 📃 Our change log outlines the breaking/major/minor updates between releases.
  • If you need to ask any questions, join us on Slack
  • Report missing features/bugs on GitHub.
Table of Contents (click to expand)

💾 Installation

VSCodeVim is automatically enabled following installation and reloading of VSCode.

Vim Compatibility

Vimscript is not supported, therefore we are not able to load your .vimrc or use .vim plugins. You have to replicate these using our Settings and Emulated plugins.

Mac Setup

To enable key-repeating execute the following in your Terminal and restart VS Code.

$ defaults write com.microsoft.VSCode ApplePressAndHoldEnabled -bool false         # For VS Code
$ defaults write com.microsoft.VSCodeInsiders ApplePressAndHoldEnabled -bool false # For VS Code Insider
$ defaults delete -g ApplePressAndHoldEnabled                                      # If necessary, reset global default

We also recommend increasing Key Repeat and Delay Until Repeat settings in System Preferences -> Keyboard.

Windows Setup

Like real vim, VSCodeVim will take over your control keys. This behaviour can be adjusted with the useCtrlKeys and handleKeys settings.

Linux Setup

If you have configured vim.useSystemClipboard: "true", we rely on clipboardy which is dependent on xsel:

apt install xsel

⚙️ Settings

The settings documented here are a subset of the supported settings; the full list is described in the Contributions tab in the extensions menu of VSCode.

Quick Example

Below is an example of a settings.json file with settings relevant to VSCodeVim:

  "vim.easymotion": true,
  "vim.sneak": true,
  "vim.incsearch": true,
  "vim.useSystemClipboard": true,
  "vim.useCtrlKeys": true,
  "vim.hlsearch": true,
  "vim.insertModeKeyBindings": [
      "before": ["j", "j"],
      "after": ["<Esc>"]
  "vim.normalModeKeyBindingsNonRecursive": [
      "before": ["<leader>", "d"],
      "after": ["d", "d"]
      "before": ["<C-n>"],
      "commands": [":nohl"]
  "vim.leader": "<space>",
  "vim.handleKeys": {
    "<C-a>": false,
    "<C-f>": false

VSCodeVim settings

These settings are specific to VSCodeVim.

Setting Description Type Default Value
vim.changeWordIncludesWhitespace Include trailing whitespace when changing word. This configures the cw action to act consistently as its siblings (yw and dw) instead of acting as ce. Boolean false
vim.cursorStylePerMode.{Mode} Configure a specific cursor style for {Mode}. Omitted modes will use default cursor type Supported cursors: line, block, underline, line-thin, block-outline, and underline-thin. String None
vim.debug.loggingLevel Maximum level of messages to log. Logs are visible in the developer tools. Supported values: 'error', 'warn', 'info', 'verbose', 'debug'). String error
vim.disableExtension Disable VSCodeVim extension. This setting can also be toggled using toggleVim command in the Command Palette Boolean false
vim.handleKeys Delegate configured keys to be handled by VSCode instead of by the VSCodeVim extension. Any key in keybindings section of the package.json that has a vim.use<C-...> in the when argument can be delegated back to VSCode by setting "<C-...>": false. Example: to use ctrl+f for find (native VSCode behaviour): "vim.handleKeys": { "<C-f>": false }. String "<C-d>": true
vim.overrideCopy Override VSCode's copy command with our own, which works correctly with VSCodeVim. If cmd-c/ctrl-c is giving you issues, set this to false and complain here. Boolean false
vim.searchHighlightColor Set the color of search highlights String rgba(150, 150, 255, 0.3)
vim.startInInsertMode Start in Insert mode instead of Normal Mode Boolean false
vim.substituteGlobalFlag Similar to Vim's gdefault setting. /g flag in a substitute command replaces all occurrences in the line. Without this flag, replacement occurs only for the first occurrence in each line. With this setting enabled, the g is on by default. Boolean false
vim.useCtrlKeys Enable Vim ctrl keys overriding common VSCode operations such as copy, paste, find, etc. Boolean true
vim.visualstar In visual mode, start a search with * or # using the current selection Boolean false

Neovim Integration

⚠️ Experimental feature. Please leave feedback on neovim integration here.

To leverage neovim for Ex-commands,

  1. Install neovim
  2. Modify the following configurations:
Setting Description Type Default Value
vim.enableNeovim Enable Neovim Boolean false
vim.neovimPath Full path to neovim executable String

Here's some ideas on what you can do with neovim integration:

Key Remapping

Custom remappings are defined on a per-mode basis.


  • Keybinding overrides to use for insert, normal, and visual modes.
  • Bind jj to <Esc> in insert mode:
    "vim.insertModeKeyBindings": [
            "before": ["j", "j"],
            "after": ["<Esc>"]
  • Bind : to show the command palette:
    "vim.normalModeKeyBindingsNonRecursive": [
            "before": [":"],
            "commands": [
  • Bind <leader>m to add a bookmark and <leader>b to open the list of all bookmarks (using the Bookmarks extension):
    "vim.normalModeKeyBindingsNonRecursive": [
            "before": ["<leader>", "m"],
            "commands": [
            "before": ["<leader>", "b"],
            "commands": [
  • Bind ZZ to the vim command :wq (save and close the current file):
    "vim.normalModeKeyBindingsNonRecursive": [
            "before": ["Z", "Z"],
            "commands": [
  • Bind ctrl+n to turn off search highlighting and <leader>w to save the current file:
    "vim.normalModeKeyBindingsNonRecursive": [
            "commands": [
            "before": ["leader", "w"],
            "commands": [
  • Bind p in visual mode to paste without overriding the current register
    "vim.visualModeKeyBindingsNonRecursive": [
            "before": [
            "after": [
  • Bind > and < in visual mode to indent/outdent lines (repeatable)
    "vim.visualModeKeyBindingsNonRecursive": [
            "before": [
            "commands": [
            "before": [
            "commands": [
  • Bind <leader>vim to clone this repository to the selected location.
    "vim.visualModeKeyBindingsNonRecursive": [
            "before": [
                "<leader>", "v", "i", "m"
            "commands": [
                    "command": "git.clone",
                    "args": [ "https://github.com/VSCodeVim/Vim.git" ]


  • Non-recursive keybinding overrides to use for insert, normal, and visual modes
  • Example: Bind j to gj. Notice that if you attempted this binding normally, the j in gj would be expanded into gj, on and on forever. Stop this recursive expansion using insertModeKeyBindingsNonRecursive and/or normalModeKeyBindingNonRecursive.
    "vim.normalModeKeyBindingsNonRecursive": [
            "before": ["j"],
            "after": ["g", "j"]

Debugging Remappings

  1. Are your configurations correct?

    Adjust the extension's logging level to 'debug', restart VSCode. In the Developer Tools console, do you see any errors?

    debug: Remapper: normalModeKeyBindingsNonRecursive. before=0. after=^.
    debug: Remapper: insertModeKeyBindings. before=j,j. after=<Esc>.
    error: Remapper: insertModeKeyBindings. Invalid configuration. Missing 'after' key or 'command'. before=j,k.

    As each remapped configuration is loaded, it is outputted to console. Misconfigured configurations are ignored.

  2. Does the extension handle the keys you are trying to remap?

    VSCodeVim explicitly instructs VSCode which key events we care about through the package.json. If the key you are trying to remap is a key in which vim/vscodevim generally does not handle, then it's most likely that this extension does not receive those key events from VS Code. With logging level adjusted to 'debug', as you press keys, you should see output similar to:

    debug: ModeHandler: handling key=A.
    debug: ModeHandler: handling key=l.
    debug: ModeHandler: handling key=<BS>.
    debug: ModeHandler: handling key=<C-a>.

    As you press the key that you are trying to remap, do you see it outputted here? If not, it means we don't subscribe to those key events.

Vim settings

Configuration settings that have been copied from vim. Vim settings are loaded in the following sequence:

  1. :set {setting}
  2. vim.{setting} from user/workspace settings.
  3. VSCode settings
  4. VSCodeVim default values
Setting Description Type Default Value
vim.autoindent Copy indent from current line when starting a new line Boolean true
vim.hlsearch Highlights all text matching current search Boolean false
vim.ignorecase Ignore case in search patterns Boolean true
vim.incsearch Show the next match while entering a search Boolean true
vim.leader Defines key for <leader> to be used in key remappings String \
vim.showcmd Show (partial) command in status bar Boolean true
vim.showmodename Show name of current mode in status bar Boolean true
vim.smartcase Override the 'ignorecase' setting if search pattern contains uppercase characters Boolean true
vim.textwidth Width to word-wrap when using gq Number 80
vim.timeout Timeout in milliseconds for remapped commands Number 1000
vim.whichwrap Controls wrapping at beginning and end of line. Comma-separated set of keys that should wrap to next/previous line. Arrow keys are represented by [ and ] in insert mode, < and > in normal and visual mode. To wrap "everything", set this to h,l,<,>,[,]. String ``

🖱️ Multi-Cursor Mode

⚠️ Multi-Cursor mode is experimental. Please report issues in our feedback thread.

Enter multi-cursor mode by:

  • On OSX, cmd-d. On Windows, ctrl-d.
  • gb, a new shortcut we added which is equivalent to cmd-d (OSX) or ctrl-d (Windows). It adds another cursor at the next word that matches the word the cursor is currently on.
  • Running "Add Cursor Above/Below" or the shortcut on any platform.

Once you have multiple cursors, you should be able to use Vim commands as you see fit. Most should work; some are unsupported (ref PR#587).

  • Each cursor has its own clipboard.
  • Pressing Escape in Multi-Cursor Visual Mode will bring you to Multi-Cursor Normal mode. Pressing it again will return you to Normal mode.

🔌 Emulated Plugins


⚠️ Experimental feature. Due to VSCode API limitations, this function modifies settings.json in the workspace resulting in latency and a constant changing diff in your working directory (see issue#2124).

Change the color of the status bar based on the current mode. Once enabled, configure "vim.statusBarColors". Colors can be defined for each mode either as string (background only), or string[] (background, foreground).

    "vim.statusBarColorControl": true,
    "vim.statusBarColors.normal": ["#8FBCBB", "#434C5E"],
    "vim.statusBarColors.insert": "#BF616A",
    "vim.statusBarColors.visual": "#B48EAD",
    "vim.statusBarColors.visualline": "#B48EAD",
    "vim.statusBarColors.visualblock": "#A3BE8C",
    "vim.statusBarColors.replace": "#D08770"


Based on vim-easymotion. To activate easymotion, you need to make sure that easymotion is set to true in settings.json (default is false).

Once easymotion is active, initiate motions using the following commands. After you initiate the motion, text decorators/markers will be displayed and you can press the keys displayed to jump to that position. leader is configurable and is \ by default.

Motion Command Description
<leader><leader> s <char> Search character
<leader><leader> f <char> Find character forwards
<leader><leader> F <char> Find character backwards
<leader><leader> t <char> Til character forwards
<leader><leader> T <char> Til character backwards
<leader><leader> w Start of word forwards
<leader><leader> b Start of word backwards
<leader><leader> l matches beginning & ending of word, camelCase, after _ and after # forwards
<leader><leader> h matches beginning & ending of word, camelCase, after _ and after # backwards
<leader><leader> e End of word forwards
<leader><leader> ge End of word backwards
<leader><leader> j Start of line forwards
<leader><leader> k Start of line backwards
<leader><leader> / <char>... <CR> Search n-character
<leader><leader><leader> bdt Til character
<leader><leader><leader> bdw Start of word
<leader><leader><leader> bde End of word
<leader><leader><leader> bdjk Start of line
<leader><leader><leader> j JumpToAnywhere motion; default behavior matches beginning & ending of word, camelCase, after _ and after #

<leader><leader> (2s|2f|2F|2t|2T) <char><char> and <leader><leader><leader> bd2t <char>char> are also available. The difference is character count required for search. For example, <leader><leader> 2s <char><char> requires two characters, and search by two characters. This mapping is not a standard mapping, so it is recommended to use your custom mapping.

You can customize the appearance of easymotion markers (the boxes with letters) using the following settings:

Setting Description
vim.easymotionMarkerBackgroundColor The background color of the marker box.
vim.easymotionMarkerForegroundColorOneChar The font color for one-character markers.
vim.easymotionMarkerForegroundColorTwoChar The font color for two-character markers, used to differentiate from one-character markers.
vim.easymotionMarkerWidthPerChar The width in pixels allotted to each character.
vim.easymotionMarkerHeight The height of the marker.
vim.easymotionMarkerFontFamily The font family used for the marker text.
vim.easymotionMarkerFontSize The font size used for the marker text.
vim.easymotionMarkerFontWeight The font weight used for the marker text.
vim.easymotionMarkerYOffset The distance between the top of the marker and the text (will typically need some adjusting if height or font size have been changed).
vim.easymotionKeys The characters used for jump marker name
vim.easymotionJumpToAnywhereRegex Custom regex to match for JumpToAnywhere motion (analogous to Easymotion_re_anywhere). Example setting (which also matches start & end of line, as well as Javascript comments in addition to the regular behavior (note the double escaping required): ^\s*.


Based on surround.vim, the plugin is used to work with surrounding characters like parenthesis, brackets, quotes, and XML tags.

t or < as <desired char> or <existing char> will do tags and enter tag entry mode. Using <CR> instead of > to finish changing a tag will preserve any existing attributes.

Surround is enabled by default, but can be disabled by setting "vim.surround": false.

Surround Command Description
d s <existing char> Delete existing surround
c s <existing char> <desired char> Change surround existing to desired
y s <motion> <desired char> Surround something with something using motion (as in "you surround")
S <desired char> Surround when in visual modes (surrounds full selection)

Some examples:

  • "test" with cursor inside quotes type cs"' to end up with 'test'
  • "test" with cursor inside quotes type ds" to end up with test
  • "test" with cursor inside quotes type cs"t and enter 123> to end up with <123>test</123>
  • test with cursor on word test type ysaw) to end up with (test)


Similar to vim-commentary, but uses the VSCode native "Toggle Line Comment" and "Toggle Block Comment" features.

Usage examples:

  • gc - toggles line comment. For example gcc to toggle line comment for current line and gc2j to toggle line comments for the current line and the next two lines.
  • gC - toggles block comment. For example gCi) to comment out everything within parenthesis.


Based on vim-indent-object, it allows for treating blocks of code at the current indentation level as text objects. Useful in languages that don't use braces around statements (e.g. Python).

Provided there is a new line between the opening and closing braces / tag, it can be considered an agnostic cib/ci{/ci[/cit.

Command Description
<operator>ii This indentation level
<operator>ai This indentation level and the line above (think if statements in Python)
<operator>aI This indentation level, the line above, and the line after (think if statements in C/C++/Java/etc)


Based on vim-sneak. To activate sneak, you need to make sure that sneak is set to true in settings.json (default is false).

"vim.sneakUseIgnorecaseAndSmartcase": true can be set if desired to allow for respecting vim.ignorecase and vim.smartcase while sneaking (default is false)

Once sneak is active, initiate motions using the following commands. For operators sneak uses z instead of s because s is already taken by the surround plugin.

Motion Command Description
s<char><char> Move forward to the first occurence of <char><char>
S<char><char> Move backward to the first occurence of <char><char>
<operator>z<char><char> Perform <operator> forward to the first occurence of <char><char>
<operator>Z<char><char> Perform <operator> backward to the first occurence of <char><char>

Input Method

Disable input method when exiting Insert Mode.

Setting Description
vim.autoSwitchInputMethod.enable Boolean denoting whether autoSwitchInputMethod is on/off.
vim.autoSwitchInputMethod.defaultIM Default input method.
vim.autoSwitchInputMethod.obtainIMCmd The full path to command to retrieve the current input method key.
vim.autoSwitchInputMethod.switchIMCmd The full path to command to switch input method, with {im} a placeholder for input method key.

You can use any third-party program to switch input methods. We recommend im-select, and the following will walkthrough installation and configuration for im-select.

  1. Install im-select

    Follow the installation guide to install im-select

  2. Find your default input method key

    • MacOS:

      Switch your input method to English, and run the following in your terminal:

      $ /usr/local/bin/im-select

      the program will output your default input method (eg. com.apple.keyload.US). The table below is a list of common English key layouts for MacOS.

      Key Description
      com.apple.keylayout.US U.S.
      com.apple.keylayout.ABC ABC
      com.apple.keylayout.British British
      com.apple.keylayout.Irish Irish
      com.apple.keylayout.Australian Australian
      com.apple.keylayout.Dvorak Dvorak
      com.apple.keylayout.Colemak Colemak
    • Windows:

      For most people, their default input method key is 1033, the locale ID of en_US. But if your default keyboard layout is not en_US, you can use im-select.exe to find out, the guide is here. You can also find your locale ID in this page, the LCID Decimal column is the locale ID.

  3. Configure vim.autoSwitchInputMethod.

    • MacOS:

      Given default input method key of com.apple.keylayout.US and im-select saved to the default location. The configuration is:

      "vim.autoSwitchInputMethod.enable": true,
      "vim.autoSwitchInputMethod.defaultIM": "com.apple.keylayout.US",
      "vim.autoSwitchInputMethod.obtainIMCmd": "/usr/local/bin/im-select",
      "vim.autoSwitchInputMethod.switchIMCmd": "/usr/local/bin/im-select {im}"
    • Windows:

      Given default input method key of 1033(en_US) and your im-select.exe is located at D:/bin. The configuration is:

      "vim.autoSwitchInputMethod.enable": true,
      "vim.autoSwitchInputMethod.defaultIM": "1033",
      "vim.autoSwitchInputMethod.obtainIMCmd": "D:\\bin\\im-select.exe",
      "vim.autoSwitchInputMethod.switchIMCmd": "D:\\bin\\im-select.exe {im}"

If using an alternative program to switch input methods and it requires a command-line options to switch or get the input method, you should add the options to the configuration. For example, if your program's usage is my-program -s imKey to switch input method, your vim.autoSwitchInputMethod.switchIMCmd should be /path/to/my-program -s {im}.

🎩 VSCodeVim tricks!

Vim has a lot of nifty tricks and we try to preserve some of them:

  • gd - jump to definition.
  • gq - on a visual selection reflow and wordwrap blocks of text, preserving commenting style. Great for formatting documentation comments.
  • gb - adds another cursor on the next word it finds which is the same as the word under the cursor.
  • af - visual mode command which selects increasingly large blocks of text. For example, if you had "blah (foo [bar 'ba|z'])" then it would select 'baz' first. If you pressed af again, it'd then select [bar 'baz'], and if you did it a third time it would select "(foo [bar 'baz'])".
  • gh - equivalent to hovering your mouse over wherever the cursor is. Handy for seeing types and error messages without reaching for the mouse!

📚 F.A.Q.

None of the native Visual Studio Code ctrl (e.g. ctrl+f, ctrl+v) commands work

Set the useCtrlKeys setting to false.

Moving j/k over folds opens up the folds

Try setting vim.foldfix to true. This is a hack; it works fine, but there are side effects (see issue#22276).

Key repeat doesn't work

Are you on a Mac? Did you go through our mac-setup instructions?

There are annoying intellisense/notifications/popups that I can't close with <esc>! Or I'm in a snippet and I want to close intellisense

Press shift+<esc> to close all of those boxes.

How can I use the commandline when in Zen mode or when the status bar is disabled?

This extension exposes a remappable command to show a vscode style quick-pick, limited functionality, version of the commandline. This can be remapped as follows in visual studio keybindings.json settings file.

  "key": "shift+;",
  "command": "vim.showQuickpickCmdLine",
  "when": "editorTextFocus && vim.mode != 'Insert'"

Or for Zen mode only:

  "key": "shift+;",
  "command": "vim.showQuickpickCmdLine",
  "when": "inZenMode && vim.mode != 'Insert'"

❤️ Contributing

This project is maintained by a group of awesome people and contributions are extremely welcome ❤️. For a quick tutorial on how you can help, see our contributing guide.

Special shoutouts to cool contributors

  • Thanks to @xconverge for making over 100 commits to the repo. If you're wondering why your least favorite bug packed up and left, it was probably him.
  • Thanks to @Metamist for implementing EasyMotion!
  • Thanks to @sectioneight for implementing text objects!
  • Special props to Kevin Coleman, who created our awesome logo!
  • Shoutout to @chillee aka Horace He for his contributions and hard work.