Claude Codeの--execでシェルコマンドをバックグラウンド実行する
Claude Codeの--execフラグは、シェルコマンドをモデルを介さずPTY付きのバックグラウンドジョブとして起動する仕組みです。--bgとの組み合わせ方、管理コマンド、出力が5分で消える制約を扱います。
Claude Codeの--execフラグは、シェルコマンドをClaudeセッションとしてではなく、PTY(疑似端末)付きのバックグラウンドジョブとして起動します。--bgと組み合わせてclaude --bg --exec 'pytest -x'のように使うと、モデルを一度も呼ばずにpytest -xだけが裏側で走り、結果はagent viewの一覧に1行として現れます。テスト実行やビルドのような重いシェル処理を、Claudeへの依頼と同じIDや管理コマンドで扱いたいときに使う機能です。
--execが起動するのはClaudeセッションではない
claude --bgだけを渡すと、渡した指示文をClaudeが読み、調査や編集を行う対話セッションがバックグラウンドで始まります。会話が発生し、ファイルを編集する前にはgitワークツリーへ移動し、終わればコミットや報告を作る一連の流れが動きます。
--execはこの流れをまるごと飛ばします。公式ドキュメントは「シェルジョブはClaudeの代わりにコマンドを実行するもので、モデルは呼ばれず、出力もどのセッションにも送られない」と明記しています。つまり動くのは指定したコマンドのプロセスだけで、Claude自身は一切介在しません。PTY付きというのは、素のシェルから実行したときと同じ疑似端末をコマンドに与えるという意味です。
この違いは地味に見えて実務上は大きいです。テストを1回走らせたいだけなのに、わざわざClaudeに「テストを実行して」と頼むと、モデルが結果を解釈するぶんの時間とやり取りが挟まります。--execはその解釈を挟まず、コマンドの実行結果だけを一覧の1行として残します。
PTY(pseudo terminal、疑似端末)は、パイプでつないだだけのプロセスと違い、本物の端末から実行されているように相手のプロセスへ見せる仕組みです。色付きの出力や進捗表示を含むコマンドでも、素のターミナルで直接実行したときに近い見た目でログが残ります。--execがこの形式を選んでいるのは、対象がClaudeとの会話ではなく、あくまで「シェルで動かすはずだったコマンド」だからです。
--bgと組み合わせて実行する
使い方は2通りあります。1つはシェルから直接、--bgと--execを並べて起動する方法です。
claude --bg --exec 'pytest -x'--execの値は実行したいコマンドそのものを1つの文字列として渡します。シェルのパイプやリダイレクトを含む複雑なコマンドを渡す場合は、クォートで囲んで1つの引数にしておく必要があります。ビルドを裏で走らせておきたいときも同じ形です。
claude --bg --exec 'npm run build'出力はあとで説明するとおり一定時間で消えるため、結果をファイルに残したいコマンドは、あらかじめシェル側でリダイレクトしておくのが確実です。
claude --bg --exec 'pytest -x > /tmp/pytest.log 2>&1'このようにしておけば、agent view側の出力が片付いたあとでも/tmp/pytest.logを直接開けます。--exec自体はログを保存しないので、保存したい場合はコマンド側の責務として書いておく発想が必要です。
もう1つはagent view内から起動する方法です。画面下部の入力欄で先頭に!を付けると、その行全体がClaudeへのプロンプトではなくシェルコマンドとして扱われます。
!pytest -x!は入力欄でプレフィックスとして表示され、それ以降の文字列がそのままコマンドになります。Enterを押すとジョブが始まり、シェルから--bg --execで起動した場合と同じ種類の行が一覧に追加されます。起動経路が違うだけで、ジョブとしての性質は同じです。
ジョブはagent viewやターミナルを閉じても動き続けます。裏で常駐しているsupervisorプロセスがセッションとジョブの両方を保持しているため、画面を閉じたからといってpytestが途中で止まることはありません。
--execは必ず--bgとセットで使います。--bgは非対話モードの-p(--print)と同時に指定できず、指定した時点でセッションを作る前にエラーになります。スクリプトから--execを呼ぶときにこの組み合わせを混ぜてしまうミスは起きやすいので、先に--bg単体で起動できることを確認してから--execを足すと切り分けやすくなります。
起動したジョブを確認・停止する方法
起動すると短いIDが発行されます。このIDは~/.claude/jobs/<id>ディレクトリの名前と同じで、他のバックグラウンドセッションと共通の仕組みです。管理に使うコマンドも共通です。
| コマンド | 用途 |
|---|---|
claude agents | 用途一覧を開き、ジョブの行を状態付きで確認する |
claude attach <id> | 用途ジョブの出力をこのターミナルで直接見る |
claude logs <id> | 用途アタッチせずに直近の出力だけ表示する |
claude stop <id> | 用途ジョブを止める(claude killでも同じ) |
agent view上では、行にはコマンドの最新の出力行がステータスとしてそのまま表示されます。全体の出力を見たいときは行を選んでSpaceキーを押すと、アタッチせずに覗き見できます。じっくり見たい場合はEnterでアタッチするか、claude logs <id>をシェルから叩きます。
ジョブを含むすべてのバックグラウンド行は、claude daemon statusで確認できる常駐のsupervisorプロセスが動かしています。動作がおかしいときの復旧手段として、claude daemon stop --anyはsupervisorとそれが抱えるセッション・ジョブをまとめて止めます。個別のジョブだけを止めたい通常の運用では、claude stop <id>で十分です。
複数のリポジトリで--execを使っていると、claude agentsの一覧はセッションとジョブが入り混じって長くなりがちです。claude agents --cwd <path>を使うと、指定したディレクトリ配下で始めた行だけに絞り込めるので、目当てのジョブを探す手間が減ります。
出力は5分で消える — 見る前に確認すること
--execで起動したジョブの出力は、ディスクには書き込まれずメモリ上にだけ保持されます。しかもコマンドが終了してから約5分で、行と出力の両方が自動的に片付けられます。結果が必要なら、その前にclaude logsかclaude attachで読んでおく必要があります。
これは通常のClaudeセッションとの明確な違いです。claude --bg "調査して"で始めたセッションの会話は、終了後もディスクに残り続け、claude --resumeでいつでも参照できます。一方--execのジョブは使い捨てで、5分を過ぎれば結果を取り戻す手段がありません。長時間かかる処理を--execに投げっぱなしにして、結果を見忘れるという事故が起きやすい設計です。
5分のカウントは「コマンドが終了してから」始まる点にも注意します。tail -fのように自分では終了しないコマンドを走らせている間は、このルールは働きません。行が消えるのは、あくまでコマンド自身が終了するか、claude stopで止めたときです。ログを流し続けるような監視用途では、むしろこの性質のほうが都合よく働きます。
もう1つ覚えておく価値がある挙動があります。シェルコマンドの行は、Enterキーでの再起動にもclaude attachでの再起動にも対応していません。公式ドキュメントは、再起動すると同じコマンドをもう一度実行することになるため、シェルジョブの行だけは意図的に再起動しない、と説明しています。行のメッセージとclaude attachの出力の両方が、そのコマンドは再実行されない旨を表示します。テストのように何度走らせても副作用がないコマンドなら気にする必要はありませんが、ファイルへの書き込みを伴うコマンドを再起動のつもりで動かすと、想定と違う結果になりかねません。
通常のバックグラウンドセッションとの使い分け
同じ--bgから始まる2つの起動方法は、性質がまったく違います。何を任せたいかで選ぶのが基本です。
| 項目 | claude --bg "指示文" | claude --bg --exec 'コマンド' |
|---|---|---|
| 実行されるもの | claude --bg "指示文"Claudeによる対話セッション | claude --bg --exec 'コマンド'シェルコマンドそのもの(モデル呼び出しなし) |
| 向いている用途 | claude --bg "指示文"調査・修正・複数手順にまたがる作業 | claude --bg --exec 'コマンド'テスト実行・ビルドなど単発コマンドの実行監視 |
| 結果の保存 | claude --bg "指示文"会話としてディスクに残り、いつでも参照可能 | claude --bg --exec 'コマンド'メモリ保持のみで、終了後 約5分で消える |
| 再開・再実行 | claude --bg "指示文"claude respawn <id>で会話ごと再開できる | claude --bg --exec 'コマンド'Enterやclaude attachでは再実行されない |
結果として、agent viewの一覧にはClaudeが動くセッションと、モデルを介さない素のシェルジョブが同じ行の形式で並ぶことになります。テストの完了を待つだけの用途にモデルを呼ぶ必要はなく、--execを使えばその分の待ち時間とやり取りを省けます。逆に、結果を解釈してファイルを直したいような作業には、最初から--execではなく通常の--bgを使うほうが手数が少なくて済みます。
ターミナルでコマンドの末尾に&を付けて裏で走らせる方法と何が違うのか、という疑問も出てきます。&はそのターミナルを閉じた瞬間にプロセスごと終了しますが、--execのジョブはsupervisorが保持するため、ターミナルを閉じても走り続けます。加えて&のプロセスにはclaude attachやclaude logsのような共通の管理コマンドがなく、いま何が動いているかを一覧で把握する手段もありません。--execが解決しているのは、その「裏で動かしたコマンドを、あとから他のセッションと同じやり方で見失わずに済む」という部分です。ターミナルを1枚しか開かずに複数のコマンドを並行で走らせたい人ほど、この違いの恩恵を受けやすいはずです。
この機能名そのものが示しているのは、agent viewが単に「Claudeとの会話を裏で続ける画面」ではなく、手元のシェル作業を一時的に預けておく場所としても設計されている点です。
claude agents --jsonでジョブの状態をスクリプトから読み取りたい場合や、--cwdで対象ディレクトリを絞り込みたい場合は、claude agents --jsonでバックグラウンドセッションを操作するにスクリプト向けの詳細があります。agent view全体の常駐プロセス設計や状態アイコンの見方は、Claude Codeのagent viewにまとまっています。
--exec以外の起動時フラグで挙動を固定したい場合は、権限モードを起動時に決め打ちするClaude Codeの--permission-modeで起動モードを指定するや、使えるツールを起動時に絞り込むClaude CodeのallowedTools/disallowedToolsで起動時に権限を絞るもあわせて確認してください。