--permission-prompt-tool(パーミッションプロンプトツール)

起動オプション
--permission-prompt-tool
パーミッションプロンプトツール
Claude Code を <code>-p</code>(無人モード)で動かすときに出る「実行していい?」の確認を、自前のMCP関数に肩代わりさせる起動指定。判定関数を指定する際の正確な関数名フォーマット(アンダースコア1本か2本か、サーバー名を含めるかなど)は公式ドキュメントに詳細記載がないため、起動ログや <code>--debug</code> で実認識名を確認するのが安全。

CI/CDで claude -p を回しているが、許可確認画面で止まる問題に当たっていて、MCPの関数に判定を任せたい人向け

GitHub Actions などのCI環境で <code>claude -p</code> を回したいが、Bash 実行や git 操作のたびに許可確認が出て止まってしまうとき。さらに「<code>npm test</code> はOK、<code>git push --force</code> はNG」みたいな複雑な判定を自前のMCP関数に書きたい場面で、<code>claude -p --mcp-config ./mcp.json --permission-prompt-tool <判定関数名> "query"</code> の形で叩く。

CIで claude -p "テストを回してから commit して" みたいに走らせると、Claude Code は実行直前に「これ実行していい?」の確認を出します。人間が前に座っているなら yes/no を押せばいいんですが、GitHub Actions のように無人で動く環境だと、その確認画面でジョブが固まる。

これを「許可判定する係」をMCPの関数1つに肩代わりさせるのが --permission-prompt-tool。許可ロジックを自分で書いた関数の中に集約できるので、CI 専用の判定ルールを自由に組めます。たとえば「npm testnpm run lint は通す、それ以外は拒否」みたいな振る舞いを、自前で書き込める。

とはいえ、初手で使うべきものではないです。

噛み砕くと

普段の Claude Code は、危ない操作の手前で必ず「これ実行していい?」と聞いてきます。ファイル書き換え・コマンド実行・git push などが対象。画面の前に人間がいれば押せばいい。

でも CI は無人なので、その確認画面で動かなくなる。

解決のやり方は2つあります。1つは「事前に許可リストを渡して、聞かずに実行させる」--allowedTools 方式。もう1つが今回の --permission-prompt-tool で、こっちは「許可判定を外部の関数に丸投げする」やり方です。判定関数の中で時刻を見たり、外部 API に問い合わせたりして「許可 / 拒否」を返せるので、複雑な条件分岐が必要なときに効きます。

大事な前提:-p モードでしか効かない

--permission-prompt-tool は「人間が画面の前にいない」前提で動くので、対話セッションでは完全に無視されます。claude だけで起動した普通の対話画面で書いても効かない。必ず -p と組み合わせて使う。-p--print の短縮形で、「1回叩いて結果を返して終わる無人モード」のことです。

もう1つ前提があって、MCP の判定関数自体は別途登録しておく必要があります。--mcp-config ./ci-mcp.json でセッション限定で繋ぐか、ユーザー設定に登録済みの状態で叩く。判定関数が見つからないと「そんな関数ないよ」で落ちます。

「GitHub Actions で claude -p を回す」を例に、実際の手順を見る

状況設定はこう。GitHub Actions のジョブ内で claude -p "Run all integration tests, commit if green" を走らせたい。Claude Code は内部で npm test を実行し、通れば git addgit commitgit push まで走らせる。途中の Bash 実行や git 操作で全部「実行していい?」の確認が走るので、それを CI 用の判定関数に肩代わりさせる、という流れです。

ステップ1: 判定用の MCP サーバーを用意する

MCP サーバー側に「許可判定の関数」を1つ実装します。実装の中身は MCP 側の話なのでここでは深追いしません。関数名は approve としておきます。中身としては「来たリクエストが Bash(npm test)Bash(npm run lint)Bash(git ...) なら許可、それ以外は拒否を返す」程度の素朴な判定でOK。

ステップ2: ローカルの設定ファイルに MCP サーバーを登録する

プロジェクト直下に ci-mcp.json を置きます。中身は MCP サーバーの起動コマンドと接続情報。

{
  "mcpServers": {
    "ci_approver": {
      "command": "node",
      "args": ["./mcp-ci-approver/index.js"]
    }
  }
}

