Claude Media
claude plugin --accept-commandでインストールコマンドを承認する

claude plugin --accept-commandでインストールコマンドを承認する

--json実行が返すshownCommandのsha256を--accept-commandに渡し、表示済みのインストールコマンドだけを承認する手順です。効かない場面と再表示される条件も押さえます。

claude plugin --accept-commandでインストールコマンドを承認する

claude plugin installに--accept-command <sha256>を付けると、直前の--json実行で表示されたインストールコマンドだけを承認できます。-yのように「何が表示されても通す」フラグではなく、ハッシュ値で対象を固定する承認です。Claude Codeのv2.1.271以降で使えます。

--accept-commandは何を承認するフラグか

マーケットプレイスのエントリがコマンドを実行してインストールする場合や、ダウンロードにheadersHelperを設定している場合、Claude Codeはインストール前にコマンドを表示し、Run this command now?と尋ねます。対話端末ならここで承認すれば済みます。

困るのはスクリプトやCIです。標準入力か標準出力がTTYでないとき、-yも--accept-commandも付けなければインストールは拒否されます。出力には「コマンドは表示しただけ」と出て、終了コードは1です。-yは表示されたコマンドをそのまま通すため、内容を見ないまま承認することになります。

--accept-commandは、その中間の選択肢です。

くらべる

-yと--accept-commandの承認範囲

v2.1.229以降

-y, --yes

表示されたコマンドなら何でも通します。--accept-commandとは併用できません。

v2.1.271以降

--accept-command <sha256>

前回の--json実行で表示されたコマンドだけを通します。-yとは併用できません。

plugin installとplugin updateの両方に用意されたフラグです。

使うための前提バージョン

この手順は2つのフラグの組み合わせで成り立ち、要件のバージョンが別々です。

あゆみ

関連フラグが入ったバージョン

  1. v2.1.229-y(--yes)

    表示されたインストールコマンドを、プロンプトなしで承認できます。

  2. v2.1.268--json

    結果を最終行のJSONで返し、shownCommandを読めるようにします。

  3. v2.1.271--accept-command

    shownCommandのsha256を渡して、そのコマンドだけを承認します。

--jsonだけ使えて--accept-commandが使えないのはv2.1.268から270の範囲です。この範囲では、コマンドの表示までは自動化できても、ハッシュ値による承認は使えません。claude --versionで先に確認しておくと、途中で「不明なオプション」と言われずに済みます。

手順: 表示、確認、承認の3段階

承認は2回のコマンド実行に分けます。

手順

承認までの3段階

  1. 1

    表示させる

    --jsonを付けてplugin installを実行します。コマンドは実行されず、表示だけで終わります。

  2. 2

    人が確認する

    出力最終行のJSONからshownCommandを読み、表示されたコマンドが妥当かを見ます。

  3. 3

    承認して再実行する

    shownCommandのsha256を--accept-commandに渡して、同じインストールをもう一度実行します。

# 1回目: コマンドは実行されず、failedの結果が返る
claude plugin install my-plugin@my-marketplace --json | tail -n 1 \
  | tee result.json
 
# 2回目: shownCommandのsha256だけを取り出して承認する
claude plugin install my-plugin@my-marketplace \
  --accept-command "$(jq -r '.shownCommand.sha256' result.json)"

--jsonを付けると、標準出力の最終行に結果のJSONオブジェクトが1つ出ます。マーケットプレイスが宣言したコマンドはその前に表示されるため、パースするのは最終行だけにします。tail -n 1はそのための切り出しです。

1回目の結果はoutcomeがfailedになり、shownCommandオブジェクトが付きます。jqの例が読むのは、そのうちsha256だけです。

2行目のコマンド置換をそのまま自動化に使うと、確認の段階が抜け落ちます。上のスクリプトは形の説明で、実運用では人がresult.jsonを開いてshownCommandの中身を見る段を挟みます。

返る出力の例(v2.1.289)

動きを見るには、commandソースのプラグインを1つ持つ最小のマーケットプレイスを作るのが早道です。commandには、ディレクトリのパスを1行で出して終わる、害のないコマンドを置きます。

mkdir -p demo/mp/.claude-plugin demo/pl/.claude-plugin
echo '{"name":"demo-plugin","version":"1.0.0"}' \
  > demo/pl/.claude-plugin/plugin.json
cat > demo/mp/.claude-plugin/marketplace.json <<EOF
{"name":"demo-mp","owner":{"name":"demo"},
 "plugins":[{"name":"demo-plugin","source":
  {"source":"command","command":"printf $PWD/demo/pl"}}]}
EOF
claude plugin marketplace add ./demo/mp

HOMEとCLAUDE_CONFIG_DIRを空の一時ディレクトリに向けて実行すると、ふだんの設定を汚さずに試せます。

非対話の環境で--jsonを付けてinstallすると、先に人間向けの説明が出ます。

"demo-plugin" is installed by running a command from marketplace "demo-mp" on this machine:
  printf /tmp/demo/pl
  (mode "copy": its output directory is copied into the plugin cache)
