`claude -p` を CI スクリプトに組み込んで、複数ユーザー・複数マシン環境で同じ処理を回している人向け
GitHub Actions の matrix で OS 違いの runner(実行用の仮想マシン)が並列に同じ `claude -p` スクリプトを叩いている場面や、社内メンバー複数人が自分のマシンから同じ Claude スクリプトを叩く場面で、共通のシステムプロンプト部分が Anthropic 側で使い回される率を上げたいときに、起動コマンドの後ろに `--exclude-dynamic-system-prompt-sections` を書き足して使う
Claude Code を claude -p "..." の形でスクリプトに組み込むと、Anthropic 側に「prompt cache」と呼ばれる仕組みがあって、同じシステムプロンプトを使い回せるとトークン代を割り引いてくれます。ただし、システムプロンプトの中に「いま走っているマシン固有の情報」が混ざっていると、マシンが違うだけで「別物」と判定されて、再利用率がガクッと落ちます。
--exclude-dynamic-system-prompt-sections は、その「マシン固有の4つの記述」をシステムプロンプトから引き剥がして、最初の人間側メッセージの先頭に押し込んでくれる起動スイッチです。具体的には次の4つ。
- 作業フォルダ
- 環境情報
- メモリ置き場
- git管理下かどうかの印
複数マシンで同じスクリプトを叩く CI 用途で、共通部分の再利用を真剣に効かせたいときに使います。
名前が長くて読みづらいですが、やってることは1つだけ。
噛み砕くと
Anthropic の課金は、システムプロンプトが完全一致していれば「前回と同じやつね」と判定して、その部分のトークン代を割り引く仕組みになっています。マシンが3台あって、それぞれの作業フォルダや内部のメモリ置き場が違うと、システムプロンプトの中の「いまどこで動いてるか」の行だけが違って、それだけで「別の人」扱いされてしまう。
会議室で例えると、配布資料の最初のページに参加者の名前が印刷されていると、本文がまったく同じでも資料は1人ずつ別物になります。それをやめて、名前は別紙に書いて配って、本文だけ全員共通の印刷物にしましょう、というのがこのスイッチの発想です。
大事な前提:このスイッチは「同じスクリプトを複数マシンで叩く」とき以外は意味が薄い
仕組み上、得をするのは「1人のユーザーが1台で叩いている」ときではありません。むしろ、CI の matrix で OS 違いの runner が3台同時に走っているとか、社内のメンバー5人がそれぞれの作業マシンから同じスクリプトを叩いている、そういう状況で初めて効果が見えます。
1台でしか叩かないなら、マシン固有情報も毎回同じなので、システムプロンプトは元から完全一致して保存分が再利用されています。このスイッチを足しても何も変わらない、むしろメッセージ構造が少し複雑になるぶん損です。
「GitHub Actions の matrix で3つのrunnerが同じClaudeスクリプトを叩く」を例に、実際の手順を見る
仮の状況として、PR の差分を要約するスクリプトを GitHub Actions に組み込んでいて、3つの OS で同じスクリプトが並列で走るとします。OS は Ubuntu / macOS / Windows の3種類です。
ステップ1:スイッチなしで叩いている状態を見る
ワークフローはこんな感じになっているとします。
jobs:
summarize:
strategy:
matrix:
os: [ubuntu-22.04, macos-14, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- run: claude -p "summarize the diff in this PR"
この状態で3台同時に走ると、それぞれの runner で claude が組み立てるシステムプロンプトには、次のような「マシンごとに違う行」が紛れ込みます。
- 作業フォルダ:runner ごとに違う場所。
~/work/...配下でも OS によって書式が違う - 環境情報:OS 名、コマンド入力画面の種類、ロケール
- メモリの置き場:
~/.claudeの実体が runner ごとに別の場所 - git管理下かどうかの印:内容自体は同じでも、内部表現で差が出る場合がある
結果として、Anthropic 側から見ると「3つの別のシステムプロンプト」が来ているように見えて、保存データは3台それぞれが独自に温める形になります。
ステップ2:スイッチを1つ足す
ワークフローの run 行を1つ書き換えます。
- run: claude -p --exclude-dynamic-system-prompt-sections "summarize the diff in this PR"
これだけです。設定ファイルもいじりません。
ステップ3:内部で何が起きるか
claude は、自分が組み立てるシステムプロンプトから、上のステップ1で挙げた4つの記述を切り取って、ユーザー側の最初のメッセージの先頭にくっつけて API に送ります。
図にすると、こうなります。
【スイッチなし】
system: [共通部] + [マシン固有4セクション] + [ツール案内]
user: "summarize the diff in this PR"
【スイッチあり】
system: [共通部] + [ツール案内]
user: [マシン固有4セクション] + "summarize the diff in this PR"
こうなると、system 部分は3台の runner で完全一致します。Anthropic 側の保存済みデータは system 部分を見て「同じやつ」と判定するので、2台目以降の runner は1台目が温めた保存に乗れる、というわけです。
ステップ4:効いてるかを確認する
API 応答の usage ブロックに、保存再利用の関連項目が入っています。
claude -p --exclude-dynamic-system-prompt-sections --output-format stream-json "summarize the diff in this PR"
stream-json で受けると、最後の result イベントの usage に cache_read_input_tokens と cache_creation_input_tokens が出ます。2台目以降の runner で cache_read_input_tokens が増えていれば、共通の system プロンプトが再利用できています。
ステップ5:ここでよくある勘違い
「マシン固有情報を消す」と聞くと、AI が作業フォルダや OS を知らない状態になると思いがちですが、そうじゃありません。情報自体は最初のメッセージの先頭に移動するので、AI からは引き続き見えています。仕事の能力は変わりません。Anthropic の判定ロジックから見たときに「system は共通、user に個別情報」という形に見えるだけです。
ステップ6:チーム共有スクリプトに展開する
同じパターンは、社内メンバー5人が同じ claude -p ベースのスクリプトを叩く構成にも使えます。Makefile やコマンド入力画面用のスクリプトに --exclude-dynamic-system-prompt-sections を入れておけば、5人それぞれのマシンで叩いても、共通の system 部分は同じ照合キーになります。
つまり --exclude-dynamic-system-prompt-sections は何をしてくれるのか
- やってくれる:マシン固有の4セクションを system プロンプトから user メッセージの先頭に移動する
- やってくれる:その結果、複数マシンで同じスクリプトを叩いたとき、共通の system プロンプトが Anthropic 側で使い回される
- やってくれない:他のシステムプロンプト要素を消すこと。ツール案内・安全対策・コーディング規約は system 側に残る
- やってくれない:違う質問文を投げているマシン同士で保存済みデータを共有させること。質問が違えば user 側も別物になる
- 意味が薄い場面:1人が1台で
claudeを叩いているケース。元から system が一致して保存分が効いている - 意味が薄い場面:対話モード、つまり
-pを付けずに起動して会話する使い方。複数ユーザーで保存を共有する旨味がほぼ無い
使いどころ3シナリオ(具体題材で再現)
シナリオ1:GitHub Actions の matrix で OS 3種類の runner が並列に走る PR レビュー bot
PR が立つたびに、Ubuntu / macOS / Windows の3 runner で同じ「差分を要約して」スクリプトが走る構成です。何もしないと、3 runner ごとに別の照合キーが切られて、保存は温めるだけ温めて使い回せません。--exclude-dynamic-system-prompt-sections を1個足すと、共通の system プロンプトが再利用できるので、2台目と3台目の runner はトークン代が割引される計算になります。
月に100本 PR が立つチームなら、これだけで地味に効きます。
シナリオ2:5人チームの全員が同じ make summarize を自分のマシンから叩く
社内のレビュー支援スクリプトを Makefile にまとめて、メンバー全員が make summarize で呼べるようにしている、みたいな運用です。各人のマシンの作業フォルダや内部のメモリ置き場は当然違うので、何もしないと5人分の保存データが別々に温まります。Makefile の中で claude -p --exclude-dynamic-system-prompt-sections "..." の形にしておけば、誰かが先に叩いた保存に後の人が乗れます。
シナリオ3:自社の SaaS サーバーから複数の顧客アカウント宛てに同じ claude -p を叩く
自社サービスの裏で、Anthropic の API を介して複数顧客分の処理を回しているケースです。顧客ごとにコンテナ(独立した実行環境のこと)が立ち上がる構成だと、コンテナの作業フォルダや環境情報が顧客ごとに違って、共通スクリプトでも system プロンプトが顧客ごとに分裂します。このスイッチで共通化すれば、サーバー全体の保存再利用率が上がる、という使い方ができます。
初心者が踏みやすい落とし穴
--system-promptまたは--system-prompt-fileを一緒に使うと黙って無視される。公式は "ignored when --system-prompt or --system-prompt-file is set" と書いていて、エラーも警告も出ません。気づくのに時間がかかる罠です。差し替え系と一緒に使いたいなら、追加系の--append-system-promptや--append-system-prompt-fileと組み合わせる方を選びます- 移動先は「最初の user メッセージ」。後段で user メッセージを切り出して別処理に流すスクリプトを書いていると、想定外のメタ情報が先頭に紛れ込みます。
--output-format stream-jsonで受けて型ごとに振り分ければ問題ないですが、素朴に user 文字列を切り出すパースは要見直し - 対象は4セクションだけ。作業フォルダ、環境情報、メモリ置き場、git管理下かどうかの印、この4つだけが移動します。ツール案内や安全対策の文言は system に残るので、「全てのマシン固有情報が消える」とは思わない方が無難
- 同じ質問を投げているときだけ効く。複数 runner で違う質問文を投げているなら、user 側が別物なので保存分は元から共有できません。共通の system だけが対象です
- 対話モードでは旨味がほぼ無い。
-pを付けない普段使いでは、そもそも複数ユーザーで保存を共有する話にならないので効果がほぼ出ません。公式の例も-p付きで書かれています - バージョン番号を推測で書かない。公式の更新履歴で、このスイッチがいつ追加されたかの記載が私の確認範囲では見つかりませんでした。「いつから使える」を断言せず、
claude --helpまたは公式の CLI リファレンスで動作確認するのが安全です - 名前が長いのでタイポしやすい。
--exclude-dynamic-system-prompt-sectionsは一発で正しく書ける長さじゃありません。コマンド履歴か Makefile に保存しておく運用がおすすめです
書き方
claude -p --exclude-dynamic-system-prompt-sections "質問文"
やってみるとこうなる
入力
claude -p --exclude-dynamic-system-prompt-sections "summarize the diff in this PR"
出力例
通常の `claude -p` と同じ応答が返る。違いは内部のメッセージ構造で、システムプロンプトから4要素が外れて user 側の先頭に移動している。`--output-format stream-json` で受けると result イベントの usage に `cache_read_input_tokens` が出るので、2台目以降の実行で値が増えていれば共通システムプロンプトの再利用が効いている
このページに出てきた言葉
- prompt cache
- Anthropic 側でシステムプロンプト等の長い前置きを保存しておき、同じ内容が来たら次回以降トークン代を割り引く仕組み
- システムプロンプト
- ユーザーの質問より先に AI に役割や前提を伝える「下準備の説明書」。<code>claude</code> はこれを自動で組み立てている
- ダイナミックセクション
- システムプロンプトの中で「マシンごとに値が変わる」4つの記述(作業フォルダ/環境情報/メモリ置き場/git管理下かどうかの印)
- CI
- Continuous Integration の略。コードを変更するたびに自動でテストや処理を回す仕組み
- matrix runner
- GitHub Actions で、同じ処理を OS違い・バージョン違いで並列実行するときの個々の実行用仮想マシン
- cache_read_input_tokens
- API 応答の usage に含まれる、保存済みデータから読み出せたトークン数。多いほど再利用が効いている証拠