Skip to content

Instantly share code, notes, and snippets.

@nikolovlazar
Last active October 26, 2025 09:24
Show Gist options
  • Save nikolovlazar/1174876ab2769c52ac9fc1534c557d70 to your computer and use it in GitHub Desktop.
Save nikolovlazar/1174876ab2769c52ac9fc1534c557d70 to your computer and use it in GitHub Desktop.
VSCode key bindings to navigate like Neovim
[
// Navigation
{
"key": "ctrl-h",
"command": "workbench.action.navigateLeft"
},
{
"key": "ctrl-l",
"command": "workbench.action.navigateRight"
},
{
"key": "ctrl-k",
"command": "workbench.action.navigateUp"
},
{
"key": "ctrl-j",
"command": "workbench.action.navigateDown"
},
{
"key": "space ,",
"command": "workbench.action.showAllEditors",
"when": "vim.mode == 'Normal' && (editorTextFocus || !inputFocus)"
},
{
"key": "space e",
"command": "runCommands",
"args": {
"commands": [
"workbench.action.toggleSidebarVisibility",
"workbench.files.action.focusFilesExplorer"
]
},
"when": "vim.mode == 'Normal' && (editorTextFocus || !inputFocus) && !sideBarFocus"
},
{
"key": "space e",
"command": "runCommands",
"args": {
"commands": [
"workbench.action.toggleSidebarVisibility",
"workbench.action.focusActiveEditorGroup"
]
},
"when": "sideBarFocus && !inputFocus"
},
{
"key": "space e",
"when": "vim.mode == 'Normal' && editorTextFocus && foldersViewVisible",
"command": "workbench.action.toggleSidebarVisibility"
},
{
"key": "s h",
"command": "workbench.action.splitEditor",
"when": "vim.mode == 'Normal' && (editorTextFocus || !inputFocus)"
},
{
"key": "s v",
"command": "workbench.action.splitEditorDown",
"when": "vim.mode == 'Normal' && (editorTextFocus || !inputFocus)"
},
// Coding
{
"key": "space c a",
"command": "editor.action.codeAction",
"when": "vim.mode == 'Normal' && editorTextFocus"
},
{
"key": "shift-k",
"command": "editor.action.moveLinesUpAction",
"when": "vim.mode == 'VisualLine' && editorTextFocus"
},
{
"key": "shift-j",
"command": "editor.action.moveLinesDownAction",
"when": "vim.mode == 'VisualLine' && editorTextFocus"
},
{
"key": "shift-k",
"command": "editor.action.showHover",
"when": "vim.mode == 'Normal' && editorTextFocus"
},
{
"key": "space c r",
"command": "editor.action.rename",
"when": "vim.mode == 'Normal' && editorTextFocus"
},
{
"key": "space c s",
"command": "workbench.action.gotoSymbol",
"when": "vim.mode == 'Normal' && editorTextFocus"
},
{
"key": "space b d",
"command": "workbench.action.closeActiveEditor",
"when": "(vim.mode == 'Normal' && editorTextFocus) || !inputFocus"
},
{
"key": "space b o",
"command": "workbench.action.closeOtherEditors",
"when": "(vim.mode == 'Normal' && editorTextFocus) || !inputFocus"
},
{
"key": "space space",
"command": "workbench.action.quickOpen",
"when": "vim.mode == 'Normal' && (editorTextFocus || !inputFocus)"
},
{
"key": "space g d",
"command": "editor.action.revealDefinition",
"when": "vim.mode == 'Normal' && editorTextFocus"
},
{
"key": "space g r",
"command": "editor.action.goToReferences",
"when": "vim.mode == 'Normal' && editorTextFocus"
},
{
"key": "space g i",
"command": "editor.action.goToImplementation",
"when": "vim.mode == 'Normal' && editorTextFocus"
},
{
"key": "space s g",
"command": "workbench.action.findInFiles",
"when": "vim.mode == 'Normal' && (editorTextFocus || !inputFocus)"
},
{
"key": "space g g",
"command": "runCommands",
"when": "vim.mode == 'Normal' && (editorTextFocus || !inputFocus)",
"args": {
"commands": ["workbench.view.scm", "workbench.scm.focus"]
}
},
{
"key": "ctrl-n",
"command": "editor.action.addSelectionToNextFindMatch",
"when": "(vim.mode == 'Normal' || vim.mode == 'Visual') && (editorTextFocus || !inputFocus)"
},
// File Explorer
{
"key": "r",
"command": "renameFile",
"when": "filesExplorerFocus && foldersViewVisible && !explorerResourceIsRoot && !explorerResourceReadonly && !inputFocus"
},
{
"key": "c",
"command": "filesExplorer.copy",
"when": "filesExplorerFocus && foldersViewVisible && !explorerResourceIsRoot && !explorerResourceReadonly && !inputFocus"
},
{
"key": "p",
"command": "filesExplorer.paste",
"when": "filesExplorerFocus && foldersViewVisible && !explorerResourceIsRoot && !explorerResourceReadonly && !inputFocus"
},
{
"key": "x",
"command": "filesExplorer.cut",
"when": "filesExplorerFocus && foldersViewVisible && !explorerResourceIsRoot && !explorerResourceReadonly && !inputFocus"
},
{
"key": "d",
"command": "deleteFile",
"when": "filesExplorerFocus && foldersViewVisible && !explorerResourceIsRoot && !explorerResourceReadonly && !inputFocus"
},
{
"key": "a",
"command": "explorer.newFile",
"when": "filesExplorerFocus && foldersViewVisible && !explorerResourceIsRoot && !explorerResourceReadonly && !inputFocus"
},
{
"key": "s",
"command": "explorer.openToSide",
"when": "filesExplorerFocus && foldersViewVisible && !explorerResourceIsRoot && !explorerResourceReadonly && !inputFocus"
},
{
"key": "shift-s",
"command": "runCommands",
"when": "filesExplorerFocus && foldersViewVisible && !explorerResourceIsRoot && !explorerResourceReadonly && !inputFocus",
"args": {
"commands": [
"workbench.action.splitEditorDown",
"explorer.openAndPassFocus",
"workbench.action.closeOtherEditors"
]
}
},
{
"key": "enter",
"command": "explorer.openAndPassFocus",
"when": "filesExplorerFocus && foldersViewVisible && !explorerResourceIsRoot && !explorerResourceIsFolder && !inputFocus"
},
{
"key": "enter",
"command": "list.toggleExpand",
"when": "filesExplorerFocus && foldersViewVisible && !explorerResourceIsRoot && explorerResourceIsFolder && !inputFocus"
},
// Debug
{
"key": "space d a",
"command": "workbench.action.debug.selectandstart",
"when": "vim.mode == 'Normal' && (editorTextFocus || !inputFocus) && debuggersAvailable"
},
{
"key": "space d t",
"command": "workbench.action.debug.stop",
"when": "vim.mode == 'Normal' && editorTextFocus && inDebugMode && !focusedSessionIsAttached"
},
{
"key": "space d o",
"command": "workbench.action.debug.stepOver",
"when": "vim.mode == 'Normal' && (editorTextFocus || !inputFocus) && inDebugMode && debugState == 'stopped'"
},
{
"key": "space d b",
"command": "editor.debug.action.toggleBreakpoint",
"when": "vim.mode == 'Normal' && editorTextFocus"
},
{
"key": "space d e",
"command": "editor.debug.action.showDebugHover",
"when": "vim.mode == 'Normal' && editorTextFocus && inDebugMode && debugState == 'stopped'"
},
{
"key": "space d c",
"command": "workbench.action.debug.continue",
"when": "vim.mode == 'Normal' && (editorTextFocus || !inputFocus) && inDebugMode && debugState == 'stopped'"
}
]
@nikolovlazar
Copy link
Author