Not an interactive terminal, so the command was only displayed, not accepted. ...

最終行のJSONは次の形です(読みやすいよう整形し、messageは省いています)。

{
  "command": "install",
  "outcome": "failed",
  "plugin": "demo-plugin@demo-mp",
  "scope": "user",
  "failureCode": "command_source_refused",
  "shownCommand": {
    "kind": "command_source",
    "pluginId": "demo-plugin@demo-mp",
    "command": "printf /tmp/demo/pl",
    "mode": "copy",
    "catalogRevision": "sha256:eaf02cfd…",
    "sha256": "45a9843d…"
  }
}

sha256のほかに、catalogRevisionが入っています。承認が「コマンド、プラグイン、カタログ」の3点組で効く話は、このフィールドと対応します。またfailureCodeがcommand_source_refusedなので、スクリプトは文言ではなくこの値で分岐できます。

ここで2>&1を付けると、JSONの後ろにエラーメッセージが重なって出ます。最終行を切り出すときは、標準エラー出力を混ぜません。

JSON結果の基本フィールド

--jsonの結果には、常に入る3つのフィールドがあります。

フィールド中身
command中身実行したサブコマンド(installなど)
outcome中身okかfailed
message中身結果を説明する文

pluginId、scope、failureCodeのようなフィールドは、当てはまるときだけ付きます。スクリプトではoutcomeで成否を分け、failedのときにshownCommandがあるかを確認する順になります。shownCommandが付くのは、マーケットプレイスが宣言したコマンドを表示しただけで実行しなかった場合です。

--jsonはplugin update、plugin uninstall、plugin enable、plugin disableにもあり、同じ形のオブジェクトを返します。--scopeの値が不正といった使い方の誤りでは、結果行は出ず、理由が標準エラー出力に出て終了コード1で終わります。この場合に最終行をパースすると、JSONではない行を読むことになります。

セッション内では効かない

--accept-commandは、Claude Codeのセッションの外、つまり自分の端末で実行したときにだけ意味を持ちます。セッション内のBashツールやhooksから実行しても、フラグは効きません。-yも同じで、Claude自身がBashツール経由で走らせたインストールでは無視されます。

v2.1.289の実機では、Claude Codeのセッション内で正しいsha256を渡して実行しても、acceptCommandMatchedはtrueなのにoutcomeはfailedのままで、1回目と同じcommand_source_refusedが返ります。ハッシュが合っていることと、承認が通ることは別です。同じコマンドをenv -iで環境変数を落とした端末から実行すると、Successfully installed plugin: demo-plugin@demo-mp (scope: user)で終わります。

Claudeに任せられるのは--json実行によるコマンドの表示までです。承認の実行は自分の端末で行う分担になります。

Claudeにプラグイン導入を手伝わせるなら、CLAUDE.mdに次の1行を置いておくと、承認の段だけ人に戻せます。

プラグインのインストールで「コマンドが表示された」と出たら、
自分では承認せず、`--json`の結果(shownCommand)を私に見せて止まること。

コマンドが変わると再表示される

sha256が承認として通るのは、表示されたコマンド、プラグイン、マーケットプレイスのカタログの3つがすべて同じときだけです。どれか1つでも変わると、Claude Codeはsha256を受け付けず、コマンドをもう一度表示します。

見落としやすいのは、同じ実行の中で起きる更新です。実行時にマーケットプレイスを更新して取得された変更も、「変わった」ものとして数えられます。つまり、1回目と2回目の間にマーケットプレイス側が更新されていれば、ハッシュ値は無効になりえます。

acceptCommandMatchedがfalseのとき

再表示された結果には、shownCommand.acceptCommandMatchedが含まれます。この値がfalseなのは、渡したsha256が今表示されているコマンドと一致しないときです。v2.1.289の実機では、適当な値(deadbeef)を渡すと、falseの入った結果が終了コード1で返ります。1回目の結果にはこのキー自体がありません。

対応は、その場で新しいコマンドを読み直すことです。公式の指示も、渡し直す前に表示中のコマンドを確認するよう求めています。falseが返ったからといって、新しいsha256をそのまま機械的に渡し直すのは、--accept-commandが守るはずの確認を省くことになります。

状況起きること取るべき動き
表示したコマンドとsha256が一致起きることそのコマンドが承認され、インストールが進む取るべき動きなし
コマンド・プラグイン・カタログのいずれかが変わった起きること承認されず、コマンドが再表示される取るべき動き新しいコマンドを読み、問題なければ新しいsha256で再実行
acceptCommandMatchedがfalse起きること渡した値と今のコマンドが食い違っている取るべき動き表示中のコマンドを確認してから再実行
セッション内で実行した起きることフラグが効かない取るべき動き自分の端末から実行し直す

plugin updateでの使い方

