VimでGitHub Copilotを使う(copilot.vim)補完が出ないときの対処
GitHub CopilotはVS Code専用の機能だと思われがちですが、GitHub自身がgithub/copilot.vimというVim/Neovim用のプラグインを配布していて、公式にサポートされています。導入はプラグインを1つ置いて:Copilot setupを叩くだけなので5分もかかりません。それでも「手順どおり入れたのに灰色の候補が出てこない」で止まる人が多いのは、Copilotがバッファの種類やサインイン状態によって黙って無効になる仕組みだからです。この記事では導入手順に加えて、:Copilot statusが返すメッセージから原因を特定する方法までを扱います。
目次(7項目)
| コマンド・キー | これだけ覚える |
|---|---|
:Copilot setup | GitHubアカウントで認証して有効にする |
:Copilot status | 今のバッファでCopilotが動いているか確認する |
| Tab | 表示されている候補を確定する |
| Ctrl-] | 今の候補を消す |
:Copilot panel | 候補を最大10件まとめて表示する |
検証環境:macOS + Vim 9.1.1752、copilot.vim 1.59.0(2026年1月版)で確認しました。コマンドの出力やメッセージはすべてこの環境の実物です。ただしGitHubアカウントへのサインインは行っていないため、候補が実際に表示されてからTabで確定するまでの操作感については、プラグイン内のマッピング定義と公式ヘルプ(:help copilot)を根拠に書いています。
動かすために必要なもの
前提は3つあります。エディタ側のバージョン、Node.js、そしてCopilotのサブスクリプションです。
| 必要なもの | 条件 | 確認方法 |
|---|---|---|
| Vim | 9.0.0185以降 | vim --versionの1行目とパッチ番号 |
| Neovim | 最新版 | nvim --version |
| Node.js | PATHにnodeがあること | node --version |
| アカウント | Copilotのサブスクリプション | GitHubの設定画面 |
Vimの条件が「9.0.0185以降」と妙に細かいのは、この付近のパッチで入った機能をプラグインが使っているためです。Vim 8系では動きません。vim --versionの出力はVIM - Vi IMproved 9.1のようなバージョン表記に続けてIncluded patches: 1-1752とパッチ番号が並ぶので、9.0のままの人はここまで見て判断してください。
サブスクリプションについては、個人向けの無料枠(GitHub Copilot Free)が用意されていて、月あたりの補完回数に上限はあるものの課金なしで試せます。まずはこれで自分の書き方に合うか確かめてから有料プランを検討する、という順番でも問題ありません。
インストールとセットアップ
copilot.vimはVim標準のパッケージ機能に対応しているので、プラグインマネージャーを使っていない環境ならpackディレクトリにcloneするのが最短です。公式が案内している配置先は次のとおりです。
# Vim (macOS/Linux)
git clone --depth=1 https://github.com/github/copilot.vim.git \
~/.vim/pack/github/start/copilot.vim
# Neovim (macOS/Linux)
git clone --depth=1 https://github.com/github/copilot.vim.git \
~/.config/nvim/pack/github/start/copilot.vim
Windowsの場合はVimが$HOME/vimfiles/pack/github/start/copilot.vim、Neovimが$HOME/AppData/Local/nvim/pack/github/start/copilot.vimになります。startの下に置いたプラグインは起動時に自動で読み込まれるので、~/.vimrcに書き足すものはありません。読み込まれているか怪しいときは:scriptnamesでパスが並んでいるか確認できます。
vim-plugやlazy.nvimを使っているなら、いつもどおりリポジトリ名を1行足すだけです。
Plug 'github/copilot.vim' " vim-plug (~/.vimrc)
{ 'github/copilot.vim' }, -- lazy.nvim (init.lua)
プラグインを置いたらVimを起動し直して:Copilot setupを実行します。8桁前後のワンタイムコードとURLが表示されるので、ブラウザでそのURLを開いてコードを貼り、GitHubアカウントで承認します。承認が終わるとVim側が自動的に検知して有効になり、以降は認証情報が~/.config/github-copilot/に保存されるため、次回以降のセットアップは不要です。サインアウトしたいときは:Copilot signoutを使います。
候補を受け取るキー操作
Copilotの候補はポップアップメニューではなく、カーソルの先に薄いグレーで直接表示されます(ゴーストテキストと呼ばれる表示です)。Vim標準のCtrl-nによる補完のように候補リストから選ぶのではなく、目の前の1案を丸ごと受け入れるか無視するかを決める操作になります。
| キー | 動作 | 割り当てられている実体 |
|---|---|---|
| Tab | 候補全体を確定する | copilot#Accept() |
| Ctrl-] | 今の候補を消す | <Plug>(copilot-dismiss) |
| Alt-] | 次の候補に切り替える | <Plug>(copilot-next) |
| Alt-[ | 前の候補に戻る | <Plug>(copilot-previous) |
| Alt-\ | その場で候補を要求する | <Plug>(copilot-suggest) |
| Alt-Right | 候補のうち1単語だけ確定する | <Plug>(copilot-accept-word) |
| Alt-Ctrl-Right | 候補のうち1行だけ確定する | <Plug>(copilot-accept-line) |
Altを使うマップは端末エミュレータ側の設定に強く依存し、macOSのターミナルではOptionキーが別の文字入力として解釈されて届かないことがよくあります。効かなかったら諦めるのではなく、右列の<Plug>マップを自分の押しやすいキーに割り当て直すのが正解です。未割り当てのキーを探して~/.vimrcに書きます。
imap <C-L> <Plug>(copilot-accept-word)
もう1つ知っておくと安心なのが、Tabが乗っ取られるわけではないという点です。プラグインが実際に定義しているマッピングを:verbose imap <Tab>で覗くと、こうなっていました。
i <Tab> & empty(get(g:, 'copilot_no_tab_map')) ? copilot#Accept() : "\t"
候補が表示されていないときのTabは通常のタブ入力に戻り、既に自分でTabにマッピングを割り当てていた場合はそちらがフォールバックとして呼ばれます。それでも別のキーで確定したい場合は、g:copilot_no_tab_mapを立ててからcopilot#Accept()を好きなキーに割り当てます。引数には「候補が無かったときに代わりに送るキー」を渡します。
imap <silent><script><expr> <C-J> copilot#Accept("\<CR>")
let g:copilot_no_tab_map = v:true
候補を1つずつ見比べたいときは:Copilot panelが便利です。最大10件の候補を別ウインドウに並べ、Enterで選んだものを挿入できます。ウインドウ内では[[と]]で候補から候補へジャンプできます。
補完が出ないときは:Copilot statusを読む
ここがこの記事の本題です。Copilotは「動いていません」とエラーを出して止まるのではなく、条件を満たさないバッファでは何も言わずに黙るので、体感としては「入れたのに反応しない」になります。原因は:Copilot statusが1行で教えてくれます。実際に手元で再現できたメッセージを並べます。
| メッセージ | 意味と対処 |
|---|---|
Error: You are not signed into GitHub. | 認証が終わっていない。:Copilot setupを実行する |
Disabled for filetype=gitcommit by internal default | そのfiletypeがプラグインの既定で除外されている |
Disabled for filetype= by internal default | filetypeが空。ファイル名の無い新規バッファでよく起きる |
Disabled for filetype=... by g:copilot_filetypes | 自分の設定で除外している |
Ready | そのバッファでは有効 |
いちばん引っかかりやすいのが3行目の、filetype=の後ろが空になっているパターンです。vimとだけ打って起動した無名バッファや:enewで開いた空バッファはfiletypeが決まっていないため、Copilotは既定で対象外にします。「とりあえず動くか試そう」と空のVimを立ち上げて何か書いてみる、という一番自然な試し方が、そのまま一番反応しないパターンになっているわけです。ファイル名を付けて保存するか:setfiletype pythonのように明示すれば有効になります。
プラグインのソースを読むと、既定で無効にされるfiletypeは次の5つと「filetypeが空の状態」だけでした。
gitcommit:コミットメッセージgitrebase:git rebase -iの編集画面hgcommit:Mercurialのコミットメッセージsvn:Subversionのコミットメッセージcvs:CVSのコミットメッセージ
Git・Mercurial・Subversion・CVSと、バージョン管理システムのコミットメッセージが軒並み外されています。理由はソースには書かれていませんが、他人が読む文章まで勝手に生成されるのを避ける狙いでしょう。加えてbuftypeがhelp・quickfix・terminal・promptのバッファも対象外です。こちらはそもそもコードを書く場所ではないので、実害のない除外です。
ここで1つ、日本語の解説記事でよく見かける情報が古くなっています。「markdownとyamlは既定で無効なのでg:copilot_filetypesで明示的に有効化する必要がある」という記述です。手元の1.59.0で.mdと.yamlを開いて:Copilot statusを叩いたところ、どちらもDisabledの行は返ってきませんでした。除外リストは上の5つに整理済みなので、今から入れる人がmarkdownのために設定を足す必要はありません。
逆に、コミットメッセージでもCopilotに書かせたい場合や、特定のファイルタイプだけ切りたい場合はg:copilot_filetypesで上書きします。実際にgitcommitを有効側へ戻すと、:Copilot statusの返答がDisabledから変わることを確認しました。
let g:copilot_filetypes = {
\ 'gitcommit': v:true,
\ 'xml': v:false,
\ }
全部を既定で切っておいて、使いたい言語だけ個別に開ける運用もできます。特殊キー'*'が全体の既定値になります。
let g:copilot_filetypes = {
\ '*': v:false,
\ 'python': v:true,
\ }
ファイル単位で一時的に切りたいだけならlet b:copilot_enabled = v:false、逆にfiletypeの既定を無視して今のバッファだけ有効にしたいならv:trueを入れます。Vim全体を止めるのは:Copilot disableで、:Copilot enableで戻ります。
要点:起動直後の:Copilot statusは当てになりません。Vimを開いてすぐ実行するとCopilot: Readyと返ってくるのに、3秒ほど待ってもう一度実行するとError: You are not signed into GitHub.に変わる、という挙動を再現できました。サインイン状態の確認が非同期で走っているためで、最初の1回はまだ結果が返っていないだけです。状態を確かめるときは一呼吸おいてから、できれば2回叩いてください。
言語サーバーはどのNodeで動いているのか
補完そのものはVimのプラグインが計算しているわけではなく、別プロセスで動くCopilot Language Serverが担当しています。この構成を知っておくと、トラブルの切り分けがぐっと楽になります。状態は:Copilot versionで見えます。手元での出力はこうでした。
copilot.vim 1.59.0
Vim 9.1.1752
GitHub Copilot Language Server 1.527.4
Node.js 22.23.1
macOS
注目してほしいのはNode.js 22.23.1の行です。この検証マシンのPATHに入っているnodeはv18.20.2で、22系はどこにもインストールしていません。それでも22.23.1と表示されるのは、現在の言語サーバーがプラットフォームごとのネイティブバイナリとして配布されていて、実行に使うNodeランタイムを自分の中に抱えているからです。つまりPATHのNodeが少々古くても、言語サーバー自体は自前の新しいランタイムで動きます。「Node.js 18以上を入れないとCopilotは動かない」という説明を見かけますが、少なくとも1.59.0の構成ではそこまで神経質になる必要はありません。
ではPATHのnodeは何に使われているかというと、その言語サーバーを取ってくるnpxの実行です。g:copilot_versionを指定していない場合、プラグインは起動時にnpx経由で@github/copilot-language-serverの適合バージョンを取得します。初回の起動だけやたら待たされるのはこのダウンロードが走っているためで、実際に検証後の~/.npm/_npx/を覗くと、ダウンロードされたパッケージ一式が残っていました。2回目以降はキャッシュから起動するので待ち時間は消えます。
このnpx方式が都合の悪い環境もあります。ネットワークが制限されていてnpxが外に出られない場合や、起動のたびに外部から実行ファイルを取ってくる挙動を避けたい場合です。その場合はg:copilot_versionにv:falseを入れると、プラグインに同梱されている静的な言語サーバーを使うようになります。手元のcopilot.vim 1.59.0に同梱されていたのはバージョン1.408.0で、npxが取ってくる1.527.4より古い代わりに、外部への取得が一切発生しません。
let g:copilot_version = v:false " 同梱の言語サーバーを使う
let g:copilot_version = 'latest' " 起動のたびに最新を取得する
PATHのNodeが本当に古すぎてnpxすら動かない場合は、プラグインがNode.js too old. Upgrade to N.x or newerという専用のメッセージを出します(プラグインのソースで確認しました。手元の18.20.2では再現しませんでした)。バージョン管理ツールで複数のNodeを併用している人は、g:copilot_node_commandで使うバイナリを直接指定できます。
let g:copilot_node_command = "~/.nodenv/versions/22.11.0/bin/node"
社内プロキシの内側にいる場合はg:copilot_proxyでプロキシを指定します。SSLの中間証明書を挟む構成で接続が通らないときの逃げ道としてg:copilot_proxy_strict_sslをv:falseにする設定も用意されていますが、証明書の検証を止める設定なので、他に手が無いときだけにしてください。
Neovimでの違い
copilot.vimはVimとNeovimの両方を同じコードベースでサポートしているので、コマンドもオプションも共通です。違うのはプラグインの置き場所と、設定をLuaで書くときの記法だけです。
| 項目 | Vim | Neovim |
|---|---|---|
| 配置先 | ~/.vim/pack/github/start/ | ~/.config/nvim/pack/github/start/ |
| 設定ファイル | ~/.vimrc | ~/.config/nvim/init.lua |
| グローバル変数 | let g:copilot_no_tab_map = v:true | vim.g.copilot_no_tab_map = true |
| キーマップ | imap | vim.keymap.set('i', ...) |
Luaで確定キーを差し替える場合は、replace_keycodesを明示的に切る必要があります。ここを省くと<CR>の扱いが変わってフォールバックが壊れます。
vim.keymap.set('i', '<C-J>', 'copilot#Accept("\\<CR>")', {
expr = true,
replace_keycodes = false
})
vim.g.copilot_no_tab_map = true
Neovim側で実際に多いトラブルは、Copilotそのものではなくキーの取り合いです。nvim-cmpのような補完プラグインがTabを先に押さえていると、Copilotの候補ではなく補完メニューの選択が動いてしまいます。この場合はCopilot側を別のキーに逃がすか、補完メニューが開いているかどうかで分岐する条件付きマッピングを書くことになります。プラグインの読み込み順や依存関係が絡んで原因が見えにくいときは、:checkhealthで全体の構成を確認してから絞り込むと早いです。
最初に試したとき、空のVimを起動していきなり関数を書き始めて「何も出ない」と数分悩みました。原因はfiletype=が空だったことで、:Copilot statusを叩いていれば1行で分かった話です。プラグインが黙って無効になる仕様である以上、入れた直後にまずステータスを確認する癖をつけたほうが、結果的に早く動くところまで辿り着けます。
まとめ
VimでGitHub Copilotを使うのに特別な回り道は必要なく、packディレクトリにcloneして:Copilot setupを実行すれば公式サポートの範囲で動きます。躓くとしたらインストールではなく、その後の「なぜか候補が出ない」のほうです。:Copilot statusを1回叩けば、サインインの問題なのか、そのバッファが除外されているのかが即座に分かります。特にfiletypeが空の無名バッファは既定で対象外なので、試すときは拡張子の付いたファイルを開いてください。言語サーバーが自前のNodeランタイムを抱えて別プロセスで動いていることまで把握しておけば、Nodeのバージョンやプロキシが絡んだ問題も切り分けられます。