Claude Codeに zellij / cmux を操作させて疑似マルチエージェントをする
こんにちは、小笠原みつき(@yamitzky)です。
Claude Code から zellij と cmux を操作するスキルを作ったので共有します。
zellij や cmux とは
簡単に紹介しておくと、zellij は tmux のようなターミナルマルチプレクサです。フローティングペインを作れたり、キーバインドが手に馴染んでおり、愛用しています。zellij は CLI からの操作(タブを作ったり、出力内容を見たり)が充実しています。
そして cmux は Ghostty ベースのターミナルアプリの一つです。こちらも zellij 同様、タブやペインを作ったりもできますし、タブを作ったり出力内容を見たりといった操作が CLI 経由でできます。
zellij は tmux 的なもの、cmux は Terminal.app 的なもの...ということでレイヤーの異なる2者ですが、どちらもタブやペインが作れて CLI から操作できるということで、私は似たような使い方をしています。
※ zellij と cmux ではタブやペインの概念の名称が異なります。zellij のペインは cmux では surface と呼びますが、以下ではペインと呼びます。
作ったスキル
zellij を操作する Agent Skill と cmux を操作する Agent Skill の2つを作りました。具体的には Claude Code から次のことができます。
- 別のペインにコマンドやテキストを送る
- 別のペインの出力(画面に出ている内容)を読み取る
- 新しいタブやペインを作る
npx skills add yamitzky/agent-skills などで入れられます。
...と、ここまで書いて気づいたのですが、cmux には公式のスキルもあります。
別ターミナルの操作を Claude に渡す
1つ目の用途は、人間が操作していたターミナルを途中から Claude Code に渡す使い方です。
当たり前ですが、Claude Code 自身が Bash のコマンドを実行することはできます。また、 !command のような形で、Claude Code のセッション内でコマンドを実行することもできます。ただ、パスワード入力や対話的な確認(y/n を聞かれるなど)が必要な操作は、Claude Code 内のターミナルではうまく扱えません。
そこで、残念ながら zellij や cmux などで別ペインで人間が普通にターミナル操作をする必要があるわけですが、認証や対話的な操作だけ人間がやって、その後の操作を claude に引き継ぐ、といったことができます。
また、もともと AI に頼むつもりがなく自分で叩いていたターミナルを、「このエラー解消して」といった形で途中から渡す、みたいなこともできます。
例えば、Claude Code で「cmux で隣の surface に npm start 送ってー」とか依頼するとやってくれます。
❯ cmux で隣の surface に npm start 送ってー
cmuxスキルを使います。
⏺ Skill(cmux)
Successfully loaded skill
まず現在のコンテキストと隣のsurfaceを確認します。
⏺ Bash(cmux identify --json && echo "---" && cmux list-pane-surfaces --pane pane:1)
自分は pane:2 / surface:2 にいます。隣のsurfaceを確認するため、ワークスペースとpaneの構成を見ます。
(中略)
send で送り、Enterを送ります。
⏺ Bash(cmux send --surface surface:21 "npm start" && cmux send-key --surface surface:21 enter)
OK surface:21 workspace:2
疑似マルチエージェント
2つ目の用途は、エージェント間で擬似的にやり取りをする使い方です。
Claude Code には サブエージェントのための機能があり ますし、Claude 同士に会話させる Claude Peers や agmsg のようなツールもあります。
ただ、Claude Code のセッションを複数立ち上げて作業していると、もともと連携させるつもりがなかったセッション同士を、後から協調させたくなることもあります。
たまにあるのが、PR 間のコンフリクト解決です。別々のブランチで作業していた2つのセッションに、お互いの状況を伝え合ってもらって、どちらがどう直すかを相談して解決してもらう、という使い方をします。片方のペインの出力を読んで、もう片方のペインに状況を送る、というのをスキル経由でやらせる形です。
例えば Claude Code に「zellij の Tab2 を参照して〜」とかいうとやってくれます。
## メインのタブ
❯ zellij のTab2 と Tab3で Claude Code を動かしているから、CCとやり取りして現状をまとめて。
zellij の Tab2 と Tab3 の Claude Code とやり取りして現状をまとめます。まず zellij スキルで操作方法を確認します。
⏺ Skill(zellij)
Successfully loaded skill
(中略)
見つかりました。Tab2 = terminal_1、Tab3 = terminal_3。それぞれの Claude Code に現状確認の質問を送ります。まず現在の画面状態を見てから送ります。
⏺ Bash(echo "=== TAB2 (terminal_1) ==="; zellij action dump-screen -p terminal_1 2>/dev/null | tail -25; echo; echo "=== TAB3 (terminal_3) ==="; zellij action dump-screen -p terminal_3 2>/dev/null | tail -25)
=== TAB2 (terminal_1) ===
---
## 別タブ ※以下の文章は、メインタブの Claude Codeが自分で考えて送った文章※
❯ 今の作業の現状を簡潔にまとめてください。ブランチ名、対応中のPR番号、何の作業か、今どのステップで止まっているか(次に何をすべきか)を箇条書きで。実装は不要、状況報告だけお願いします。
⏺ 現状報告です。
(略)
---
## メインのタブ
⏺ 両方の Claude Code から状況を取得しました。まとめます。
---
Tab2 / Tab3 の作業状況まとめ
(略)
まとめ
CLIの操作にして、エージェント間のやり取りにしても、基本的には Claude Code 公式の機能を使ったり、専用のプラグインを使った方が良いです。トークン効率も悪いので。
ただ、「後からやっぱり Claude Code に引き継いで〜」というときに、たまーに、ちょっとだけ便利なテクニックなので紹介させてもらいました。
Discussion