plugin updateにも同じ--accept-commandがあります。コマンドソースのcommandやmodeをマーケットプレイス側が変更すると、インストール済みの利用者は新しいコマンドを承認するまで更新が止まります。/pluginのErrorsタブに新しいコマンドと、実行すべきclaude plugin updateが出ます。

非対話の環境では、plugin updateも-yか--accept-commandが必須です。claude plugin update --helpの-yの説明は「変更されたインストールコマンド」を承認するものと書かれており、installの「表示されたコマンド」とは言い回しが違います。--scopeの既定値も、installのヘルプはuser、updateは自動検出です。流れはinstallと同じで、--jsonで表示させ、確認し、sha256を渡します。

--scopeを省くと、ローカル、プロジェクト、ユーザー、管理の順に、今のプロジェクトで最も狭くインストールされているスコープが対象になります。v2.1.281より前はユーザースコープ固定で、プロジェクトやローカルだけに入れたプラグインの更新は失敗しました。その場合は--scopeを明示します。同名のプラグインが複数のマーケットプレイスにあるときは、plugin-name@marketplace-nameの形で指定します。

claude plugin update my-plugin@my-marketplace --json | tail -n 1
claude plugin update my-plugin@my-marketplace \
  --accept-command <確認したsha256>

--accept-commandが使えない経路

承認できるのは、プラグインを1つだけインストール、または更新する操作に限られます。それ以外の操作では、コマンドは実行されず、アーカイブもダウンロードされません。プラグインはインストール済みのバージョンのまま、または未インストールのままです。

経路起きること
複数プラグインの一括インストール起きることコマンドを持つプラグインだけ拒否され、/pluginの画面から入れ直すよう案内される。ほかのプラグインは入る
プラグイン提案からの導入起きること同じく拒否される
他のプラグインの依存としての導入起きること拒否される。依存元は、拒否されたプラグインを単体で入れるまでインストールに失敗する
バックグラウンドの自動更新、またはアーカイブ未取得のプラグインのセッション開始時起きること/pluginのErrorsタブに載り、利用者が自分でインストールか更新をする

plugin installやplugin updateに--accept-commandを付けても、これらの経路は通せません。該当するプラグインを、1つずつinstallまたはupdateします。headersHelperの設定側の事情はプラグインのzip配布で確認できます。

headersHelperの承認が失効する条件

headersHelperを持つプラグインでは、承認したコマンドと、表示されたアーカイブのURLの組が対象です。承認から実行までの間にコマンドかアーカイブのURLが変わると、Claude Codeはインストールも更新も拒否します。ただしクエリ文字列だけの変更は、変更に数えられません。

承認したコマンドはあとで再実行される

commandソースのプラグインは、承認したコマンドを一度走らせて終わりではありません。Claude Codeは、承認したそのコマンドを次のタイミングでも実行します。

  • プラグインをインストールまたは更新するたび
  • セッションが始まって少し経つと、有効なコマンドソースのプラグインごとに1回、バックグラウンドで
  • 起動時か/reload-pluginsで、有効なプラグインのインストール済みバージョンがキャッシュに無いとき

バックグラウンドの2種類は、CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFICを設定すると止まります。ただしインストールと更新での実行は、この変数があっても止まりません。コマンドの出力から作られるハッシュが変わっていれば、新しいバージョンとして入り、稼働中の対話セッションで再読み込みされます。

この挙動があるため、sha256の承認は1回きりの許可より重い意味を持ちます。承認したコマンドは、以後セッションのたびに走る前提だからです。--accept-commandで固定する価値は、表示内容を確認したうえで、その実行を許すところにあります。

よくあるつまずき

  • -yと一緒に付けた: error: option '--accept-command <sha256>' cannot be used with option '-y, --yes'で止まります。どちらか一方を選びます。
  • --jsonなしでsha256を探した: shownCommandは--json実行の結果に載るものです。先に--json付きで表示させます。
  • v2.1.271より前のバージョンで使った: フラグ自体が存在しません。-yは別で、v2.1.229以降です。
  • TTYのある端末でsha256を渡した: 対話端末なら確認プロンプトで承認できるため、この手順は必須ではありません。自動化したい場面で効きます。
  • 結果の先頭行をパースした: JSONは最終行です。マーケットプレイスが宣言したコマンドの表示が先に出るため、先頭行では読めません。

インストールオプション全体はplugin init/installの全オプションに、v2.1.271の位置づけはリリースノートにあります。

使い分けの目安

--accept-commandは、コマンドを表示した内容ごと固定して承認する方式です。-yは表示内容を問わない方式です。CIに組み込むなら、-yで全部通すより、1度人が確認したコマンドだけを通せる--accept-commandのほうが、マーケットプレイス側の変更に巻き込まれにくくなります。

まとめ

CIで使うなら、1回目の--jsonを回すジョブと、承認して再実行するジョブを分け、間に人のレビューを挟む形が合います。ハッシュ値をスクリプトで拾ってそのまま渡す運用は、-yと同じく確認を飛ばすことになります。

この記事を共有:XはてブLinkedIn