ターミナル派エンジニアのための VSCode(Cursor)Vim カスタマイズ完全ガイド
はじめに
みなさん、普段どんなエディタで開発していますか?
「やっぱりターミナル上で nvim と tmux でしょ!」という方も多いはず。
私もその一人で、CLI 上での開発体験にこだわり続けてきました。
しかし、AI エディタの進化が目覚ましい昨今、
「Cursor」や「Windsurf」など、AI を組み込んだ IDE の波に乗り遅れるわけにはいきません!(そんな気がします)
本記事では、Vim 派エンジニアが VSCode(Cursor)を Vim ライクにカスタマイズする方法を、実際の設定例とともに徹底解説します。
AI × エディタの進化と私の開発スタイル
まず初めに、簡単に私の開発環境の変化を共有させてください。(興味の無い方は飛ばしてください)
私の AI 活用開発ライフは、ざっくり以下のようなフェーズを経てきました。
- ChatGPT などのチャット型 LLM で質問・コード生成
- nvim に Copilot を導入し、エディタ内でコード補完・修正
- ターミナル AI エージェント(aider など)の活用
- Cursor の導入
それぞれの課題
-
1. チャット型 LLM
- llmが生成した回答を毎回エディタにコピペするのが面倒
- 基本的には自分でコードを書いている状態(それが楽しかったりもする)
-
2. Copilot in nvim
- コードの予測精度に満足できない
- 長い予測を適応すると nvim が落ちることも…
- チャットやコード修正の UX がイマイチ
-
3. ターミナル AI エージェント
- 結構優秀
- コードもガッツリ書いてくれる
- nvimに組み込まれたらもっと最高
- 結局 LSP や 他のチャット型LLM 頼みになりがちな時も
そして遂に Cursor 導入😇
私にも転機が訪れました。
ある日、会社の先輩との何気ない会話。
先輩:「作業の調子どう?」
自分:「まあいい感じですね。今テスト書いてます。」
先輩:「テストはAIに書かせたらいいんじゃない?」
自分:「そうですよねぇ(llmが吐いたコードをコピペしてるんだよな〜)」
この時は仕事で Copilot と ChatGPT を主に使っていましたが、
「AIに書かせてるのに、結局コピペは自分でやってる…」というジレンマを強く感じていました。
よし、Cursor使うか…😇
ただし、Vim のキーバインドにカスタマイズしなければ自分の開発スタイルは守れない!
こうして、僕の Cursor カスタマイズの旅が始まりました。
Cursor カスタマイズのゴール
- 普段使っている nvim(特にnvimディストリビューションのLazyVim )のキーバインドにできるだけ近づける
- Vim の操作感を VSCode(Cursor)でも再現し、AI の恩恵も最大限受ける
カスタマイズ手順
1. Vim プラグインのインストール
まずは公式の Vim プラグインをインストールしましょう。
これだけだと「純 Vim」な基本機能しか使えません。
ここからがカスタマイズの本番です!
2. キーバインドのカスタマイズ
修正するファイルは以下二つです。(VSCode内でファイルの検索をすると見つかるはずです。)
どちらもユーザー設定用のファイルを開きましょう。
- keybindings.json
- settings.json
これらのVSCode設定ファイルで Vim 関連のカスタマイズを行います。ここでは、私が特に気に入っている各カスタマイズキーを個別に説明します。
(※設定ファイル全体は本ページの最下部に記載しています)
タブ移動(L/H)
-
L
(shift + l
) で右のタブに移動、H
(shift + h
)で左のタブに移動できます。 - 複数ファイルを開いているときに素早くタブを切り替えたいときに便利です。
[
{
"before": ["L"],
"commands": ["workbench.action.nextEditor"]
},
{
"before": ["H"],
"commands": ["workbench.action.previousEditor"]
},
]
分割されたeditor移動(ctrl + l
/ ctrl + h
)
-
ctrl + l
で右のeditorに移動、ctrl + h
で左のeditorに移動できます。 - 複数editorを分割しているときに素早くeditorを切り替えたいときに便利です。
[
{
"key": "ctrl+h",
"command": "workbench.action.focusLeftGroup",
"when": "editorTextFocus"
},
{
"key": "ctrl+l",
"command": "workbench.action.focusRightGroup",
"when": "editorTextFocus"
},
{
"key": "ctrl+j",
"command": "workbench.action.focusBelowGroup",
"when": "editorTextFocus"
},
{
"key": "ctrl+k",
"command": "workbench.action.focusAboveGroup",
"when": "editorTextFocus"
},
]
ファイルエクスプローラーの開閉(<leader> + e
)
-
<leader> + e
(例: Space + e)でエクスプローラーを開閉できます。 - ファイルの切り替えや新規作成時にすぐアクセスできます。
[
{
"before": ["<leader>", "e"],
"commands": ["workbench.view.explorer"]
},
]
[
{
"key": "space e",
"command": "workbench.action.toggleSidebarVisibility",
"when": "filesExplorerFocus && !inputFocus"
},
]
<leader>
keyは自由に設定できます。
私はspaceに設定しているので、<leader>
はspace
を意味します。
"vim.leader": "<space>",
ファイルエクスプローラー上での操作
-
a
:新規ファイルの追加 -
m
:ファイル名の修正 -
d
:ファイルの削除 -
y
:コピー -
p
:ペースト -
enter
:ファイルを開く
ファイル管理をキーボードだけで完結できます。
もちろんファイルの移動はvimキーで可能です。
[
{
"key": "a",
"command": "explorer.newFile",
"when": "explorerViewletVisible && filesExplorerFocus && !explorerResourceIsRoot && !explorerResourceReadonly && !inputFocus"
},
{
"key": "d",
"command": "deleteFile",
"when": "explorerViewletVisible && filesExplorerFocus && !explorerResourceIsRoot && !explorerResourceReadonly && !inputFocus"
},
{
"key": "m",
"command": "renameFile",
"when": "explorerViewletVisible && filesExplorerFocus && !explorerResourceIsRoot && !explorerResourceReadonly && !inputFocus"
},
{
"key": "y",
"command": "filesExplorer.copy",
"when": "explorerViewletVisible && filesExplorerFocus && !explorerResourceIsRoot && !inputFocus"
},
{
"key": "p",
"command": "filesExplorer.paste",
"when": "explorerViewletVisible && filesExplorerFocus && !explorerResourceReadonly && !inputFocus"
},
{
"key": "enter",
"command": "-renameFile",
"when": "explorerViewletVisible && filesExplorerFocus"
},
{
"key": "enter",
"command": "list.select",
"when": "listFocus && !inputFocus"
},
]
関数や変数の詳細表示(K)
-
Shift + k
で関数や変数の詳細(Hover)を表示します。 - コードの意味や型情報をすぐに確認したいときに便利です。
[
{
"before": ["K"],
"commands": ["editor.action.showHover"]
},
]
リネーム( + c + r)
-
<leader> + c + r
でクラスや変数のリネームができます(VSCodeでいうF2)。 - 変数名や関数名を一括で変更したいときに便利です。
[
{
"before": ["<leader>", "c", "r"],
"commands": ["editor.action.rename"]
},
]
グローバル検索(<leader> + s + g
)
-
<leader> + s + g
でプロジェクト全体を検索できます。 - 大規模なリポジトリでも素早く目的のコードを探せます。
[
{
"before": ["<leader>", "s", "g"],
"commands": ["workbench.action.findInFiles"]
},
]
エディタの分割(<leader> + -
/ <leader> + |
)
-
<leader> + -
でエディタを水平分割、<leader> + |
で垂直分割します。 - 複数ファイルを同時に編集したいときに便利です。
[
{
"before": ["<leader>", "-"],
"commands": ["workbench.action.splitEditorDown"]
},
{
"before": ["<leader>", "|"],
"commands": ["workbench.action.splitEditorDown"]
},
]
タブのクローズ(<leader> + b + d
/ <leader> + b + o
)
-
<leader> + b + d
で現在のタブを閉じる、<leader> + b + o
で他のタブを全て閉じます。 - タブ整理や集中したいときに役立ちます。
[
{
"before": ["<leader>", "b", "d"],
"commands": ["workbench.action.closeActiveEditor"]
},
{
"before": ["<leader>", "b", "o"],
"commands": ["workbench.action.closeOtherEditors"]
},
]
インサートモードからのEscape(jj
)
- インサートモード中に
j + j
でノーマルモードに戻れます。 - Esc キーに手を伸ばさずに済むので、入力の流れを止めません。
{
"vim.insertModeKeyBindings": [
{
"before": ["j", "j"],
"after": ["<Esc>"]
}
],
}
ヤンク(コピー)時のハイライト
- ヤンク(コピー)した時にハイライト表示されるので、コピー範囲が一目で分かります。
{
"vim.highlightedyank.enable": true,
}
やりたいけど諦めていること
- globalで文字列の検索機能(ripgrepみたいなUI)
- cmdline(
:
押してコマンド入力待ちの状態)を画面中央に表示させる
VSCodeだと画面下で表示がちっちゃすぎる、、、 - 他にも色々あったけど忘れた
まとめ
自分が気に入っているvim設定を共有させていただきました。
フルの設定はこのページに貼り付けるので、参考にしてみてください。
またおすすめのvimカスタマイズがあれば是非ご教示ください🙏
では、快適なvimライフを!!
最後に
今はClaude Codeがすごく気になっています。なんせターミナル上で動くのがいいですよね??
agent機能は優秀でいいが、まだnvim上でいい感じにコード補完ができるようになるには時間がかかるのでしょうか...
terminal上での開発生活にいつ戻れるのかしら。
と思っていたら会社でClaude Code Maxプランが使えるようになりました。嬉しい:)
※私が所属する会社ではAIを活用した開発を絶賛推進中です。興味ある方はこちらをどうぞ〜。
自分でvimキーの設定するのが面倒くさい貴方へ。
下記コピペで快適なvimライフが送れます。(そのはず)
config最新バージョン
{
"window.commandCenter": true,
"editor.fontSize": 16,
"editor.wordWrap": "on",
"editor.lineNumbers": "relative",
"editor.cursorSurroundingLines": 8,
"vim.easymotion": true,
"vim.incsearch": true,
"vim.ignorecase": true,
"vim.useSystemClipboard": true,
"vim.useCtrlKeys": true,
"vim.hlsearch": true,
"vim.highlightedyank.enable": true,
"vim.insertModeKeyBindings": [
{
"before": ["j", "j"],
"after": ["<Esc>"]
}
],
"vim.normalModeKeyBindingsNonRecursive": [
{
"before": ["K"],
"commands": ["editor.action.showHover"]
},
{
"before": ["L"],
"commands": ["workbench.action.nextEditor"]
},
{
"before": ["H"],
"commands": ["workbench.action.previousEditor"]
},
{
"before": ["<leader>", "e"],
"commands": ["workbench.view.explorer"]
},
{
"before": ["<leader>", "s", "f"],
"commands": ["workbench.action.quickOpen"]
},
{
"before": ["<leader>", "<leader>"],
"commands": ["workbench.action.quickOpen"]
},
{
"before": ["<leader>", "tab", "tab"],
"commands": ["workbench.action.files.newUntitledFile"]
},
{
"before": ["<leader>", "tab", "f"],
"commands": ["workbench.action.openEditorAtIndex1"]
},
{
"before": ["<leader>", "tab", "l"],
"commands": ["workbench.action.lastEditorInGroup"]
},
{
"before": ["<leader>", "s", "g"],
"commands": ["workbench.action.findInFiles"]
},
{
"before": ["<leader>", "c", "r"],
"commands": ["editor.action.rename"]
},
{
"before": ["<leader>", "s", "r"],
"commands": ["workbench.action.replaceInFiles"]
},
{
"before": ["<leader>", "-"],
"commands": ["workbench.action.splitEditorDown"]
},
{
"before": ["<leader>", "|"],
"commands": ["workbench.action.splitEditorRight"]
},
{
"before": ["<leader>", "g"],
"commands": ["workbench.view.scm"]
},
{
"before": ["<leader>", "n", "o"],
"commands": [":nohl"]
},
{
"before": ["<Leader>", ":"],
"commands": [{ "command": "workbench.action.showCommands" }]
},
{
"before": ["<leader>", "b", "d"],
"commands": ["workbench.action.closeActiveEditor"]
},
{
"before": ["<leader>", "b", "o"],
"commands": ["workbench.action.closeOtherEditors"]
},
],
"vim.visualModeKeyBindingsNonRecursive": [
{
"before": ["p"],
"after": ["P"]
}
],
"vim.leader": "<space>",
"vim.handleKeys": {
"<C-a>": false,
"<C-f>": false,
"<C-h>": false,
"<C-j>": false,
"<C-k>": false,
"<C-l>": false,
},
"extensions.experimental.affinity": {
"vscodevim.vim": 1
}
}
[
{
"key": "cmd+i",
"command": "composerMode.agent"
},
{
"key": "ctrl+h",
"command": "workbench.action.focusLeftGroup",
"when": "editorTextFocus"
},
{
"key": "ctrl+l",
"command": "workbench.action.focusRightGroup",
"when": "editorTextFocus"
},
{
"key": "ctrl+l",
"command": "workbench.action.focusActiveEditorGroup",
"when": "!editorTextFocus"
},
{
"key": "ctrl+j",
"command": "workbench.action.focusBelowGroup",
"when": "editorTextFocus"
},
{
"key": "ctrl+k",
"command": "workbench.action.focusAboveGroup",
"when": "editorTextFocus"
},
{
"key": "space e",
"command": "workbench.action.toggleSidebarVisibility",
"when": "filesExplorerFocus && !inputFocus"
},
{
"key": "a",
"command": "explorer.newFile",
"when": "explorerViewletVisible && filesExplorerFocus && !explorerResourceIsRoot && !explorerResourceReadonly && !inputFocus"
},
{
"key": "d",
"command": "deleteFile",
"when": "explorerViewletVisible && filesExplorerFocus && !explorerResourceIsRoot && !explorerResourceReadonly && !inputFocus"
},
{
"key": "m",
"command": "renameFile",
"when": "explorerViewletVisible && filesExplorerFocus && !explorerResourceIsRoot && !explorerResourceReadonly && !inputFocus"
},
{
"key": "y",
"command": "filesExplorer.copy",
"when": "explorerViewletVisible && filesExplorerFocus && !explorerResourceIsRoot && !inputFocus"
},
{
"key": "p",
"command": "filesExplorer.paste",
"when": "explorerViewletVisible && filesExplorerFocus && !explorerResourceReadonly && !inputFocus"
},
{
"key": "enter",
"command": "-renameFile",
"when": "explorerViewletVisible && filesExplorerFocus"
},
{
"key": "enter",
"command": "list.select",
"when": "listFocus && !inputFocus"
},
{
"key": "ctrl+space",
"command": "editor.action.smartSelect.expand",
"when": "editorTextFocus"
},
{
"key": "ctrl+shift+space",
"command": "editor.action.smartSelect.shrink",
"when": "editorTextFocus"
},
{
"key": "ctrl+j",
"command": "workbench.action.quickOpenSelectNext",
"when": "inQuickOpen"
},
{
"key": "ctrl+k",
"command": "workbench.action.quickOpenSelectPrevious",
"when": "inQuickOpen"
},
{
"key": "h",
"command": "editor.action.scrollLeftHover",
"when": "editorHoverFocused"
},
{
"key": "j",
"command": "editor.action.scrollDownHover",
"when": "editorHoverFocused"
},
{
"key": "k",
"command": "editor.action.scrollUpHover",
"when": "editorHoverFocused"
},
{
"key": "l",
"command": "editor.action.scrollRightHover",
"when": "editorHoverFocused"
},
{
"key": "space space",
"command": "workbench.action.quickOpen",
"when": "!editorIsOpen && !inputFocus"
},
{
"key": "space s g",
"command": "workbench.action.findInFiles",
"when": "!inputFocus"
},
]