Neovim 0.12 徹底レビュー - vim.pack と autocomplete で外部プラグインから卒業できるか

Neovim 0.12 徹底レビュー - vim.pack と autocomplete で外部プラグインから卒業できるか

作成日:
更新日:

はじめに - 0.12は「ビルトイン回帰」のリリース

Neovim0.12.0は、GitHubReleases上では2026年3月29日17:16:57UTCに公開されています。日本時間では2026年3月30日2:16:57です。

公式ロードマップでは0.12の見出しをThe year of Nvim OOTBと置き、vim.pack、進捗メッセージ、LSPの追加能力、デフォルトステータスライン、プロンプトバッファ強化などを並べています。ここでいうOOTBは、追加プラグインを入れる前のNeovim本体だけで使える範囲を広げる方向性です。

この記事では、0.12を「外部プラグイン不要になった」と雑にまとめるのではなく、どこまで本体機能で置き換えられるのかを見ます。特に焦点は次の2つです。

  • vim.packでプラグイン管理をどこまで本体に寄せられるか
  • vim.lsp.completion.enable()'autocomplete'、inline completionで補完プラグインをどこまで減らせるか

結論を先に言うと、プレーンなNeovim構成なら0.12はかなり魅力的です。一方、LazyVimやlazy.nvimで育った構成をそのまま置き換えるには、まだ割り切りが必要です。

主要変更点サマリ

領域0.12の変更実用度置き換え候補
プラグイン管理vim.packを追加小規模構成なら実用的一部のpacker.nvim用途
補完'autocomplete'とLSP補完を強化LSP中心なら実用的軽いnvim-cmp構成
inline completionLSPtextDocument/inlineCompletionに対応サーバー依存Copilot系の一部操作
LSP診断workspace diagnosticsやpull diagnosticsを拡張大規模リポジトリで有用診断表示の自作部分
document colors色参照のハイライトを標準提供CSS/設定ファイルで有用色表示系の軽量プラグイン
code lens再実装され、virtual lines表示に変更対応サーバーなら有用個別codelens設定
起動/実行性能vim.glob.to_lpeg()i_CTRL-R:packadd周りを改善条件が合うと効く一部の最適化プラグイン
ステータスライン診断と進捗をデフォルト表示最小構成なら十分簡易statusline設定

vim.pack詳説

vim.packは、Neovim本体に入ったプラグインマネージャーです。公式ヘルプでは「外部プラグインのインストール、更新、削除」を行う機能と説明されています。ただし、同じヘルプ内でexperimentalとも明記されています。日常利用に耐える安定性を目指しているものの、lazy.nvimのような成熟した周辺機能をすべて持つわけではありません。

管理対象ディレクトリはstdpath('data')配下のsite/pack/core/optです。Gitを使ってプラグインを取得し、状態は$XDG_CONFIG_HOME/nvim/nvim-pack-lock.jsonに保存されます。公式ヘルプでは、このロックファイルを設定の一部としてバージョン管理する考え方も示されています。

最小設定例

init.luaに直接書くなら、まずはこのくらいから始められます。

init.lua
vim.pack.add({
  { src = 'https://github.com/nvim-lua/plenary.nvim' },
  {
    src = 'https://github.com/echasnovski/mini.nvim',
    name = 'mini.nvim',
    version = 'main',
  },
})
 
require('mini.files').setup()

srcにはgit cloneで扱えるURIを指定します。nameを省略するとリポジトリ名がディレクトリ名になります。versionは未指定ならリポジトリのデフォルトブランチ、文字列ならブランチ/タグ/コミット、vim.version.range()ならsemverタグの範囲指定として扱われます。

更新はLua関数としてはvim.pack.update()で実行できます。更新前に確認バッファを出す挙動も用意されています。対話なしに進めたい場合はforceオプションを使う設計です。

lazy.nvim/packer.nvimとの機能比較

観点vim.packlazy.nvimpacker.nvim
本体同梱はいいいえいいえ
設定方式vim.pack.add()プラグイン仕様テーブルuseベースの仕様
ロックファイルnvim-pack-lock.jsonlazy-lock.jsonsnapshot機能
Git取得対応partial clone対応対応
遅延読み込み手動設計が中心イベント/コマンド/ft/キーで自動化イベント/コマンド/ftなど
UI更新確認バッファ中心管理UI、更新確認、プロファイルフローティングUIあり
依存解決明示順序の設計が必要依存順序制御あり依存指定あり
プロファイル本体機能としては限定的ありあり
向いている構成少数プラグイン、標準寄せ本格構成、LazyVim既存packer構成の維持

