🧪

【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 も開発しました。

デモ

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