Glad you found this useful @hvenry @ravicorreia 🙌

@cognitiveRobot
Copy link

@nikolovlazar thanks a lot. This is what I need - good from both worlds - VimVS.

@vsokolovskii
Copy link

If you have a problem with space+e try this:

 "key": "space e",
 "when": "vim.mode == 'Normal' && editorTextFocus && foldersViewVisible",
 "command": "workbench.action.toggleSidebarVisibility"
},
{
  "key": "space e",
  "when": "vim.mode == 'Normal'  && sideBarVisible",
  "command": "workbench.action.toggleSidebarVisibility"
}

@oni-shiro
Copy link

Anybody knows how to make the file explorer related bindings to work on solution explorer that comes with C# dev kit. I am trying to migrate from Visual studio to Code for that. I did not find any documentation around that as well.

@santi-ug
Copy link

santi-ug commented May 12, 2025

I saw that someone added keybinds for splitting the editor, which is exactly what I wanted, but I also noticed that the bindings s h and s v conflicted with Vim's native s (substitute) command, which I use quite a bit.

So I tested a few ergonomic alternatives and landed on the following setup, which feels much more natural:

{
  "key": "space h",
  "command": "workbench.action.splitEditor",
  "when": "vim.mode == 'Normal' && (editorTextFocus || !inputFocus)"
},
{
  "key": "space v",
  "command": "workbench.action.splitEditorDown",
  "when": "vim.mode == 'Normal' && (editorTextFocus || !inputFocus)"
},

I also changed the close current pane, since personally space b d and space b o didn't feel very comfortable and VSCode’s default ctrl+w wasn’t working inside Vim mode. (If you’re more used to Vim’s :q command to close, you could use space q instead, but I chose space w because it matches browser tab behavior and VSCode’s native pane-closing shortcut.). This one's personal preference but I'll still add it in case someone else also likes it.

{
  "key": "space w",
  "command": "workbench.action.closeActiveEditor",
  "when": "vim.mode == 'Normal' && (editorTextFocus || !inputFocus)"
},
{
  "key": "space shift+w",
  "command": "workbench.action.closeOtherEditors",
  "when": "(vim.mode == 'Normal' && editorTextFocus) || !inputFocus"
},

Lastly, I adjusted the Explorer bindings to avoid conflict with Vim motions and maintain consistent muscle memory:

{
  "key": "space e h",
  "command": "explorer.openToSide",
  "when": "filesExplorerFocus && foldersViewVisible && !explorerResourceIsRoot && !explorerResourceReadonly && !inputFocus"
},
{
  "key": "space e v",
  "command": "runCommands",
  "when": "filesExplorerFocus && foldersViewVisible && !explorerResourceIsRoot && !explorerResourceReadonly && !inputFocus",
  "args": {
    "commands": [
      "workbench.action.splitEditorDown",
      "explorer.openAndPassFocus",
      "workbench.action.closeOtherEditors"
    ]
  }
}

Just thought I'd comment this since I really liked these modifications to this already amazing config, thank you so much!

@slavpetroff
Copy link

This is amazing, thank you very much. The only issue i have is that, space is always triggered as leader and expects another key to be pressed, even in the terminal. As you can guess, it does not even allow me to write anything on the terminal with more than one word as it breaks. Does anyone have this issue and a way to solve it?

@nikolovlazar
Copy link
Author

@slavpetroff you can add another conditional in the when value to not target the terminal. I think the editorTextFocus should cover that + the surrounding UI elements because the editor is just the code panel. If that still doesn't work, there must be a terminal-specific when condition. Search for it and see if that works. Let me know when you figure it out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment