Claude Code / Codex Hooks と nvim --server で作る terminal-native IDE
1. はじめに
こんにちは、Algomatic エンジニアの末國です!
『Algomatic 初夏のアドベントカレンダー』と題して、メンバーそれぞれが好きな技術を好きに語る会の 18 日目です。
昨日の記事は「gog と Codex で Google スライドを作る」でした。
今日は Neovim と Coding Agent を同時に使う際に役立つ Tips をお届けします!
私は普段、tmux で分割した左ペインに Neovim を、右側に Codex/Claude Code を開いて開発を行っています。Agent が次々とファイルを編集しているのに、エディタ側には変更が反映されず「今どこを直してるの?」となります。
以前の記事で AI に「編集したら Neovim で開いて」と頼む方式を紹介しましたが、コンテキストが長くなると忘れられるし、このやり取り自体にトークンを消費します。そこで、今回は Hooks を使って Neovim を自動追従させる方法を紹介します。
この記事の内容を取り入れることで「Agent の編集がリアルタイムで Neovim に表示される」」「Agent が Neovim を直接操作できる」環境が構築できます。ぜひ最後までご覧ください。
imageClaude Code の編集箇所が自動的に Neovim で開かれる様子
2. 全体像
image全体像
tmux の 1 つの window に、左ペインの Neovim と右ペインの AI Agent(Claude Code / Codex)があります。Agent が tool を実行するたびに hook が発火し、薄い中継スクリプト(helper)経由で nvim --server を叩いて Neovim を追従させます。さらに同じ socket で逆方向(Agent が Neovim の状態を読む)にも広げています。この仕組み全体をAgent followと呼んでいます。
3. できること
編集の自動追従
Agent がファイルを編集すると、Neovim が自動的にそのファイルの変更箇所を開きます。編集前のタイミングでは変更箇所にカーソルをジャンプさせ、編集後には変更されたファイルをバッファに読み込みます。Agent の作業を目で追いながら、必要があればすぐに手を入れられます。
ON/OFF の切り替え
Agent が連続で多くのファイルを編集すると、Neovim のバッファが次々に切り替わって今読んでいる箇所を追えなくなります。そのため、tmux window 単位で Agent follow の ON/OFF を切り替えられるようにしています。
Neovim側からは<leader>ta で toggle するキーマップを設定し、statusline に Agent:ON / Agent:OFF を表示しています。
逆方向:Agent が Neovim を読む
追従とは逆に、同じ socket を使って Agent が Neovim の状態を読むこともできます。
たとえば Agent に「今開いているファイルの diagnostics(診断情報)を確認して」と頼むと、helper 経由で buffer / cursor / LSP diagnostics を取得し、それをもとにコードを修正できます。
静的解析の結果を知る目的であれば別に Neovim の LSP を経由する必要はないのですが、Neovim 自体やプラグインの挙動が不安定な時の調査にもとても便利です。
4. 仕組み
ここからは Agent follow がどう動いているかを、データフローに沿って説明します。
hook:編集を検知する
Claude Code の Hooks で 2 種類設定します。
編集前ジャンプ(PreToolUse)
対象: Edit, MultiEdit
Agent がこれからファイルを編集しようとしたとき、変更箇所に Neovim のカーソルを移動させます。
hook の stdin には tool_input.file_path と tool_input.old_string(変更前テキスト)が含まれます。編集前のタイミングなので、old_string はまだファイル内にそのまま残っています。hook はこの情報を helper に渡し、helper が old_string の先頭行をファイル内で検索して該当行にジャンプさせます。
編集後オープン(PostToolUse)
対象: Edit, MultiEdit, Write
Agent が編集を完了したあと、hook が stdin の tool_input.file_path を helper に渡し、変更されたファイルを Neovim で開きます。
helper:agent の違いを吸収する
hook から直接 nvim --server を叩くのではなく、間に薄い helper script を置いています。やることは 2 つで、ファイルを Neovim で開くことと、検索文字列や行番号から該当行にジャンプさせることです。
helper は socket path の計算、socket の存在確認、Agent follow の ON/OFF チェック、nvim --server の呼び出しまでを担います。
Claude Code の hook payload は構造が安定しており、tool_input.file_path と tool_input.old_string を取り出すだけで済みます。
一方、Codex は apply_patch という独自形式のパッチを使います。payload 構造も異なるため、専用の parser でパッチ内の変更ブロックを解析し、変更後の行番号を特定します。
入口は agent ごとに分かれますが、最終的に同じ helper に集約されます。agent が増えても、入口の parser を書けば同じ追従の仕組みに載せられます。
socket:Neovim との接点
Neovim は--listen オプションで Unix socket を開けます。plugin 不要です。
nvim --listen /tmp/nvim_myproject.sock
このソケットに対して、外部プロセスから--remote-send(:e +行番号 ファイルのようなキーストロークを送る)や--remote-silent(ファイルパスを渡して開く)を送ることができます。
socket path を固定にすると、複数プロジェクトや複数ウィンドウで誤接続するので、次の形で計算します。
/tmp/nvim_<repo-name>_<repo-root-hash>_<tmux-window-id>.sock
それぞれの要素を含める理由は次の通りです。
- repo name + hash を含める: 別プロジェクトの Neovim に接続しないため。hash を付けるのは、同名の repo を別パスで開いた場合の衝突を防ぐため
- tmux window id を含める: 同じプロジェクトでも、別ウィンドウで開いている Neovim と混ざらないため
結果として、「エージェントが動いている tmux ウィンドウ」と「そのウィンドウで起動した Neovim)」が 1 対 1 で対応します。
このソケットを作るのは Neovim の起動時です。普段の nvim コマンドの代わりに、socket path の計算と--listen の付与を行う薄いラッパースクリプトを作っておきます。フック側も同じ命名規則で socket path を計算することで、正しい Neovim に接続できます。既存のソケットが残っている場合は生存確認を行い、stale(古くなった)なら削除して起動し直します。
ON/OFF の状態管理
状態は~/.local/state/nvim/agent_follow_disabled_<tmux-window-id>というファイルの有無で管理します。このファイルがあれば OFF です。フックとヘルパーの先頭でこれをチェックし、OFF なら即座に何もせず終了します。
5. まとめ
実装の具体は載せていませんが、この記事で説明した構成(ソケットの命名規則、フックの種類と対象ツール、ヘルパーの責務分担)を設計図として AI エージェントに渡せば、同等の仕組みを作れるはずです。部品は小さく、shell スクリプトが中心なので、自分の環境に合わせてカスタマイズしやすいと思います。
ここまで読んでいただきありがとうございました。
もし少しでもご興味をお持ちいただけましたら、カジュアル面談に足を運んでいただけるとうれしいです!
原文を表示
1. はじめに
こんにちは、Algomaticエンジニアの末國です!
『Algomatic 初夏のアドベントカレンダー』と題して、メンバーそれぞれが好きな技術を好きに語る会の18日目です。
昨日の記事は「gogとCodexでGoogleスライドを作る」でした。
今日はNeovimとCoding Agentを同時に使う際に役だつTipsをお届けします!
私は普段、tmuxで分割した左paneにNeovimを、右側にCodex/Claude Codeを開いて開発を行っています。Agentが次々とファイルを編集しているのに、エディタ側には変更が反映されず「今どこを直してるの?」となります。
以前の記事でAIに「編集したらNeovimで開いて」と頼む方式を紹介しましたが、コンテキストが長くなると忘れられるし、このやり取り自体にトークンを消費します。そこで、今回はHooksを使ってNeovimを自動追従させる方法を紹介します。
この記事の内容を取り入れることで「Agentの編集がリアルタイムでNeovimに表示される」「AgentがNeovimを直接操作できる」環境が構築できます。ぜひ最後までご覧ください。

