この記事が扱う症状
以下に心当たりがある人向けです。
- LazyVim で
<leader>sg(Grep (Root Dir))を押しても何も起きない <leader>ffのファイル検索も期待どおりに動かない- fzf-lua が「fzf が無い」という趣旨のエラーを出す
- シェルで
which rgを叩くと反応が返ってくるのに、nvim からは検索できない - 確認すると
fzf not foundやexecutable("fzf") = 0になっている - キーマップを調べると正しく割り当たっているので余計に分からない
結論を先に書きます。原因は設定ではなく、外部バイナリの不在です。 LazyVim の検索まわりは Lua プラグインを入れただけでは動かず、rg(ripgrep)・fd・fzf の 3 本が実体として必要です。
brew install ripgrep fd fzfインストール後は nvim を再起動してください。理由は後述します。
キーマップは生きていた
<leader>sg で grep したいのにできない、というところから始まりました。まず疑ったのは自分の設定です。~/.config/nvim を見ても、キーマップを潰すような記述はありません。
nvim 自身に聞くのが早いので、割り当てを直接出しました。
nvim --headless -c 'lua local m = vim.fn.maparg("<leader>sg", "n", false, true); print(m.lhs, m.desc)' -c 'qa'<Space>sg Grep (Root Dir)設定は正しく入っていました。 <Space>sg が “Grep (Root Dir)” に割り当たっている。つまりキーを押せば LazyVim の grep が呼ばれているはずで、なのに画面には何も出ない。
ここが分かりにくいところです。LazyVim のキーマップはプラグインが読み込まれている限り常に存在します。押しても無反応なとき、キーマップが死んでいるのか、呼ばれた先で失敗しているのかは、キーマップ側を見ても区別がつきません。
登場人物を数える
呼ばれた先で失敗しているなら、失敗しうるのは検索の実体です。nvim から見た外部コマンドの状態を出します。
nvim --headless -c 'lua print("rg", vim.fn.executable("rg"), "fd", vim.fn.executable("fd"))' -c 'qa'rg 0 fd 0executable() は「そのコマンドが実行可能か」を 1 / 0 で返します。両方 0。ripgrep も fd も入っていませんでした。
which rg は当てにならなかった
ここで一度混乱しました。シェルで which rg や command -v rg を叩くと、反応が返ってくるのです。入っているように見える。
正体はこれでした。
rg () {
local _cc_bin="${CLAUDE_CODE_EXECPATH:-}"
...
}Claude Code がシェルに定義している関数で、実体のバイナリではありません。関数はそのシェルの中にしか存在しないので、nvim から見れば無いのと同じです。だから executable("rg") は 0 のまま。
シェルで見えるのに nvim で動かないときは、シェルに聞かず nvim に聞くのが確実です。ターミナルのプロンプトで確認した結果は、nvim の中の話の証拠になりません。
1回目の修理は、必要だったが足りなかった
ripgrep と fd を入れました。
brew install ripgrep fd🍺 /opt/homebrew/Cellar/ripgrep/15.2.0
🍺 /opt/homebrew/Cellar/fd/10.5.0nvim から見ても rg: 1 / fd: 1 に変わりました。設定ファイルは一切触っていないので、再起動すれば効くはずです。
それでも grep はできませんでした。
真犯人は3本目のバイナリ
決め手は調査ではなく、本人の一言でした。
leader sgでgrepできません。fzfがないだとかエラーが表示されます。
エラーが出ていること、そこに fzf と書いてあること。この 2 つが分かった時点で残りは早かったです。
LazyVim はどの picker を使うかを切り替えられます。設定と、実際に選ばれた結果を並べて出します。
nvim --headless -c 'lua print(vim.g.lazyvim_picker, LazyVim.pick.picker.name)' -c 'qa'auto fzf左が設定値、右が解決結果です。auto のままだと、インストール済みのプラグインから fzf-lua が選ばれていました。 そして fzf-lua は、名前のとおり fzf のラッパーです。
which fzffzf not foundfzf バイナリだけ入っていませんでした。 ripgrep と fd は 1 回目で入れたのに、3 本目が残っていた。fzf-lua は Lua プラグインだけでは動かず、fzf コマンド本体を呼びます。プラグインは lazy-lock.json に載っていて、更新もされていて、それでも動かない。
3 本それぞれの役割はこうなっています。
| バイナリ | 効くところ |
|---|---|
rg(ripgrep) | <leader>sg の grep。中身の検索 |
fd | <leader>ff のファイル検索 |
fzf | picker が fzf-lua のときの絞り込み UI そのもの |
直し方
brew install fzf🍺 /opt/homebrew/Cellar/fzf/0.74.4nvim から見えるか確認します。
nvim --headless -c 'lua print("rg", vim.fn.executable("rg"), "fd", vim.fn.executable("fd"), "fzf", vim.fn.executable("fzf"))' -c 'qa'rg 1 fd 1 fzf 13 本とも 1 になりました。ここまで来たら <leader>sg が動きます。
再起動が要る
インストール前から開いていた nvim では効きません。 fzf-lua はバイナリを起動時に探しますし、executable() の結果もセッション内でキャッシュされます。:Lazy reload では足りないので、:qa で閉じて開き直すのが確実です。
brew の caveat は無視してよい
fzf を入れると Homebrew がこう言ってきます。
To use fzf in Vim, add the following line to your .vimrc:
set rtp+=/opt/homebrew/opt/fzfこれは Vim 本体から fzf を使う場合の話で、fzf-lua には要りません。fzf-lua は $PATH にあるバイナリを直接呼ぶだけなので、~/.vimrc に何か足す必要はないです。
どうしても fzf を入れたくないなら
picker を変える手もあります。telescope.nvim も snacks.nvim も LazyVim には最初から入っているので、lua/config/options.lua に 1 行足すだけで切り替わります。
vim.g.lazyvim_picker = "telescope"ただし telescope の grep も結局 ripgrep を呼ぶので、rg は必要です。避けられるのは fzf だけです。
教訓
「設定が効かない」ときは、設定より先に依存バイナリを疑う。 LazyVim のキーマップはプラグインが読まれていれば常に存在します。押して無反応でも、それはキーマップが壊れている証拠にはなりません。設定ファイルを読み返すより、executable() を叩くほうが早いです。
which は環境によって嘘をつく。 シェル関数、エイリアス、シェル固有の仕組みは、そのシェルの中にしかありません。判定は、それを使う当人に聞く。nvim の中の話なら nvim に聞く。
1 つ直して直らなくても、その修理が無駄だったとは限らない。 ripgrep と fd は実際に必要で、入れたのは正解でした。足りないものが 1 つとは限らないだけです。「直したのに直らない」と思ったら、さっきの修理を疑う前に、同じ種類の不足がまだ残っていないかを数えたほうが早いことがあります。
そして、エラーメッセージを読めるのは画面の前にいる人だけです。 今回いちばん効いた情報は「fzf がないというエラーが出ている」という一言でした。ログを掘るより早かったです。

