🐷

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 から次のことができます。

  • 別のペインにコマンドやテキストを送る
  • 別のペインの出力(画面に出ている内容)を読み取る
  • 新しいタブやペインを作る

https://github.com/yamitzky/agent-skills

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 Peersagmsg のようなツールもあります。

ただ、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