lazy.nvimのREADMEは、強力なUI、Luaモジュールの自動キャッシュ、イベント/コマンド/ファイルタイプ/キーマップでの遅延読み込み、依存順序、プロファイリング、ロックファイルを機能として挙げています。packer.nvimも、宣言的な仕様、依存関係、lazy-loading、コンパイル済みローダー、snapshotなどを持っています。

そのため、vim.packは「本体に入った最小中核」と見るのが自然です。lazy.nvimを丸ごと置き換えるというより、まずは小さな設定、検証用環境、最小構成のdotfilesで効いてきます。

LazyVimユーザーが乗り換える価値はあるか

LazyVimユーザーが、既存構成のプラグイン管理をvim.packへ全面移行する価値は、2026年5月時点では低めです。

理由は単純で、LazyVim自体がlazy.nvim上に構成されています。LazyVimのREADMEも、NeovimをIDEに近い状態へ変えること、lazy.nvimで簡単にカスタマイズできること、多数のプラグインが事前設定済みであることを特徴にしています。ここをvim.packへ差し替えると、LazyVimの前提から外れます。

ただし、次のような用途なら試す価値があります。

  • LazyVimとは別に、素のNeovim検証用プロファイルを作る
  • サーバー上で数個のプラグインだけを使う軽量設定を作る
  • 自分のdotfilesから外部プラグインマネージャー依存を減らす
  • プラグイン開発時に、本体機能だけで再現環境を作る

LazyVim本体を使い続けるなら、vim.packは今すぐの乗り換え先というより、Neovim本体の方向性を知るための観察対象です。

vim.packで詰まる典型ケース

vim.packはシンプルですが、シンプルさゆえに詰まりどころもあります。

ケース原因見直す場所
インストールされないGit実行ファイルが見つからないgit --version、PATH
管理ディレクトリが見つからない--cleanXDG_DATA_HOME変更でpackpathが想定外:set packpath?
semver範囲指定が効かない対象リポジトリにv1.2.3形式のタグがないタグ一覧、version指定
既存プラグインが古いままadd()だけでは既存revisionの同期確認をしないvim.pack.update()
遅延読み込みが足りないlazy.nvimのイベント指定に相当する高機能DSLはないautocmdや手動packadd
依存関係で壊れる依存順や読み込みタイミングを自分で設計する必要があるadd()の順序、require()位置
ロックファイルを直したくなる公式ヘルプでは手編集しない前提削除後の再生成、バージョン管理

特に、lazy.nvimeventcmdftkeysに慣れていると、vim.packはかなり素朴に感じます。そこを「不便」と見るか「標準APIとして十分」と見るかで評価が分かれます。

ネイティブautocomplete

0.12の補完は、nvim-cmpblink.cmpを一気に不要にするというより、Neovim本体の補完レイヤーが実用域に近づいたリリースです。

vim.lsp.completion.enable()と'autocomplete'オプション

まず分けて考えたいのは、vim.lsp.completion.enable()'autocomplete'は同じものではないという点です。

vim.lsp.completion.enable()は、指定したLSPクライアントとバッファに対して、LSP由来の補完候補をNeovimの組み込み補完へ流すためのAPIです。公式ヘルプでは、autotrigger=trueにするとサーバー定義のtriggerCharactersに基づいて自動補完が起動すると説明されています。すべてのキー入力で起動したい場合は、triggerCharactersを拡張するか、InsertCharPreからvim.lsp.completion.get()を呼ぶ案が示されています。

一方、'autocomplete'はエディタのオプションです。オンにすると、i_CTRL-Nに近い補完メニューが入力中に自動表示されます。遅延は'autocompletedelay'、タイムアウトは'autocompletetimeout'で調整できます。公式ヘルプ上のデフォルトは'autocomplete'がoff、'autocompletedelay'が0、'autocompletetimeout'が80です。

LSP中心の最小設定なら、まずは次の形で十分です。

init.lua
vim.opt.completeopt:append({ 'menuone', 'noselect', 'popup' })
 
vim.api.nvim_create_autocmd('LspAttach', {
  callback = function(ev)
    local client = vim.lsp.get_client_by_id(ev.data.client_id)
    if client and client:supports_method('textDocument/completion') then
      vim.lsp.completion.enable(true, client.id, ev.buf, {
        autotrigger = true,
      })
    end
  end,
})

この設定で、LSPサーバーが補完をサポートしていれば、組み込み補完の候補として扱えます。候補の確定はCTRL-Yです。nvim-cmpに慣れている場合、Enter確定やTab選択は自分でキーマップを考える必要があります。

inline completionの挙動

0.12ではLSPのtextDocument/inlineCompletionがサポートされています。公式ヘルプでは、通常の補完が単語や行の候補をメニューに出すのに対し、inline completionは複数行のテキスト、たとえばメソッド全体の候補をoverlay textとして表示する機能と説明されています。