2. 全体像

tmuxの1つのwindowに、左ペインのNeovimと右ペインのAI Agent(Claude Code / Codex)があります。Agentがtoolを実行するたびにhookが発火し、薄い中継スクリプト(helper)経由でnvim --serverを叩いてNeovimを追従させます。さらに同じsocketで逆方向(AgentがNeovimの状態を読む)にも広げています。この仕組み全体をAgent followと呼んでいます。
3. できること
編集の自動追従
Agentがファイルを編集すると、Neovimが自動的にそのファイルの変更箇所を開きます。編集前のタイミングでは変更箇所にカーソルをジャンプさせ、編集後には変更されたファイルをバッファに読み込みます。Agentの作業を目で追いながら、必要があればすぐに手を入れられます。
ON/OFFの切り替え
Agentが連続で多くのファイルを編集すると、Neovimのバッファが次々に切り替わって今読んでいる箇所を追えなくなります。そのため、tmux window単位でAgent followのON/OFFを切り替えられるようにしています。
Neovim側からは<leader>taでtoggleするキーマップを設定し、statuslineにAgent:ON / Agent:OFFを表示しています。
逆方向:AgentがNeovimを読む
追従とは逆に、同じsocketを使ってAgentがNeovimの状態を読むこともできます。
たとえばAgentに「今開いているファイルのdiagnosticsを確認して」と頼むと、helper経由でbuffer / cursor / LSP diagnosticsを取得し、それをもとにコードを修正できます。
静的解析の結果を知る目的であれば別にNeovimのLSPを経由する必要はないのですが、Neovim自体やプラグインの挙動が不安定な時の調査にもとても便利です。
4. 仕組み
ここからはAgent followがどう動いているかを、データフローに沿って説明します。
hook:編集を検知する
Claude CodeのHooksで2種類設定します。
編集前ジャンプ(PreToolUse)
対象: Edit, MultiEdit
Agentがこれからファイルを編集しようとしたとき、変更箇所にNeovimのカーソルを移動させます。
hookのstdinにはtool_input.file_pathとtool_input.old_string(変更前テキスト)が含まれます。編集前のタイミングなので、old_stringはまだファイル内にそのまま残っています。hookはこの情報をhelperに渡し、helperがold_stringの先頭行をファイル内で検索して該当行にジャンプさせます。
編集後オープン(PostToolUse)
対象: Edit, MultiEdit, Write
Agentが編集を完了したあと、hookがstdinのtool_input.file_pathをhelperに渡し、変更されたファイルをNeovimで開きます。
helper:agentの違いを吸収する
hookから直接nvim --serverを叩くのではなく、間に薄いhelper scriptを置いています。やることは2つで、ファイルをNeovimで開くことと、検索文字列や行番号から該当行にジャンプさせることです。
helperはsocket pathの計算、socketの存在確認、Agent followのON/OFFチェック、nvim --serverの呼び出しまでを担います。
Claude Codeのhook payloadは構造が安定しており、tool_input.file_pathとtool_input.old_stringを取り出すだけで済みます。
一方、Codexはapply_patchという独自形式のパッチを使います。payload構造も異なるため、専用のparserでパッチ内の変更ブロックを解析し、変更後の行番号を特定します。
入口はagentごとに分かれますが、最終的に同じhelperに集約されます。agentが増えても、入口のparserを書けば同じ追従の仕組みに載せられます。
socket:Neovimとの接点
Neovimは--listenオプションでUnix socketを開けます。plugin不要です。
nvim --listen /tmp/nvim_myproject.sockこのsocketに対して、外部プロセスから--remote-send(:e +行番号 ファイルのようなキーストロークを送る)や--remote-silent(ファイルパスを渡して開く)を送ることができます。
socket pathを固定にすると、複数プロジェクトや複数windowで誤接続するので、次の形で計算します。
/tmp/nvim_<repo-name>_<repo-root-hash>_<tmux-window-id>.sockそれぞれの要素を含める理由は次の通りです。
- repo name + hashを含める: 別プロジェクトのNeovimに接続しないため。hashを付けるのは、同名のrepoを別パスで開いた場合の衝突を防ぐため
- tmux window idを含める: 同じプロジェクトでも、別windowで開いているNeovimと混ざらないため
結果として、「Agentが動いているtmux window」と「そのwindowで起動したNeovim」が1対1で対応します。
このsocketを作るのはNeovimの起動時です。普段のnvimコマンドの代わりに、socket pathの計算と--listenの付与を行う薄いwrapper scriptを作っておきます。hook側も同じ命名規則でsocket pathを計算することで、正しいNeovimに接続できます。既存のsocketが残っている場合は生存確認を行い、staleなら削除して起動し直します。
ON/OFFの状態管理
状態は~/.local/state/nvim/agent_follow_disabled_<tmux-window-id>というファイルの有無で管理します。このファイルがあればOFFです。hookとhelperの先頭でこれをチェックし、OFFなら即座に何もせず終了します。
5. まとめ
実装の具体は載せていませんが、この記事で説明した構成(socketの命名規則、hookの種類と対象tool、helperの責務分担)を設計図としてAI Agentに渡せば、同等の仕組みを作れるはずです。部品は小さく、shell scriptが中心なので、自分の環境に合わせてカスタマイズしやすいと思います。
ここまで読んでいただきありがとうございました。
もし少しでもご興味をお持ちいただけましたら、カジュアル面談に足を運んでいただけるとうれしいです!
関連記事
Algomatic がノーコード環境「LeLab」で模倣学習を開始
Algomatic のエンジニアである Yusuke 氏が、低コストロボットアーム SO-101 を用いたシミュレーションと実機実験を通じて、同社が提供するノーコードプラットフォーム「LeLab」での模倣学習の取り組みを紹介している。
gogとCodexでGoogleスライドを作る
AI生成コードを保守するために、開発を「水彩」と「油絵」で分ける
今日のまとめ
AI日報で今日の重要ニュースをまとめ読み