【Vim】quickfix にフック機構を追加 / MCP経由でAI連携
はじめに
この記事は Vim advent calendar 2025 (Adventar) の 1日目の記事です。
Vim の quickfix は、コンパイルエラーや検索結果を効率的に扱える強力な機能です。
それらの恩恵を受けつつ、quickfix の操作に独自の処理をフックを統合しようとすると、autocmd では管理が煩雑 になります。
例えば、「QuickFix リストのファイルを開くたびに自動で差分比較を表示したい」 という場合:
" autocmd で実装すると...
" 問題:全ての quickfix で発火、条件分岐が複雑化、保守が困難
autocmd QuickFixCmdPost cnext call SomeDiffLogic()
この課題を解決するため、vim-qfhooks を開発しました。
コンテキストベースのフック機構により、特定の quickfix リストにだけ処理を適用できます。
qf-mcp
更に、「Neovim を AI から操作できるか?」 という実験的な試みとして qf-mcp も開発しました。
デモ

以前、カジュアルなLT会に参加した時に話した内容です。
vim-qfhooks の設計
Quickfix 拡張の課題
Vim の quickfix の操作に独自の処理をフックしようとすると問題があります
課題1:全ての quickfix で発火してしまう
" autocmd で実装すると...
" 問題:全ての quickfix で発火、条件分岐が複雑化、保守が困難
autocmd QuickFixCmdPost cnext call MyDiffLogic()
課題2:条件分岐が複雑化
function! MyDiffLogic()
" どの quickfix か判定が必要...
if getqflist({'title': 1}).title =~# 'git'
" Git diff 用の処理
elseif ...
" 他の処理
endif
endfunction
課題3:タイミング制御が難しい
" 実行前と実行後で別の処理をしたい -> 管理が煩雑
autocmd QuickFixCmdPre cnext ...
autocmd QuickFixCmdPost cnext ...
課題4:autocmd のパフォーマンス懸念
" 複数の autocmd を定義すると、全てが毎回実行される
autocmd QuickFixCmdPost cnext call Hook1()
autocmd QuickFixCmdPost cnext call Hook2()
autocmd QuickFixCmdPost cprev call Hook3()
" 問題:
" - 全ての quickfix コマンドの実行のたびに全ての autocmd が発火
" - フック数が増えるほどパフォーマンスが劣化
" - 実行順序の制御や優先度の制御が面倒
vim-qfhooks の解決策:コンテキストベースのフック
コンテキスト(現在は IDやタイトル)を付与することで、
特定の quickfix リストにだけフックを適用できます:
" コンテキスト (show_diff) を設定
call setqflist([], 'r', {
\ 'context': { 'qfhooks': 'show_diff' },
\ 'items': [...]
\ })
" show_diff コンテキストでのみ実行されるフックを定義
let g:qfhooks_context_hooks = {
\ 'show_diff': [
\ {
\ 'stage': 'after',
\ 'cmds': ['cnext', 'cprevious'],
\ 'priority': 10,
\ 'hook': function('AutoShowDiff')
\ }
\ ]
\ }
- コンテキストベース:現在の quickfix のコンテキストに一致するフックのみ評価
- オーバーヘッド削減:不要なフックは一切実行されない
- 優先度制御:priority パラメータで実行順序を明示的に指定可能
- コマンド別フック:cmds で特定のコマンド(cnext, cprev 等)にのみフックを限定
- タイミング制御: 'before' / 'after' で実行タイミングを細かく制御
詳細な実装例は GitHub リポジトリ を参照してください。
Neovim MCP 連携の実験
更に、「Neovim を AI から操作できるか?」 という実験的な試みとして qf-mcp も開発しました。
qf-mcp について
Neovim の RPC インターフェースを利用して、
quickfix を MCP ツールとして公開する Go サーバーを実装しました。
qf-mcp のセットアップ手順
1. Neovim RPC 設定
-- ~/.config/nvim/init.lua
vim.fn.serverstart('/tmp/nvim.sock')
2. qf-mcp のビルドと起動
git clone https://github.com/kis9a/vim-qfhooks.git
cd vim-qfhooks/qf-mcp
go build -o qf-mcp ./cmd/qf-mcp
# MCP サーバー起動
./qf-mcp --nvim-address /tmp/nvim.sock
MCP クライアント(Claude Code 等)から標準入出力経由で操作可能になります。
アーキテクチャ
MCP ツール
| ツール名 | 機能 |
|---|---|
| qf.set_list | quickfix リスト作成・更新 |
| qf.jump | ナビゲーション(next/prev/first/last) |
| qf.get_cursor_item | 現在の quickfix アイテム取得 |
| qf.get_list | quickfix リスト全体を取得 |
| qf.add_hooks | 動的フック追加(vim-qfhooks 必須) |
| vim.cmd | Vim コマンド実行(ホワイトリスト) |
できること
Claude Code に自然言語で指して quickfix を操作できます‼️
例:
👦 変更ファイルを quickfix に読み込んで
-> Claude が qf.set_list ツールを使って自動で quickfix 作成
👦 quickfix の次のアイテムへ移動して、変更内容をレビュー
-> Claude が qf.jump ツールで cnext を実行し、変更内容をレビュー
詳細は GitHub リポジトリ を参照してください。
まとめ
quickfix という地味な機能ですが、フック機構や AI 連携を組み合わせることで、意外と面白い開発体験ができるかもしれません。このような自由なカスタマイズができるのも、Vim というエディタの懐の深さのおかげだと改めて感じています。Vim も AI 連携はまだ勉強中ですが、バッファ操作や LSP との連携など、今後もっと面白いことができそうでワクワクしています🚀
Vim を学ぶとは、テキストを速く編集することではない。自分というホモサピエンスの認知の限界を覗き込み、言語と身体と思想をひとつの体系へ統合する試みである。だからこそ、Vimを教えるという行為は、道具の説明ではなく、知性の自己進化の案内なのだ。
Discussion