有効化と受け入れは通常の補完とは別です。

inline completion
vim.lsp.inline_completion.enable(true)
 
vim.keymap.set('i', '<Tab>', function()
  if vim.lsp.inline_completion.get() then
    return ''
  end
  return '<Tab>'
end, { expr = true, desc = 'Accept inline completion or fallback' })

ここで重要なのは、inline completionはNeovimだけで完結しないことです。対応するLSPサーバーが必要です。公式ヘルプのquickstartではCopilot Language Serverの例が示されています。したがって「0.12にしたらAI補完が勝手に出る」ではありません。

nvim-cmp/blink.cmpユーザーの移行可否

LSP候補だけでよく、補完UIに強いこだわりがないなら、本体補完への移行は現実的です。特に小さなLua設定、サーバー上の編集、プラグインを極力減らしたい環境では試しやすいです。

一方、次の用途があるならnvim-cmpblink.cmpを残す方が無難です。

  • LSP、バッファ、パス、スニペット、絵文字ではなく記号候補など、複数sourceを細かく統合したい
  • Enter、Tab、Shift-Tab、snippet jumpをひとまとめに制御したい
  • 候補の並び順、フィルタリング、表示幅、ドキュメント表示を細かく作り込みたい
  • LazyVimの既存補完UXを崩したくない

0.12のネイティブ補完は「軽い構成なら卒業できる」段階です。補完体験そのものをエディタの中心に置いている人には、まだ外部プラグインの価値が残ります。

LSP拡張の実用度

0.12のLSPは、目立つUI変更よりもプロトコル対応と標準挙動の底上げが効いています。

機能公式で確認できる内容実用上の見方
workspace diagnosticsvim.lsp.buf.workspace_diagnostics()を追加プロジェクト全体診断をサーバーへ要求できる
document colorsdocument color highlightingはデフォルト有効CSS、Tailwind設定、テーマ設定で便利
color presentationvim.lsp.document_color.color_presentation()を提供色表現の変換UIを作りやすい
code lenstextDocument/codeLensが再実装され、code lensesはvirtual lines表示テスト実行や参照数表示が見やすくなる可能性
codeLens refreshworkspace/codeLens/refreshに対応サーバー側から再取得を促せる
diagnostic refreshworkspace/diagnostic/refreshに対応pull diagnostics系の更新と相性が良い
dynamic registrationtextDocument/diagnosticのdynamic registration対応LspAttach後に能力が増えるケースを扱いやすい
:checkhealth vim.lsp有効なLSP機能がどのバッファへ付いているか確認可能移行時の最初の確認先になる

個人的に効くと思うのは、workspace diagnosticsと:checkhealth vim.lspです。LSPが動いているかどうかは、以前からLspInfoやプラグイン側のUIで見ることが多かったところです。0.12では本体側の健康診断で、どの機能がどのバッファへ付いているかを追いやすくなっています。

dynamic registrationについては、自前のon_attachで「サーバーがこのメソッドを持っていたらキーマップを生やす」という実装をしている人ほど注意が必要です。公式ヘルプは、サーバーがdynamic registrationを行う場合、能力はLspAttach後に登録されることがあるため、client/registerCapabilityイベントを扱う選択肢を示しています。

パフォーマンス - LuaJIT2.1で15〜20%高速化をどう見るか

0.12.0のGitHubReleases本文では、ビルド情報としてLuaJIT 2.1.1774638290が示されています。

ただし、今回確認したNeovim公式リリース本文、0.12のnews.txt、ロードマップの範囲では、「LuaJIT2.1によりNeovim全体が15〜20%高速化した」という直接の記述は確認できませんでした。そのため、この記事ではその数値をNeovim公式の性能保証としては扱いません。

公式の0.12news.txtで確認できるパフォーマンス項目は、より具体的です。

  • vim.glob.to_lpeg()がLPegベース実装になり、複雑なpatternで約50%高速化
  • i_CTRL-Rで名前付き/クリップボードレジスタをliteralに挿入し、10倍高速化
  • LSPtextDocument/semanticTokens/rangeで表示範囲だけのsemantic tokensを要求
  • :packaddがLua package pathキャッシュを無効化せず、インプレース更新するようになった

つまり、0.12の高速化は「LuaJIT2.1だから一律に速い」と見るより、特定の処理パスで改善が入ったと見る方が安全です。起動が重い設定では:packaddvim.pack.add()の置き方、巨大ファイルではsemantic tokensやTreesitter、日常操作では補完やレジスタ貼り付けの挙動が体感に出やすいはずです。

既存設定の移行手順

いきなり既存のlazy.nvimnvim-cmpを消すのではなく、切り分けながら進めるのがおすすめです。

1. Neovim0.12の状態を確認する

