Neovimの履歴管理ができるAIプラグインsenpai.nvimの使い方
この記事はVim駅伝の2025年4月9日の記事です。
前回(2025年4月7日)の記事はmikoto2000さんのdevcontainer.vim で Claude Code を使うでした。
NeovimのAIプラグインもかなり増えてきましたね。今回はチャット履歴を保存して、後から会話も継続できるAIプラグインsenpai.nvimを紹介します。

senpai.nvimとは
senpai.nvimはNeovimのAI系プラグインです。筆者が作りました。
既存プラグインと比べた特徴は次のとおり。
- チャットの履歴が管理できる
- Mastra/Vercel AI SDKベースで作られている
- 呼び出しのためのデフォルトキーマップを設定していない
他の機能は次のとおり。
- MCP(Model Context Protocol)
- RAG(Retrieval Augmented Generation)
- プロンプトをカスタマイズしてチャットを開く(一言でなんていえばいいんでしょうね)
- conventionalコミットメッセージの作成
導入方法
eetann/senpai.nvim
依存
依存はあります。なるべく依存減らしたいって人、ごめんなさいね。
- curl
- Bun
- インストール簡単だから許して
- 依存プラグイン
- nui.nvim: UIの表示で使用
- plenary.nvim: curlとかのラッパー
- nvim-treesitter: UIの表示で使用
Node.jsではなくBunを採用したのは速いからです。
インストール
lazy.nvimだと次のように書いてインストールできます。
return { "eetann/senpai.nvim", build = "bun install", dependencies = { "MunifTanjim/nui.nvim", "nvim-lua/plenary.nvim", "nvim-treesitter/nvim-treesitter", }, opts = {}}
bun install
、ちょっと時間かかります。履歴とかRAGの管理で必要なライブラリがあるんです。
lazy.nvimでの遅延読み込み
lazy.nvimでの遅延読み込みの例も載せておきます。
return { "eetann/senpai.nvim", build = "bun install", dependencies = { "MunifTanjim/nui.nvim", "nvim-lua/plenary.nvim", "nvim-treesitter/nvim-treesitter", }, keys = { { "<space>ss", "<Cmd>Senpai toggleChat<CR>" }, { "<space>sl", "<Cmd>Senpai promptLauncher<CR>" }, { "<space>sv", "<Cmd>Senpai transferToChat<CR>", mode = "v" }, }, cmd = { "Senpai" }, ft = "gitcommit", opts = {}}
設定の書き方
プラグインの設定はsetup
の中に書きます。
require("senpai").setup()
lazy.nvimの場合、setup
の中身はopts
に書きます。この書き方について知りたい人は別の記事「lazy.nvimの使い方から起動を爆速にする方法までを解説」を読んでください。
return { "eetann/senpai.nvim", -- 省略 opts = { -- ここに書く }}
対応しているLLM
現在対応しているのプロバイダーは次のとおりです。
名前 | API tokenの環境変数 |
---|---|
anthropic | ANTHROPIC_API_KEY |
deepseek | DEEPSEEK_API_KEY |
google | GOOGLE_GENERATIVE_AI_API_KEY |
openai | OPENAI_API_KEY |
openrouter | OPENROUTER_API_KEY |
デフォルトでどのプロバイダーを使うかはproviders.default
に書きます。
require("senpai").setup({ providers = { default = "openrouter", },})
各プロバイダーでのモデルの指定はmodel_id
に書きます。
require("senpai").setup({ providers = { default = "openrouter", openrouter = { model_id = "openai/chatgpt-4o-latest" }, },})
model_id
の書き方は次のリンクを参考にしてください。
主要な機能の紹介
機能を紹介していきます。詳しい使い方はREADMEかヘルプを読んでください。
チャット機能
:Senpai toggleChat
でチャットのウィンドウをトグルできます。

入力欄(下のウィンドウ)に入力したら<CR>
で送信です。
ファイル読み込み
ファイル名があればAIが判断して読み込みます。
たとえばfoo/bar/buz.txt
をbuz.txt
のように書いても反応します。
Git管理下のファイルから**/buz.txt
を探す、という実装になっています。ゆくゆくはプロジェクト毎に読み取り禁止とか承認を設定できるようにしたいところです。
ファイル編集
ファイル編集もできます。AIにファイル編集頼んだらReplace File
というブロックが表示されます。
このブロック内でa
を入力するとdiffが開きます。
diffはNeovimのdiffthis
を使っているので、do
やdp
といったキーマップでdiffを適用できます(ヘルプは:help copy-diffs
)。
キーマップ
?
でチャットのヘルプが開きます。キーマップをカスタマイズしたらこのヘルプにも反映されます。

ここでEnterを押すとそのキーを入力したときと同じ動作になります。
キーマップを設定していないやつも実行できます。
たとえばopen_api_doc
で、senpai.nvim開発者向けのOpenAPI(OpenAIではない)のUIが開きます。