登録名 ci_approver の中で公開した関数 approve を、Claude Code が内部でどう参照するかは公式ドキュメントに詳細記載がありません。cli-reference の Example では mcp_auth_tool(アンダースコア1本)の形式が示されています。MCP プロンプトの慣例では mcp__<server>__<tool> 形式(ダブルアンダースコア)も使われますが、--permission-prompt-tool 専用の表記ルールは公式に明記がないため、起動時のログや --debug を付けて認識された関数名を確認するのが確実です。

ステップ3: GitHub Actions の workflow から叩く

.github/workflows/claude-ci.yml でこう書きます。

- name: Run Claude CI
  run: |
    claude -p \
      --mcp-config ./ci-mcp.json \
      --permission-prompt-tool <判定関数名> \
      "Run all integration tests, commit if green"

この3行が揃ってはじめて動きます。--mcp-config で判定関数を読み込み、--permission-prompt-tool で「許可判定はこいつに任せる」と指定。-p で無人モード起動。関数名の正確な表記は前段で書いた通り、起動ログを見て決めるのが安全です。

ステップ4: Claude Code が走る

Claude Code が npm test を実行しようとすると、内部で判定関数に「Bash(npm test) を実行してもいい?」を問い合わせます。判定関数が許可を返せばそのまま実行、拒否を返せばブロックされます。返り値の具体的な JSON 形式(フィールド名・値のフォーマット)は公式ドキュメントに明記されていないため、Claude Code のリリースノートや実装例・コミュニティの実例を参照して確認してください。本記事では概念的な「許可 / 拒否」の判定があるという話に留めます。

ここで初心者がやりがちな勘違いがあります。判定関数が「保留」を返した場合、対話モードなら人間に聞きに行きますが、-p モードでは聞ける相手がいないのでブロック扱いになります。「保留」が「拒否」と同じ結果になる点には注意。

ステップ5: 通れば git 操作も走る

テストが通れば、Claude Code が次に git add . git commit -m "..." git push を順に実行します。判定関数の中で「git ... 始まりは許可」を実装していれば、人間の介入なしで全部走り切ります。

ステップ6: ログで判定経過を確認

判定関数の中で console.error で「何を許可した / 何を拒否した」を吐いておくと、GitHub Actions のログに残ります。後から「あれ、ここでなんで止まったんだ?」が追えるので、初期構築のうちはログを厚めにしておくのが安全です。

つまり --permission-prompt-tool は何をしてくれるのか

  • やってくれる: -p モードで Claude Code が出す許可確認を、自前の MCP 関数に振り分ける。判定関数の中で時刻・分岐・外部 API 問い合わせ等の複雑なロジックを組める
  • やってくれない: 対話モードの許可確認には一切影響しない。あくまで無人モード専用
  • 意味が薄い場面: 許可したい道具が Bash(npm test) みたいに固定リストで済むなら、シンプルに --allowedTools を使った方が速いし軽い。判定関数を呼ぶたびに往復が発生するので、毎ターン遅くなる

使いどころ3シナリオ(具体題材で再現)

シナリオ1: 個人開発の OSS で「テスト通ったら自動でリリース PR を作る」

例えば自作の家計簿アプリの GitHub プロジェクトで、main ブランチへのマージごとに claude -p "Run tests, bump version, open release PR" を回したい。判定関数の中で Bash(npm test) Bash(npm version patch) Bash(gh pr create ...) は許可、それ以外は拒否、と書いておく。万一 Claude Code が予期せぬコマンドを叩こうとしても、判定関数が止めてくれる。

シナリオ2: 業務プロジェクトで「時間帯によって許可範囲を変える」

例えば社内の決済システムで、平日昼間は git push も許可するが、深夜と週末は読み取り系の操作だけ許可する、みたいな運用が必要なケース。--allowedTools だけだと固定リストしか書けないので無理。判定関数の中で new Date() を見て「今は深夜だから push 系は拒否」と判定する。これは --permission-prompt-tool でないと書けない領域です。

シナリオ3: 監査ログを残したい SaaS 開発チーム

例えば医療系・金融系で「Claude Code がいつ何を実行したか」を全部ログ DB に残す必要があるケース。判定関数の中で、許可・拒否の判定結果を毎回ログサーバーに POST してから返す。--allowedTools だとログが取れないので、判定の中継地点を1個挟むためだけでも --permission-prompt-tool を使う価値があります。

