🤖

Claude CodeのプロンプトをNeovimで快適に書く

に公開
更新履歴

2025-01-24

  • 拡張子を .md から .claude に変更: 通常のMarkdownファイル編集時に @ キーバインドが干渉しなくなりました。シンタックスハイライトなしで起動するため高速です
  • ファイル選択後にスペースを追加: @ファイルパス の後にスペースが自動で入るようになりました
  • 初期クエリ機能を追加: カーソル後にファイル名らしき文字列があると、それを fzf の初期検索クエリとして使います
  • nvimをINSERTモードで開始するようにしました

デモ

はじめに

Claude Codeはターミナルで動くAIアシスタントですが、複雑なプロンプトを1行の入力欄で書くのは大変です。日本語入力との相性が悪く、インライン変換ができない問題もあります。

Ctrl-g でエディタを起動する機能もありますが、起動中はやり取りログが隠れてしまい、ログを参照しながら編集することができません。[1]

そこで、Alt-e を押すとNeovimが立ち上がり、編集して保存・終了するとClaude Codeに入力される仕組みを作りました。Neovimの中で @ を押すとファイルパスを補完できるので、ファイルを参照するプロンプトも簡単に書けます。

必要なもの

仕組み

zellijのキーバインドでフローティングウィンドウを開き、その中でNeovimを起動します。編集が終わると、内容を元のペイン(Claude Code)に送信します。

Alt-e → zellij floating window → Neovim起動 → 編集 → 保存終了 → 元のペインに流し込み

設定

1. シェルスクリプト

~/.config/nvim/claude-prompt-edit.sh として保存します。

#!/bin/bash
# /tmp に一時ファイルを作成($$ はプロセスIDで、ファイル名の衝突を防ぐ)
# .claude 拡張子にすることで、Neovim 側で専用の設定を適用できる
TMPFILE="/tmp/claude-prompt-$$.claude"

# エディタで編集(インサートモードで開始、終了まで待つ)
nvim -c "startinsert" "$TMPFILE"

# 内容を読んで元のペインに送る
if [ -s "$TMPFILE" ]; then
    # 内容を読み取る
    CONTENT=$(cat "$TMPFILE")

    # フローティングを閉じてからテキストを送る
    zellij action toggle-floating-panes
    sleep 0.1

    # 内容を直接流し込む
    zellij action write-chars "$CONTENT"
fi

# ファイルを削除
rm -f "$TMPFILE"

実行権限を付けるのを忘れずに:

chmod +x ~/.config/nvim/claude-prompt-edit.sh

2. zellijの設定

~/.config/zellij/config.kdl に以下を追加します。

keybinds {
    shared_except "locked" {
        bind "Alt e" {
            Run "bash" "-c" "~/.config/nvim/claude-prompt-edit.sh" {
                floating true
                close_on_exit true
            }
        }
    }
}

3. Neovimの設定

.claude ファイルで @ を押すとfzf-luaでファイル補完ができるようにします。Claude Codeでは @ファイルパス でファイルを参照できるため、この設定があると便利です。

.claude という専用の拡張子を使うことで、通常のMarkdownファイル編集時には @ が通常通り入力されます。また、シンタックスハイライトがないプレーンテキストとして開くため、起動が高速です。

init.lua に追加:

-- .claude ファイルで @ を押すと fzf-lua でファイル補完を発動
-- Claude Code では @ファイルパス でファイルを参照できるため、この設定があると便利
-- 素の @ を入力するには <C-v>@ またはキャンセル (Esc)
vim.api.nvim_create_autocmd({ "BufRead", "BufNewFile" }, {
  pattern = "*.claude",
  callback = function()
    vim.keymap.set("i", "@", function()
      local fzf = require("fzf-lua")
      local selected_path = nil

      -- カーソル後の単語を fzf の初期クエリにする
      -- 例: "readme.md を見て" の readme.md の前で @ を押すと、readme.md で検索開始
      local line = vim.api.nvim_get_current_line()
      local col = vim.api.nvim_win_get_cursor(0)[2]
      local after_cursor = line:sub(col + 1)
      local initial_query = after_cursor:match("^(%S+)") or ""

      fzf.files({
        file_icons = false,
        git_icons = false,
        query = initial_query,
        actions = {
          -- ファイル選択時にパスを保存
          ["default"] = function(selected)
            if selected and selected[1] then
              selected_path = fzf.path.entry_to_file(selected[1]).path
            end
          end,
        },
        winopts = {
          -- fzf 終了時(選択 or キャンセル)に呼ばれる
          on_close = function()
            vim.schedule(function()
              if selected_path then
                -- 初期クエリとして使った文字列を削除
                if initial_query ~= "" then
                  local row, cur_col = unpack(vim.api.nvim_win_get_cursor(0))
                  local cur_line = vim.api.nvim_get_current_line()
                  local new_line = cur_line:sub(1, cur_col) .. cur_line:sub(cur_col + 1 + #initial_query)
                  vim.api.nvim_set_current_line(new_line)
                end
                vim.api.nvim_put({ "@" .. selected_path .. " " }, "", false, true)
              else
                -- キャンセル時は @ のみ(初期クエリは残す)
                vim.api.nvim_put({ "@" }, "", false, true)
              end

              -- インサートモードに戻る
              vim.defer_fn(function()
                vim.cmd("startinsert!")
              end, 10)
            end)
          end,
        },
      })
    end, { buffer = true, noremap = true })
  end,
})

使い方

  1. zellijでClaude Codeを起動
  2. Alt-e を押す
  3. フローティングウィンドウでNeovimが開く
  4. プロンプトを書く(@ でファイルパス補完)
  5. :wq で保存して終了
  6. 書いた内容がClaude Codeの入力欄に流し込まれる

動作の様子
Alt-eでNeovimが開き、編集した内容がClaude Codeに流し込まれる

素の @ を入力したいときは、<C-v>@ で入力するか、fzf-luaをEscでキャンセルすれば @ だけが入力されます。

おわりに

この仕組みにより、以下のメリットが得られます。

  • Vimのキーバインドで快適に編集できる
  • 日本語入力が正常に動作する
  • ファイルパスの補完が使える
  • 複数行のプロンプトを見やすく書ける

zellijのfloating paneとNeovimの組み合わせは、Claude Code以外のターミナルツールにも応用できそうです。

脚注
  1. この問題に対する issue を作りましたので、よろしければ upvote してください。 ↩︎

Discussion