まずはバージョンとLSP状態を確認します。

Neovim
:version
:checkhealth
:checkhealth vim.lsp

:checkhealth vim.lspでは、LSPがどのバッファにattachしているか、どの機能が有効かを見ます。0.12ではこの確認が移行時の基準になります。

2. プラグイン管理だけを別プロファイルで試す

本命の~/.config/nvimを触る前に、別のNVIM_APPNAMEで検証すると戻しやすいです。

Shell
NVIM_APPNAME=nvim-012-pack nvim

この別プロファイルでvim.pack.add()を試し、プラグイン数が少ない構成なら運用できるか見ます。LazyVim本体を使っている場合、ここで本体設定とは分けて検証するのが安全です。

3. 補完はLSPだけで成立するかを見る

nvim-cmpblink.cmpを外す前に、次を確認します。

  • LSPサーバーがtextDocument/completionを返すか
  • vim.lsp.completion.enable()で候補が出るか
  • completeoptCTRL-Y、Tab/Enterの操作が自分に合うか
  • snippet展開やパス補完を本当に使っているか

snippetやパス補完を多用しているなら、補完プラグインを残す判断で問題ありません。本体補完へ寄せる価値は、外部依存を減らしたいときに大きくなります。

4. mason/null-ls周辺を互換確認する

mason.nvimはLSPサーバーや周辺ツールのインストール管理、null-ls系は外部formatter/linterをLSP風に扱うための層です。vim.packはプラグイン取得を担当するだけなので、この2つの役割を直接置き換えるものではありません。

移行時は次の順で見ます。

確認対象見るべき点
masonサーバー実体のパス、インストール済みserver、既存lspconfig設定
LSP設定vim.lsp.config()または既存nvim-lspconfig経由の起動状況
null-ls系formatter/linterの実行ファイル、対象filetype、保存時formatのautocmd
診断vim.diagnostic.open_float()、location list、quickfixへの出方
health:checkhealth vim.lsp:checkhealthの警告

外部ツールを呼ぶ部分は、0.12本体だけで急に解決する領域ではありません。プラグイン管理と補完UIを軽くしても、formatter、linter、language serverの実体管理は別途残ります。

5. 削る順番を決める

移行の順番は、リスクが小さいところから進めます。

  1. 新規プロファイルでvim.packを試す
  2. LSP補完を別キーマップで試す
  3. nvim-cmpまたはblink.cmpのsource利用状況を洗い出す
  4. snippetやpath補完が不要なfiletypeから本体補完へ寄せる
  5. 最後に本命プロファイルへ反映する

特にLazyVimでは、補完、snippet、UI、diagnostics、formattingが複数プラグインで連動しています。1つだけ抜くと、想定外にキーマップや表示が崩れることがあります。

結論 - LazyVim/プレーンnvim/Vim移行検討中の3視点で評価

LazyVimユーザー

LazyVimユーザーは、0.12の新機能を「今すぐ全面移行」ではなく「本体側の進化として観察」するのがよさそうです。

vim.packは面白いですが、LazyVimの前提であるlazy.nvimのUI、遅延読み込み、依存解決、ロックファイル、既存のplugin specを捨ててまで移る理由はまだ強くありません。補完も、LazyVimのblink.cmpまたはnvim-cmp構成を使っているなら、snippetやsource統合まで含めてそのまま使う方が安定します。

ただし、NVIM_APPNAMEを分けて「素のNeovim0.12構成」を作る価値はあります。Neovim本体の未来を知るには、LazyVimの外に1つ小さな環境を持つのが一番分かりやすいです。

プレーンnvimユーザー

プレーンなNeovim設定を育てている人には、0.12はかなり刺さります。

プラグインが10個前後で、遅延読み込みも複雑ではなく、LSP補完中心なら、vim.packとネイティブ補完へ寄せる現実味があります。特に、設定ファイルを長期運用するなら「本体APIで済むものは本体へ寄せる」という設計は強いです。

ただし、依存関係が多い構成、プラグインの更新差分をUIで細かく見たい構成、プロファイルを見ながら起動速度を詰めたい構成では、lazy.nvimの方がまだ楽です。

Vim移行検討中の人

VimからNeovimへ移る理由として、0.12は分かりやすい節目になりました。

Lua設定、LSP、補完、inline completion、vim.pack、デフォルトステータスラインまで、本体側の機能だけで「まず使える」範囲が広がっています。最初から巨大なディストリビューションへ入るのが不安なら、0.12の標準機能を軸に小さく始める選択肢があります。

一方で、IDE的な体験をすぐ欲しいならLazyVimのような構成は今でも強いです。0.12は「外部プラグインから卒業するリリース」というより、「卒業できる領域を本体が少しずつ広げたリリース」と捉えるのが近いです。

参考