senpai.nvimが内部で使っているAPIをここで試せます。
履歴機能
履歴は自動で保存されます。:Senpai 〇〇Save
みたいなコマンドを打つ必要はありません。
過去のチャットを復元したい場合、:Senpai loadThread
で選択UIが開きます。
snacks.nvimユーザーであれば、画像のようにシステムプロンプトとかモデルもプレビューに表示されます。
履歴から復元したらそのまま会話も継続できます。
AIとの会話を一過性のものにはしたくないので履歴機能のあるプラグインにしました。「せんぱああああい、この前話してた実装なんですけど〜」みたいなノリです。
MCP
流行りのMCPも使えます。チャットでの呼び出しはAIが勝手に考えてくれます。
「このタイミングで呼び出さなくても……」ということはあるので、いずれメンションでの呼び出し(@foo
みたいな)機能でオンオフできるようにしたいところです。
mcp.servers
にこんな感じで設定します。
require("senpai").setup({ mcp = { servers = { sequential = { command = "bunx", args = { "-y", "@modelcontextprotocol/server-sequential-thinking" }, }, mastra = { command = "bunx", args = { "-y", "@mastra/mcp-docs-server" } }, }, },})
bunx
というのはnpx
のBun版です。npxより速いです。
server-sequential-thinking
などは数回ツールを呼び出す都合で、一度のメッセージだけでは処理しきれないことがあります。その場合は「続きをお願いします」みたいに会話すればOKです。
RAG
RAGも使えます。URL以外はまだ対応していません。
チャットの入力欄にてgR
を打つと、URL入力欄が表示されます。
URLを入力したらfetchして内部のDBに保存されます。MCP同様、チャットでの呼び出しはAIが勝手に考えてくれます。
設定の可視化
AI系のプラグインで設定していると、「これ本当に反映されたのかな?」と思うことがあります。たとえばプロバイダーをvim.env.OPENAI_API_KEY and "openai" or "openrouter"
のように動的に設定している場合です。
senpai.nvimではいくつかの設定を可視化できます。
現在チャットに紐づくLLMプロバイダー・モデル名はチャットのトップに表示されます。
設定したシステムプロンプトはヘルプ?
のshow_system_prompt
、MCPのツール設定はshow_mcp_tools
から確認できます。
プロンプトのカスタマイズ
どのチャットでも共通のシステムプロンプトを設定したい場合、設定のchat.system_prompt
に書きます。
require("senpai").setup({ chat = { system_prompt = "Answers should be in Japanese." }})
システムプロンプトは別に英語以外で書いてもかまいません。
カスタマイズしたプロンプトを使い分けたい場合、prompt_launchers
に書きます。
require("senpai").setup({ prompt_launchers = { ["Tsundere"] = { system = "Answers should be tsundere style.", priority = 100, }, ["test message"] = { user = "test message. Hello!", }, },})
ここで書いたやつは:Senpai promptLauncher
で一覧として表示されます。選んだやつがチャットで開きます。
実際に筆者がこの記事の構成を考えるときに使ったpromptLauncherを載せておきます(記事自体は頑張って25歳の人間が書いてます!)。
コミットメッセージの自動生成
:Senpai commitMessage
でコミットメッセージを生成できます。.git/COMMIT_EDITMSG
を開いたときに実行してみてください。いわゆるConventional Commits形式で書いてくれます。
この機能を作ってから、senpai.nvimのコミットメッセージの大半はこの機能で書かせてます(実例:eetann/senpai.nvim@b865dcf)。
言語指定も可能です。
:Senpai commitMessage Japanese
プロンプトに渡すだけなので厳密な言語名じゃなくてもかまいません。
:Senpai commitMessage English(Tsundere)
筆者は英語と日本語を使い分けたいので、次のようにキーマップを設定しています。.config/nvim/after/ftplugin/gitcommit.lua
.
vim.keymap.set("n", "<C-g><C-g>", function() if vim.env.COMMIT_MESSAGE_ENGLISH == "1" then vim.cmd("Senpai commitMessage English") else vim.cmd("Senpai commitMessage Japanese") endend, { buffer = true, desc = "Senpai commitMessage" })
環境変数COMMIT_MESSAGE_ENGLISH
が1なら英語、それ以外は日本語にしています。リポジトリ毎の環境変数の設定にはmiseを使ってます。
以上、自作AIプラグインsenpai.nvimの紹介でした。動画で所々senpai
(先輩)をsenapi
(せなぴ)とtypoしていますが、現在は修正済みです。純粋に無能でした。
まだ1か月くらいしか経っていないひよっこプラグインです。速度面とかパフォーマンスは改善していきたいです。進捗はvim-jpのSlackの#times-eetann
か@eetann092でウォッチできます。
他にもNeovimの記事を書いてます。よかったらどうぞ。最近のイチオシは:=
について書いている記事です。