driving-claude-code-sessions について
CLI を使って tmux 内で Claude Code、Codex、Pi のコーディングエージェントを起動・操作するスキルです。共通のコマンド体系で、複数ターンの指示、イベント監視、並列実行、人への引き継ぎを行えます。
主な機能
- 01tmux 内でワーカーを起動
- 02プロンプト送信とターン管理
- 03出力とライフサイクルイベントの閲覧
- 04複数ワーカーの並列実行
- 05セッションを人に引き継ぎ
活用シーン
- 01複数のエージェントに別々の作業を割り当て
- 02生成した仕様を実装ワーカーに渡す
- 03実行中のワーカーを監視
- 04既存の Claude セッションをワーカーとして再開
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ obra/ claude-session-driver --skill driving-claude-code-sessionsインストール後、Claude Code で/driving-claude-code-sessionsを入力して読み込まれたか確認します。
同梱ファイルscripts/csd
詳細
コーディングエージェントのセッションを起動する
概要
コーディングエージェントのセッション(Claude Code、Codex、Pi)を tmux 内で「ワーカー」として起動し、プロンプトを送信して、完了を待ち、出力を読み取り、人間に引き継ぐことができます。ワーカーは権限チェックをバイパスして実行されるため、確認を求めずにツール呼び出しを実行します。各ワーカーは、ライフサイクルイベントを JSONL ファイルに出力するため、コントローラーはワーカーの動作を監視できます。Claude と Codex はそれぞれのフックシステムを通じて、Pi は csd が読み込むネイティブ拡張機能を通じてイベントを出力します。
すべての操作は単一の CLI、csd を通じて行います。ワーカーを起動すると、コントローラーはワーカーハンドルを埋め込んだ /tmp/csd-workers/bin/<tmux-name> の シムパス を受け取ります。ワーカーごとの操作はすべてこのパスを通じて行います。呼び出し間で位置引数の状態を受け渡す必要はなく、先頭に絶対スキルパスを付ける必要もありません。動作は少数の環境変数で調整できます。下部の環境変数を参照してください。
(ワーカーディレクトリは /tmp/claude-workers から /tmp/csd-workers に移動しました。デフォルトのパスを使用する場合、csd は後方互換性のためのシンボリックリンク /tmp/claude-workers → /tmp/csd-workers を作成するため、以前のパスや使い慣れた操作も引き続き利用できます。)
シムパスは決定的です。起動時に覚えやすい tmux 名を選べば、必要なときにいつでも /tmp/csd-workers/bin/<tmux-name> を再構成できます。ツール呼び出しで操作するエージェントには、この方法が適しています。シェルの状態は呼び出し間で保持されないため、SHIM=...; $SHIM cmd というパターンは余計な記述を増やすだけです。以下の例ではパスをそのまま使用しています。
ハーネス
起動時に --harness でハーネスを選択します(デフォルトは claude)。
$SKILL/csd launch --harness codex my-task /path/to/project
$SKILL/csd launch --harness pi my-task /path/to/project
コントローラー向けのコマンド群は、3 つのハーネスすべてで 同一 です。launch、send、converse、wait-for-turn、read-turn、read-events、status、stop、handoff は、ハーネスに関係なく同じように動作します。いくつか異なる点があります。
- 認証。 各ハーネスは、それぞれのホームディレクトリ(Claude は
~/.claude、Codex は~/.codex、Pi は~/.pi/agent)で認証します。csdは起動時にそのログイン情報をワーカーに設定するため、認証情報を更新するには再起動してください。 adoptは Claude 専用です。 Claude は呼び出し元が割り当てたセッション ID を受け取るため、ID を指定してセッションを再開できます(claude --resume)。Codex と Pi は最初のプロンプトで独自の ID を生成し、ID を指定して再開する機能を備えていないため、再起動してください。- Codex は最初のプロンプトを送るまで照会できません。 Codex は最初のプロンプトを送った時点でのみセッション ID を生成するため、
launchの後、最初のsend/converseの前は、Codex ワーカーのstatus、session-id、wait-for-turnがno worker knownを返します。ワーカーは 実行中 ですが、まだ登録されていないだけです。converseはこの状況を内部で処理するため、一般的な launch→converse の流れなら問題ありません。この間隙が見えるのは、低レベルのコマンドを使う場合だけです。(Claude は起動時に ID を受け取り、Pi は起動時に登録されるため、どちらもすぐに照会できます。)
前提条件
- tmux
- ハーネスの CLI(少なくとも起動するもの):claude(デフォルト)、codex、または pi
(jq も bash フックも不要です。csd は TypeScript/node のツールで、フックは node プログラムです。node は必要ですが、Claude Code が実行される環境にはすでに存在します。)
セットアップ
CLI は <skill>/scripts/csd にあります。トップレベルのサブコマンドにはスキルのパスが必要です。
csd launch [--harness <claude|codex|pi>] <tmux-name> <cwd> [-- harness-args...]— ワーカーを起動します(ハーネスのデフォルトはclaude)csd adopt <tmux-name> <cwd> <session-id> [-- claude-args...]— 既存の Claude セッションをワーカーとして再採用します(claude のみ。[ワーカーの復旧](#recovering-workers-after-a-reboot)を参照)csd list [--all]— ワーカーを列挙しますcsd grant-consent— 権限をバイパスしてワーカーを実行するための、一度限りの同意を付与します
ワーカーの起動後は、以降のコマンドを /tmp/csd-workers/bin/<tmux-name> に対して実行します。
SKILL=/abs/path/to/skill/scripts
$SKILL/csd grant-consent # one-time per machine
$SKILL/csd launch my-task /path/to/project # stdout: /tmp/csd-workers/bin/my-task
/tmp/csd-workers/bin/my-task status # use the shim directly
起動時に覚えやすい tmux 名を選んでください。shim のパスはそれによって決まります。(対話型シェルではシェル変数に格納することもできますが、エージェント主導のワークフローでは、そのまま使えるパスのほうが簡単です。呼び出しの間に失われるシェルの状態がないためです。)
ワークフロー
以下の例では、$SKILL は skills/driving-claude-code-sessions/scripts の絶対パスです。WORKER はそのまま使える shim のパス(例:/tmp/csd-workers/bin/my-task)です。ワーカーに対応する確定的なパスに置き換えてください。
1. 起動
$SKILL/csd launch my-task /path/to/project
# stdout: /tmp/csd-workers/bin/my-task
# stderr: Worker launched. tmux/session_id/cwd/events/reproduce
csd launch は次の処理を行います。
/tmp/csd-workers/bin/my-taskに3行の shim を書き込みます- tmux とハーネスをその中で起動します
- ワーカーの準備が整うまで待機します。呼び出し元が割り当てたセッション ID を使う Claude は
session_startイベントを待ちます。Codex と Pi は最初のプロンプトで独自の ID を生成するため、起動時に TUI を安定させ、最初のイベントが発生した時点でワーカーのメタ情報が自動登録されます - shim のパスを標準出力に1行で表示します
- 「Worker launched」パネルを標準エラーに表示します。
reproduce:の行には、同じ引数で再起動するための正確なコマンドが表示されます
ハーネスの CLI 引数は -- 区切りの後に渡すか、--harness でデフォルト以外のハーネスを選択します。
$SKILL/csd launch my-task /path/to/project -- --model sonnet
$SKILL/csd launch --harness codex my-task /path/to/project
2. やり取り(通常のケース)
/tmp/csd-workers/bin/my-task converse "Refactor the auth module" 300
converse はプロンプトを送信し、ワーカーの処理が完了するまで待機して、最終的なアシスタントのテキストを標準出力に表示します。ツールを多用するターンで、テキストだけでは重要な部分が省かれてしまう場合は、--with-turn を使うと Markdown 全体を取得できます。
/tmp/csd-workers/bin/my-task converse --with-turn "Run the failing tests" 600
複数ターンのやり取りにもそのまま対応します。待機処理はターンの境界を自動的に追跡します。
/tmp/csd-workers/bin/my-task converse "Write tests for the auth module" 300
/tmp/csd-workers/bin/my-task converse "Add edge cases for expired tokens" 300
3. より低レベルの制御
ワーカーをより直接的に操作する必要がある場合:
/tmp/csd-workers/bin/my-task send "Refactor the auth module" # send without waiting
/tmp/csd-workers/bin/my-task wait-for-turn 300 # block until stop or session_end
/tmp/csd-workers/bin/my-task status # idle | working | terminated | gone | unknown
/tmp/csd-workers/bin/my-task read-turn # last turn as markdown (tool results truncated to 5 lines)
/tmp/csd-workers/bin/my-task read-turn --full # last turn with complete tool results
4. ワーカーの動作を監視
すべてのツール呼び出しで、ツール名と入力を含む pre_tool_use イベントが発生します。イベントストリームを追尾すると、リアルタイムで監視できます。
/tmp/csd-workers/bin/my-task read-events --follow &
MONITOR_PID=$!
# ... do other work ...
kill $MONITOR_PID
または、後からイベントを取得できます。
/tmp/csd-workers/bin/my-task read-events # all events
/tmp/csd-workers/bin/my-task read-events --last 5
/tmp/csd-workers/bin/my-task read-events --type pre_tool_use
--type には、session_start、user_prompt_submit、pre_tool_use、post_tool_use、stop、session_end のいずれかを指定します。不明なイベント名を指定すると、即座にエラーになります。(Claude のワーカーは pre_tool_use を出力しますが、post_tool_use は出力しません。Codex と Pi は両方を出力します。)
望ましくない動作を見つけた場合は、ワーカーを停止してください。
/tmp/csd-workers/bin/my-task stop
5. 停止してクリーンアップ
/tmp/csd-workers/bin/my-task stop
/exit を送信し、session_end を最大10秒間待ちます。まだ実行中の場合は tmux セッションを終了し、メタ情報、イベント、shim の各ファイルを削除します。
stop は破壊的な操作です。ワーカーは終了し、shim のパスも機能しなくなります。後続のターンや並行ワークフローのためにワーカーを残しておきたい場合は、作業が終わるまで stop を呼び出さないでください。同じ名前で作業を再開するには、再度起動します。たとえば csd launch my-task /path/to/project を実行すると、同じ shim パスで新しいワーカーが起動します。
stop の後は shim が存在しないため、再度呼び出すと no such file or directory: /tmp/csd-workers/bin/my-task のようなシェルエラーが表示されます(正確な文言はシェルによって異なります)。これは想定どおりです。ワーカーは終了しています。
6. 人間に引き継ぐ
/tmp/csd-workers/bin/my-task handoff
人間が tmux セッションを引き継ぐための接続手順を表示します。
ワーカーを探す
$SKILL/csd list # live workers (idle/working/terminated)
$SKILL/csd list --all # include 'gone' workers (tmux already exited)
$SKILL/csd list api # substring filter on tmux name
$SKILL/csd prune # remove dead workers + orphaned sidecars/shims
リファレンス
csd launch [--harness <claude|codex|pi>] <tmux-name> <cwd> [-- harness-args...]
csd adopt <tmux-name> <cwd> <session-id> [-- claude-args...] # claude-only
csd list [--all] [<pattern>]
csd prune # remove dead/orphaned worker state
csd grant-consent
<shim> converse [--with-turn] <prompt> [timeout=120]
<shim> send <prompt>
<shim> wait-for-turn [timeout=60] [--after-line N]
<shim> status
<shim> read-events [--last N] [--type T] [--follow] # --last caps the --follow backlog
<shim> read-turn [--full]
<shim> stop
<shim> handoff
<shim> session-id
<shim> events-file
<shim> は /tmp/csd-workers/bin/<tmux-name> です。同じ内容は csd help でも確認できます。
よくあるパターン
ファンアウト:複数のワーカーを並行して実行
$SKILL/csd launch worker-api ~/proj
$SKILL/csd launch worker-ui ~/proj
/tmp/csd-workers/bin/worker-api send "Add pagination to /users"
/tmp/csd-workers/bin/worker-ui send "Add a loading spinner to the user list"
/tmp/csd-workers/bin/worker-api wait-for-turn 600
/tmp/csd-workers/bin/worker-ui wait-for-turn 600
/tmp/csd-workers/bin/worker-api stop
/tmp/csd-workers/bin/worker-ui stop
パイプライン:Worker A が生成し、Worker B が使用する
$SKILL/csd launch spec ~/proj
/tmp/csd-workers/bin/spec converse "Write an OpenAPI spec for /users to /tmp/api.yaml" 300
/tmp/csd-workers/bin/spec stop
$SKILL/csd launch impl ~/proj
/tmp/csd-workers/bin/impl converse "Implement the endpoint defined in /tmp/api.yaml" 600
/tmp/csd-workers/bin/impl stop
Worker B が何をしたかについての要約を鵜呑みにせず、生成されたファイルを確認してください。誤った内容を書き込んでいても、Worker が成功したと報告することがあります(重要な注意事項を参照)。
エッジケース
ターンの途中で Worker がクラッシュした場合
wait-for-turn は stop または session_end のどちらにも一致するため、Worker が終了すると戻ります。その後 status を呼び出してください。gone なら、Worker はクラッシュしています。
converse がタイムアウトした後は、wait-for-turn の前に status を確認する
単独で wait-for-turn を呼び出すと、イベントファイルの現在の末尾を基準点として、次のターン終了を待ちます。converse がタイムアウトした場合、Worker はその間に処理を終えていることがよくあります。stop はすでに記録されているため、続けて wait-for-turn を呼び出すと、開始されることのないターンを待ってタイムアウト時間全体を消費してしまいます。タイムアウト後は、まず status を呼び出してください。idle ならターンはすでに終了しています(read-turn で読み取れます)。working なら、まだ処理中です。
再起動後に Worker を復旧する
Worker のランタイム状態(/tmp/csd-workers 内の meta/events/shim ファイル)は /tmp に保存されるため、macOS の再起動時に消去され、tmux ペインも同時に終了します。しかし、会話は残ります。Claude Code は各セッションのトランスクリプトを ~/.claude/projects/<encoded-cwd>/<session-id>.jsonl に永続化します。csd adopt を使うと、会話をライブ状態で操作可能な Worker として復帰できます(これはclaude のみです。Codex と Pi は独自のセッション ID を発行し、ID を指定して再開する機能がないため、再起動してください)。
$SKILL/csd adopt my-task /path/to/project <session-id>
# stdout: /tmp/csd-workers/bin/my-task (same shim contract as launch)
これは claude のみです。codex/pi の会話は stop 後に残りません。 Codex と Pi は、実際の ~/.codex/~/.pi ではなく、Worker ごとに用意されたステージング済みのホームディレクトリ /tmp/csd-workers/homes/<name>/(設定、認証情報、ロールアウト/セッショントランスクリプト)で動作します。stop はこのホームディレクトリを削除するため、トランスクリプトも失われ、復旧手段はありません。再起動すると新しいセッションが始まります。claude だけは Worker ディレクトリの外部(~/.claude/projects)にトランスクリプトを永続化するため、adopt で復帰できます。
adopt は <session-id> をキーにした meta を事前に書き込み、claude --resume <session-id> を起動します(ID が保持されるため、Worker は通常どおりイベントを出力します)。また shim も書き込みます。そのため、再開した会話は以前のコンテキストをすべて保持したまま、完全に操作可能です(converse/status/read-turn/…)。同じ名前の tmux セッションがすでに存在する場合(たとえば tmux-resurrect/tmux-continuum によって復元されている場合)、adopt はそのペインをその場で再起動し、復元されたレイアウトを保持します。存在しない場合は、新しいペインを開きます。
Worker の <session-id> は、作業ディレクトリから見つけられます。~/.claude/projects/<cwd with every / . _ replaced by -> 内で最も新しい *.jsonl を確認してください。一括復旧(たとえば tmux-continuum の @continuum-boot と組み合わせる場合)には、examples/recover-workers.sh が tmux-resurrect のスナップショットを読み込み、各 ID を特定して Worker ごとに adopt を呼び出します。まず --dry-run を付けて実行してください。注意:Worker は元のツール/MCP の状態ではなく、再開したセッションとして復元されます。必要だった起動引数(例:-- --model …)は再度渡してください。
shim のパスを見失った場合
tmux 名が分かっている場合、パスは /tmp/csd-workers/bin/<tmux-name> です。分からない場合は、csd list で一覧を表示できます。csd list <pattern> を使うと、tmux 名に指定した文字列を含む Worker に絞り込めます。
長いプロンプト
send はブラケット付きペーストを使用するため、複数行や特殊文字を扱えます。数十 KB に及ぶプロンプトの場合は、ファイルに書き込み、Worker にそのファイルを読み込むよう伝えてください。
echo "Long instructions..." > /tmp/instructions.txt
/tmp/csd-workers/bin/my-task send "Read /tmp/instructions.txt and follow it"
重要な注意事項
- Worker ごとにコントローラーは 1 つにしてください。 同じ tmux セッションを操作する 2 つのコントローラーは競合します。
- Worker はコントローラーと状態を共有しません。 共有されるのは、ディスク上のファイルとイベントストリームを介した場合のみです。
- Shim のパスにはスキルの絶対パスが埋め込まれています。 プラグインを別の場所に再インストールすると、稼働中の Worker が使えなくなるため、再起動してください。
- csd は透過的なリレーであり、検証機能はありません。
converse/read-turnは、Worker の発言をそのまま返します。Worker が自信たっぷりに間違ったことを述べている場合も同様です。正確さが重要な引き継ぎでは、Worker の自己報告の文章ではなく、ディスク上に生成された成果物を検証してください。
環境変数
csd CLI では、少数の環境変数を使用します。すべて任意です。
| 変数 | 用途 |
|---|---|
CSD_CLAUDE_BIN / CSD_CODEX_BIN / CSD_PI_BIN | 各ハーネスのバイナリへのパスです。デフォルトは claude / codex / pi です(PATH から解決されます)。バイナリが PATH にない場合や、特定のバージョンを固定したい場合に設定します。 |
CSD_CODEX_MODEL / CSD_PI_MODEL | codex / pi ワーカーで使用するモデルの任意の上書き設定です。未設定の場合は、ハーネスのデフォルトが使用されます(codex:gpt-5.5、pi:設定済みのデフォルト)。 |
CSD_CONVERSE_DIAG_FILE | 設定すると、タイムアウト時に csd converse が事後診断情報(ps のツリー、tmux capture-pane、ワーカーのセッション JSONL の末尾 30 行、csd イベント JSONL の末尾 20 行)をこのパスに書き込み、csd-diagnostic: <path> という参照先を stderr に出力します。タイムアウトのたびにファイルは上書きされます。未設定の場合、診断ファイルは作成されません。ワーカーの終了前にファイルをホスト外へ送信できるハーネスで csd をラップする場合に便利です。 |
CSD_WORKER_DIR | ワーカーディレクトリを上書きします(デフォルトは /tmp/csd-workers)。デフォルトが使用されている場合にのみ、後方互換性のための /tmp/claude-workers シンボリックリンクが作成されます。 |
CSD_SUBMIT_TIMEOUT / CSD_SUBMIT_RETRY_INTERVAL | send:ワーカーが貼り付けられたプロンプトを確認するまで待機する秒数(デフォルトは 10)と、Enter キーを再送信する間隔(デフォルトは 2)です。tmux セッションの動作が遅く、貼り付けた内容が失われる場合は、タイムアウトを長くしてください。 |
CSD_REGISTER_TIMEOUT | derive ワーカー(codex/pi)への最初の send / converse で、ワーカーがセッション ID を自動登録するまで待機する秒数です(デフォルトは 15)。 |
HOME | ~/.claude/projects/<encoded-cwd>/<sid>.jsonl(claude)と、1 回限りの同意ファイル(~/.claude/.claude-session-driver-consent)の場所を特定するために使用します。 |
csd help には、同じ項目が表示されます。