はじめに
ここ数か月、Neovim にハマっています。
LazyVim のような「最初から全部そろった設定」は使わず、素の Neovim に lazy.nvim だけを入れて、必要になったものを 1 つずつ足していく形で育ててきました。その設定づくりのほとんどを、Claude Code に相談しながら進めています。
そうやって Claude Code を毎日使っていると、だんだんサブエージェントを何本も並べて仕事をさせる場面が増えてきました。便利なのですが、ターミナルに流れるログだけでは、次のことが追いにくくなってきました。
- 今どのエージェントが動いていて、どれが終わったのか
- 親がなぜその仕事を子に任せたのか
- 子が何をして、どう報告したのか
- どこで自分の答え待ちになっているのか
そこで、Neovim から出ずに、エージェントの動きを図で見られるプラグインを作りました。もちろん、これも Claude Code と一緒に作っています。
作ったもの:agentmap.nvim
上の動画は、作り物の記録を再生して撮ったものです。
できること
| 機能 | 中身 |
|---|---|
| 流れの図 | 親 → 子 → 孫のエージェントを、START → 段 → END の図で表示します。動いている間も自動で更新されます |
| 任せた理由・作業の経過・報告 | 子の箱を開くと「親がなぜ任せたか」「子が作業中に書いた一言と使ったツール」「最後の報告」が読めます |
| HUMAN CHECK | Claude が選択肢つきの質問(AskUserQuestion)をしてくると、図に確認待ちの箱が出ます。答え待ちは紫、答えたら緑です |
| レビューと差し戻し | 子の成果に PASS / RETRY / ESCALATE を付けて、差し戻しの履歴を残せます |
| 書き出し | 実行の記録を Markdown / HTML / PDF に書き出せます。HTML は外部の道具なしで作れます |
| 日本語の画面 | 既定は英語ですが、opts = { lang = "ja" } で日本語になります |
色が見えない環境でも分かるように、状態は [RUNNING] [WAITING] [DONE] のように文字でも出しています。
しくみ
Claude Code には hooks という、「エージェントが始まった」「ツールを使った」「終わった」などのタイミングで外のプログラムを呼ぶ仕組みがあります。agentmap.nvim はこれを使って、小さな記録係(Python の標準部品だけで書いたもの)に 1 行ずつ記録を書かせています。
Claude Code ── hooks ──▶ 記録係(Python)──▶ hooks.jsonl(1 行 1 出来事)
│
▼
Neovim(:AgentMap)が読んで図にする
- 記録係は何も表示せず、失敗しても Claude Code の動きには影響しません
- Neovim は記録を読むだけなので、Claude Code が動いている間に開いていなくても、あとから見られます
- 保存するのは作業名・時刻・ツール名・ファイル名・文面の冒頭などの要点だけで、鍵やパスワードらしき文字は
***に伏せてから保存します
入れ方
lazy.nvim の場合です。
{
"ayame0328/agentmap.nvim",
lazy = false,
opts = { lang = "ja" },
keys = {
{ "<leader>aa", "<Cmd>AgentMap<CR>", desc = "AgentMap: 図を開く" },
{ "<leader>ar", "<Cmd>AgentMapRuns<CR>", desc = "AgentMap: 過去の実行" },
{ "<leader>ae", "<Cmd>AgentMapExport<CR>", desc = "AgentMap: 書き出し" },
},
}
入れたら、1 回だけ次を行います。
-
:AgentMapInstallHooks… Claude Code のsettings.jsonに hooks を足します。足す内容を差分で見せてから聞いてくるので、勝手には書き換えません。元のファイルの控えも残ります -
:checkhealth agentmap… Neovim・Python・hooks・記録の保存先などをまとめて確かめます - Claude Code を起動し直すと、そのセッションから記録されます
必要なものは Neovim 0.10 以上、Python 3、Claude Code です。Windows に直接入れた Neovim は、まだ試験的な扱いです。
Claude Code を持っていなくても、同梱の再生用データで上の動画と同じ動きを試せます(手順は README にあります)。
「なぜ任せたか」を読むための、書き方の決まり
エージェントが頭の中で考えた部分は、記録の中では空になっていて読めません。理由や報告が見えるのは、AI が文章として書いたときだけです。
そこで、CLAUDE.md に「任せるときはこう書く」「報告はこう返す」という決まりを書いておき、agentmap.nvim はその見出しを機械的に読むようにしました。
【目的】何のためにやるか
【任せる理由】なぜ自分でやらず任せるか
【期待する結果】何が返ってくれば完了か
子の報告は ## 報告(やったこと/方向/理由/残った課題)、人に確かめないと進めないときは ## 要確認 の形で返してもらいます。英語の [Goal] ## Report なども同じように読めます。決まりが守られていない項目は「(書かれていません)」と出すだけで、推測で埋めることはしません。
実際に試して分かったのですが、子エージェントは AskUserQuestion を使えません。なので「子が『要確認』を書いて止まる → 親がそれを受けて質問する」という流れにして、図ではその子の後ろに確認待ちの箱を出しています。
Claude Code と一緒に作ってみて
作り方
コードはほぼ Claude Code に書いてもらいました。ただ、丸投げではなく、次のような分担にしています。
- 設計:1 つのエージェントに、データの持ち方や画面の配置をまとめた設計書を書かせる
- 実装:触るファイルが重ならないように分けて、作業者のエージェントを最大 3 つ同時に動かす
- レビュー:作った本人とは別のエージェントに点検させる
- 最終確認:さらに別のエージェントに、本物の Claude Code を動かして通しで確かめさせる
自分の役目は、「どちらにするか」を決めることです。Claude Code が選択肢を出して聞いてくるので、それに答えていきました。名前、ライセンス、どこまで公開するか、なども全部この形で決めています。
レビューと最終確認を別のエージェントに任せたのは、かなり効きました。たとえば最終確認では、README に書いた lazy.nvim の書き方のままだと、キーを押すまでプラグインが読み込まれず、:AgentMapInstallHooks が使えないことが見つかりました。初めて入れる人が最初につまずく所だったので、公開前に気づけて助かりました。
つまずいたこと
-
hooks の項目名は、実物で確かめないと危ない
hooks で受け取る項目について、ドキュメントを要約させたエージェントの答えに誤りが 2 つありました(結果の欄の名前と、実際には無い欄)。そこからは、本物の Claude Code を動かして記録を採取し、その実物だけを使うようにしました -
「待たせない」hooks は、終了の記録を落とす
ほとんどの hooks は Claude Code を待たせない形で登録していますが、それだと終了の記録(StopとSessionEnd)が、Claude Code の終了と同時に消えてしまいました。この 2 つだけ待たせる形にしています(数ミリ秒です) -
公開前の個人情報の掃除
自分の設定の中で育てたものを切り出したので、試験用のデータに自分の家フォルダのパスや、試しに動かした会話の ID が残っていました。作り物の値に置き換え、過去の記録(git の履歴)も持ち込まない新しいリポジトリにしてから公開しました
試験は 32 本あり、GitHub Actions で Linux と macOS の上で自動で回しています。
今後
- Codex への対応
- 書き方の決まりの見出しを、自分で決められるようにする
- 古い記録の自動の片付け
- Windows に直接入れた Neovim を、試験的な扱いから正式な対応へ
おわりに
Neovim を触り始めたころは、自分がプラグインを公開するとは思っていませんでした。Claude Code と相談しながら設定を育てていくうちに、「こういうのが欲しい」を形にできるところまで来られたのは、正直うれしいです。
使ってみた感想や「ここが分かりにくい」などあれば、Issue やコメントで気軽にもらえるとうれしいです。
