Claude CodeのCLIからghq+fzfでリポジトリを選択する(tmux / zellij対応)

Tips

はじめに

前回の記事では、Claude Codeを起動する前にシェル関数でリポジトリを選択して--add-dirフラグに渡す方法を紹介しました。 ただ、この方法はClaude Codeのセッションをすでに開いている状態では使いにくく、セッション途中で参照先を追加したい場合は手動で/add-dirを入力する必要がありました。

Claude Codeのインタラクティブセッションでは!記法でシェルコマンドを呼び出せます。 ここにスクリプトを組み込めば、セッション中からでもfzfを使ってリポジトリを選択し、/add-dirコマンドをそのままセッションに流し込めます。

ただし、Claude Codeのセッション内から!でfzfを直接起動しようとすると、TTYをうまく扱えず動作しません。 tmuxのポップアップウィンドウやzellijのフローティングペインを経由することでこの問題を解決できます。

今回は~/.local/bin/ghq-fzfとして実行ファイルを作成し、tmux・zellij両対応のスクリプトを整備する手順を紹介します。

仕組み

! ghq-fzfを実行したとき、以下の流れで動作します。

  1. 環境変数を見てtmuxまたはzellijのどちらで動いているかを判定する
  2. tmuxの場合: tmux display-popup -Eでポップアップウィンドウを開いてfzfを起動して選択結果を受け取る
  3. zellijの場合: フローティングペインでfzfを起動して選択結果を受け取る
  4. 選択したパスを/add-dir <path>としてClaude Codeのセッションに書き込む
  5. Claude Codeが/add-dirコマンドを受け取り、対象ディレクトリをコンテキストに追加する

使用環境

ツール 確認バージョン
Claude Code v2.1.128
ghq 1.8.0
fzf 0.67.0
tmux 3.6a(display-popup対応版)
zellij 0.44.1
シェル zsh / bash

スクリプトの作成

~/.local/bin/ghq-fzfを以下の内容で作成します。

#!/usr/bin/env bash
set -euo pipefail

# tmux環境の場合
if [ -n "${TMUX:-}" ]; then
  # 現在のペインIDを取得する(コマンド送信先として使用する)
  current_pane=$TMUX_PANE

  # display-popup内でfzfを起動し、選択されたパスを直接send-keysで送信する
  tmux display-popup -E -w 80% -h 80% \
    "ghq list --full-path | fzf --prompt='参照リポジトリを選択: ' \
      | xargs -I{} tmux send-keys -t ${current_pane} '/add-dir {}' Enter" || true

# zellij環境の場合
elif [ -n "${ZELLIJ_PANE_ID:-}" ]; then
  current_pane=$ZELLIJ_PANE_ID

  # フローティングペイン内でfzfを起動し、選択されたパスを直接write-charsで送信する
  zellij run --floating --close-on-exit -- sh -c \
    "dir=\$(ghq list --full-path | fzf --prompt='参照リポジトリを選択: ') && \
     [ -n \"\$dir\" ] && zellij action write-chars --pane-id ${current_pane} \"\$(printf '/add-dir %s\n' \"\$dir\")\" && zellij action send-keys --pane-id ${current_pane} Enter" || true

else
  echo "エラー: tmux または zellij 環境が必要です。" >&2
  exit 1
fi

作成後、実行権限を付与します。

chmod +x ~/.local/bin/ghq-fzf

~/.local/binがPATHに含まれていない場合は、シェルの設定ファイルに以下を追加します。

export PATH="$HOME/.local/bin:$PATH"

使い方

Claude Codeのセッション内から以下のように呼び出します。

! ghq-fzf

tmuxのポップアップウィンドウ(またはzellijのフローティングペイン)にfzfの選択画面が表示されます。 リポジトリを選択してEnterで確定すると、Claude Codeのセッションに/add-dir <path>が自動で入力されます。

注意:/add-dirは1回につき1ディレクトリのみ追加できます。複数リポジトリを追加したい場合はghq-fzfを繰り返し実行してください。

追加されたディレクトリは/permissionsコマンドのWorkspaceタブで確認できます。

デモ

筆者の環境での動作デモです。

Tmuxの場合

ghq-fzfの動作デモ tmuxの場合
ghq-fzfの動作デモ tmuxの場合

Zellijの場合

ghq-fzfの動作デモ zellijの場合
ghq-fzfの動作デモ zellijの場合

tmux display-popupについて

tmux display-popupはtmux 3.2から利用できる機能で、現在のペインの上にフローティングウィンドウを表示します。 -Eオプションを付けると、内部で実行したコマンドが終了した時点でポップアップが自動的に閉じます。

ポイントは、ポップアップ内で実行するシェルコマンド自身がtmux send-keysを呼ぶことです。 ${current_pane}は外側のスクリプトで展開されて実際のペインIDになり、\$dirはエスケープされてポップアップ内シェルで展開されます。 これにより一時ファイルやFIFOを経由せず、fzfの出力を直接元のペインへ流し込めます。

ユーザーがEscapeでキャンセルした場合にfzfが非ゼロで終了しても、|| trueによってスクリプトが異常終了しないよう対処しています。

-w 80% -h 80%でポップアップのサイズを画面の80%に設定しています。サイズは好みに応じて変更してください。

zellijのフローティングペインについて

zellijではzellij run --floating --close-on-exit -- <コマンド>でフローティングペインを起動できます。 --close-on-exitを付けることで、コマンドが終了した時点でペインが自動的に閉じます。

tmuxと同じように、フローティングペイン内のコマンドから直接zellij action write-charsを呼び出すことでFIFOを不要にできます。 ${current_pane}は外側のスクリプトで展開されて実際のペインIDになり、\$dir\$(...)はフローティングペイン内のシェルで展開されます。 fzfをEscapeでキャンセルした場合は[ -n "$dir" ]が失敗するため、write-charsは呼ばれません。 || trueによりスクリプト全体が異常終了するのも防いでいます。

まとめ

~/.local/bin/ghq-fzfを作成してClaude Codeの!記法から呼び出すことで、セッション内からfzfを使ってリポジトリをインタラクティブに選択し、/add-dirをワンステップで実行できるようになります。 tmuxのポップアップとzellijのフローティングペインを活用することでTTYの問題を回避しつつ、快適な操作感を実現しています。 実際に使ってみると、セッションを中断せずにリポジトリを追加できるのは思っていた以上に快適でした。 前回紹介したシェル関数(Claude Code起動前にシェル関数でリポジトリを選択して--add-dirフラグに渡す方法)と組み合わせることで、Claude Codeの起動前・起動後どちらのタイミングでもリポジトリを柔軟に追加できる環境が整います。 リポジトリをまたいだ開発をされる方はぜひ試してみてください。

コメント

タイトルとURLをコピーしました