初心者が踏みやすい落とし穴

  • 対話モードでは無視されるclaude --permission-prompt-tool xxx だけ書いても効きません。-p とセットで初めて動く。
  • 判定関数の指定名フォーマットは公式 docs に詳細記載がない。cli-reference の Example では mcp_auth_tool(アンダースコア1本)が示されており、MCP プロンプトの慣例では mcp__<server>__<tool>(ダブルアンダースコア)が使われますが、--permission-prompt-tool 専用の表記ルールが verbatim で書かれた箇所は確認できません。起動ログや --debug で実際に認識される名前を確認するのが確実です。
  • 判定関数が「保留」を返すと拒否扱い。無人モードでは聞ける相手がいないので、保留が拒否と同じ結果になる。判定関数の中では明示的に許可・拒否のどちらかを返す設計にしないと、想定外の場面で全部ブロックされる。
  • 判定関数の中身が雑だと、結局なんでも通る。「これを使えば安全」みたいな話ではないです。判定関数の中で「Bash 系は全部許可」みたいな書き方をしていれば、Claude Code が rm -rf / を叩こうとしても素通りする。判定ロジックの厚みがそのまま安全性の厚み。
  • --allowedTools で済むなら、そっちを使う。判定関数を呼ぶたびに往復が走るので、ターン数が多いと体感で遅くなるし API コストも上振れする。固定リストで足りるケースは --allowedTools、複雑なロジックが要る場合だけ --permission-prompt-tool
  • MCP サーバー側の起動失敗に気付きにくい--mcp-config で繋ごうとした MCP サーバーが何らかの理由で立ち上がっていないと、判定関数も呼び出せず、Claude Code は「許可されていない」として全実行をブロックする。CI のログを見ると Claude Code が無言で何もしていないように見えるので、まず MCP サーバーの起動ログを確認するのが鉄則。
  • 判定関数の返り値フォーマットも公式 docs に明記がない。「許可」「拒否」をどんな JSON で返すべきか、フィールド名や値の取り得る範囲は cli-reference・headless・mcp 各 docs のいずれにも verbatim で記載されていません。Claude Code のリリースノートや実装例・コミュニティ事例を見ながら、最新の挙動に合わせる必要があります。
  • --permission-mode bypassPermissions と混同しない。これは「全部許可、確認なし」の危険モードで、判定関数すら呼ばれません。CI で焦って bypassPermissions を使うと、Claude Code が git push --force origin main でも何でも素通りで実行する。事故りやすいので、慣れないうちは --permission-prompt-tool で判定を挟む方が安全です。

書き方

claude -p --permission-prompt-tool <mcp判定関数名> "query"

やってみるとこうなる

入力

claude -p \
  --mcp-config ./ci-mcp.json \
  --permission-prompt-tool <判定関数名> \
  "Run all integration tests, commit if green"

出力例

(Claude Code が npm test 等を実行するたびに判定関数が呼ばれ、許可が返れば実行・拒否が返ればブロック。ログ上は通常の -p モード出力に、判定経過の標準エラー出力が混ざる形。返り値の具体的なJSONフォーマットは公式docs未記載のため、リリースノートや実装例を参照のこと)

このページに出てきた言葉

CI
Continuous Integration の略。コードを変更したら自動でテスト・ビルドを走らせる仕組み。GitHub Actions が代表例
MCP
Model Context Protocol。Claude Code から外部のプログラムを呼び出せるようにする差し込み口
<code>-p</code> モード
<code>--print</code> の短縮形。Claude Code を「1回だけ走らせて結果を返して終わる」無人モードで起動する書き方
判定関数の指定名
<code>--permission-prompt-tool</code> に渡す MCP 関数の名前。cli-reference の Example では <code>mcp_auth_tool</code>(アンダースコア1本)が示され、MCPプロンプトの慣例では <code>mcp__<server>__<tool></code>(ダブルアンダースコア)も使われるが、<code>--permission-prompt-tool</code> 専用の表記ルールは公式に明記がない。起動ログや <code>--debug</code> で実認識名を確認するのが確実
許可 / 拒否 / 保留
判定関数が返す3種の概念的な結果。返り値の具体的な JSON フォーマットは公式 docs 未記載のため、リリースノートや実装例を参照。<code>-p</code> モードでは「保留」は聞ける相手がいないので拒否扱いになる
bypassPermissions
<code>--permission-mode bypassPermissions</code> の指定。全部許可で確認なしの危険モード。<code>--permission-prompt-tool</code> は呼ばれない

関連項目

公式ドキュメント

https://code.claude.com/docs/en/cli-reference

-

← 戻る