3行でいうと
- ヘッドレス(非対話)は、
-p(--prompt)を付けるか、TTYのない環境で動かすと始まります。出力はtext、json、stream-jsonから選べ、終了コードは0、1、42、53の4つが公式に書かれています。ただし、公式のヘッドレスのページには、ツールの承認の扱いの説明が見つかりませんでした。信頼するフォルダを有効にしている場合、未信頼のフォルダではFatalUntrustedWorkspaceErrorで止まるので、--skip-trustかGEMINI_CLI_TRUST_WORKSPACE=trueの判断が要ります。 - MCPは
settings.jsonのmcpServersに書くか、gemini mcp addで足します。公式は、起動するサーバーの環境から*TOKEN*や*KEY*などの名前の変数を自動で取り除く、と書いています。サーバーに渡したい鍵は、envに明示します。trust: trueは、そのサーバーの確認を全部飛ばす設定です。 - Extensionsは、MCP、カスタムコマンド、フック、スキルなどを1つにまとめて配る形式です。公式のギャラリーは「Googleは、これらの拡張の機能や安全性を審査も保証もしない」と書いています。入れる前に中身を読むのが前提です。
- GitHub Actionの
run-gemini-cliには、公式の完成した例(dispatch、review、triage、invoke)があります。信頼できない入力(forkのPR、外部の人のissue)を扱うときの注意が、公式のページに具体的に書かれています。
この記事は、実際に使って確かめた記録ではありません。運営者はGeminiを入れていますが、使い心地はこの記事には書いていません。この記事は、2026年10月24日に公式ドキュメントを読んでまとめたものです。コマンド、設定のキー、YAMLやJSONの例は、公式に書かれたとおりに写しました(空行などの体裁は整えています)。ワークフローのYAMLのうち、公式のファイルを要約の形でしか読めなかったものは、そのとおりに断って「構造」として書き、僕らが部品を組み合わせた例には、そのつど「組み合わせです」と書いています。取得したのはWebFetchによる要約なので、読み切れていない箇所があります。Gemini CLIの導入とGEMINI.md、MCPとExtensionsの概観は前のガイド(04、05)に、承認モード、信頼するフォルダ、サンドボックス、ポリシーは前のガイド(06)に書いたので、ここでは、実際に使う手順に踏み込みます。
先に結論
- 最初に決めるのは「誰がいない場所で動かすか」です(僕らの整理です)。 手元の対話なら、確認の画面が最後の砦です。
-pやGitHub Actionでは、事前の設定(ポリシー、includeTools、tools.core、ワークフローのpermissions)が砦になります。 - MCPは、鍵の渡し方と、使える道具の絞り方が要です。
env、includeTools、trust、サーバー名の付け方に、公式の注意があります。 - Extensionsは、入れるのも作るのも手順が決まっています。
gemini extensions install、link、new、config。拡張の中のポリシーでallowは無視される、と公式に書かれています。 - GitHub Actionは「公式の完成品を写して、権限を絞る」のが近道です。 公式は、Workload Identity Federationと、自作のGitHub Appを勧め、forkからの実行は既定で止めています。
- 公式が書いていないこと。 ヘッドレスでの承認の扱い、カスタムコマンドの
!{...}の確認が非対話でどうなるか、は読んだ範囲では見つかりませんでした。本文の該当箇所で、そのつど書きます。
前提:用語をそろえる
- ヘッドレス(非対話)実行:対話画面を出さず、テキストかJSONを返して終わる実行です。公式は、TTYでない環境か、
-pを付けたとき、と書いています。 - MCP(Model Context Protocol)サーバー:外の道具やデータをGemini CLIにつなぐ別プロセスです。公式は、ツール、リソース、プロンプトを渡せる、と書いています。
- Extensions(拡張):プロンプト、MCPサーバー、カスタムコマンド、テーマ、フック、サブエージェント、スキルを1つの形式にまとめて配るものです。中心は
gemini-extension.jsonです。 - カスタムコマンド:TOMLで書いた、自分用のスラッシュコマンドです。
- run-gemini-cli:GitHub Actionの上でGemini CLIを動かす、公式のAction(google-github-actions/run-gemini-cli)です。
- WIF(Workload Identity Federation):GitHubのOIDCトークンで、長く使う鍵を置かずにGoogle Cloudへ認証する方式です。
先に確かめること:2026年6月18日の告知
前のガイド(05)に書いたとおり、geminicli.comのほとんどのページの冒頭に、「無料枠とGoogle Oneの利用者は、2026年6月18日にAntigravity CLIへ移った」という趣旨の告知があります。この記事の例は、その告知付きのページ(ヘッドレスは更新2026年3月10日、自動化の手引きは3月9日、拡張のリファレンスは5月14日)に書かれたものです。自分の認証方式が今も使えるかは、先に確かめてください。
ヘッドレス実行:-p で、人のいない場所の入口に立つ
どう始まるか
公式のヘッドレスのページは、ヘッドレスモードを「対話のUIなしで、テキストかJSONを返す仕組み」と説明しています。始まる条件は2つです。TTYのない環境で動かすか、-p(--prompt)で問いを渡すかです。自動化の手引きは、-p なしの位置引数は、入力か出力がパイプやリダイレクトされていない限り、対話モードを始める、と書いています。CLI参照の表では、-p は「標準入力があればその後ろに足され、非対話を強制する」とされています。
公式の例は、次のとおりです。
gemini -p "Write a poem about TypeScript"
cat error.log | gemini -p "Explain why this failed"
git diff | gemini -p "Write a commit message for these changes"
WindowsのPowerShellでは Get-Content error.log | gemini -p "..." と書く、と公式の手引きにあります。
関係するフラグ(CLI参照より)
| フラグ | 別名 | 既定 | 公式の説明の要点 |
|---|---|---|---|
--prompt |
-p |
なし | 問いの文。標準入力に足される。非対話を強制する |
--prompt-interactive |
-i |
なし | 問いを実行して、そのまま対話に入る |
--output-format |
-o |
text |
text、json、stream-json |
--approval-mode |
なし | default |
default、auto_edit、yolo、plan |
--allowed-tools |
なし | なし | 非推奨。公式は、代わりにポリシーエンジンを案内 |
--allowed-mcp-server-names |
なし | なし | 使ってよいMCPサーバー名(配列) |
--extensions |
-e |
なし | 使う拡張(配列)。省略すると、有効な拡張すべて |
--skip-trust |
なし | false |
このセッションに限り、ワークスペースを信頼する |
配列のフラグは、カンマ区切りか、複数回の指定で渡せる、と公式にあります。--yolo(-y)と --allowed-tools は非推奨で、扱いは前のガイド(06)と同じです。
-p が信頼の手前で止まることがあります。 公式の「信頼するフォルダ」のページによると、この機能は既定では無効(security.folderTrust.enabled を true にすると有効)です。有効にしていて、未信頼のフォルダで非対話(ヘッドレス)に動かすと、確認の画面を出せないため、FatalUntrustedWorkspaceError を出して終了します。回避には、--skip-trust を付けるか、環境変数 GEMINI_CLI_TRUST_WORKSPACE=true を設定します。どちらもそのセッションだけで、信頼の決定を保存しません。信頼してよいフォルダかどうかを決めてから使ってください(フォルダの信頼は06を参照)。
出力形式と終了コード
公式のヘッドレスのページに書かれている内容です。
| 形式 | 中身 |
|---|---|
json |
1つのJSON。response(最終の答え)、stats(トークン使用量とAPIの遅延)、error(失敗したときの詳細。任意) |
stream-json |
1行1イベントのJSONL。init(セッションIDとモデル)、message、tool_use、tool_result、error(致命的でない警告)、result(最終の結果と、モデルごとのトークンの内訳) |
| 終了コード | 意味 |
|---|---|
0 |
成功 |
1 |
一般のエラー、またはAPIの失敗 |
42 |
入力のエラー(プロンプトや引数が不正) |
53 |
ターン数の上限を超えた |
ターン数の上限は、公式のGitHub Actionの例で model.maxSessionTurns が25に設定されています(後の節)。ヘッドレスのページ自体には、この設定の説明は見つかりませんでした。
公式の自動化の手引きにある3つの例
公式の「Automate Tasks with Headless Mode」には、シェルスクリプトの例が3つあります。例2と例3のコードは公式のとおりです(macOS/Linux版)。
例1: フォルダ内のPythonファイルごとに、gemini -p "Generate a Markdown documentation summary for @$file. ..." > "${file%.py}.md" をループで回し、READMEを作る(公式はbashとPowerShellの両方を載せています)。
例2:JSONで結果を受け取り、jq で取り出す。 公式は、--output-format json と jq の組み合わせで、モデルが返した純粋なJSONが得られる、と書いています。
#!/bin/bash
# Ensure we are in a project root
if [ ! -f "package.json" ]; then
echo "Error: package.json not found."
exit 1
fi
# Extract data
gemini --output-format json "Return a raw JSON object with keys 'version' and 'deps' from @package.json" | jq -r '.response' > data.json
例3:ステージ済みの差分から、コミットメッセージを作る関数。
function gcommit() {
# Get the diff of staged changes
diff=$(git diff --staged)
if [ -z "$diff" ]; then
echo "No staged changes to commit."
return 1
fi
# Ask Gemini to write the message
echo "Generating commit message..."
msg=$(echo "$diff" | gemini -p "Write a concise Conventional Commit message for this diff. Output ONLY the message.")
# Commit with the generated message
git commit -m "$msg"
}
公式は、WindowsのPowerShell版も載せています。なお、例3は、生成された文をそのまま git commit -m に渡します。内容を確かめる手順は公式の例に入っていません(これは僕らの見立てです。履歴に残る文なので、最初は目で確かめてから通すのが無難だと思います)。
承認の扱いは、書かれていない
ここが大事です。公式のヘッドレスのページにも、自動化の手引きにも、ツールの承認(ファイルの書き換えやシェルの実行を、確認なしで通すか)の説明は、読んだ範囲では見つかりませんでした。前のガイド(06)に書いたとおり、ポリシーのページから読めるのは、ask_user が非対話では拒否として扱われること、書き込み系の既定が ask_user であることです。読むだけの用途(要約、説明、差分のレビュー)なら関係が薄く、書き込みをさせたいなら、先に承認の設定を決める必要があります。どう決めるかは、06の「自動化(-p)の場面」を見てください。
MCP:外の道具につなぐ
設定の書き方
公式の「MCP servers」のページは、settings.json の mcpServers に、サーバーごとの設定を書くとしています。基本の形は次のとおりです。
{
"mcpServers": {
"serverName": {
"command": "path/to/server",
"args": ["--arg1", "value1"],
"env": {
"API_KEY": "$MY_API_TOKEN"
},
"cwd": "./server-directory",
"timeout": 30000,
"trust": false
}
}
}
つなぎ方は、書いた項目で決まります。command ならstdio、url ならSSE、httpUrl ならStreamable HTTPです。主な項目は次のとおりです。
| 項目 | 公式の説明の要点 |
|---|---|
command/url/httpUrl |
どれか1つが必須。起動コマンド、SSEのURL、Streamable HTTPのURL |
args、cwd |
stdioの引数と作業フォルダ |
env |
サーバーに渡す環境変数。$VAR、${VAR}、Windowsは %VAR% も使える。未定義の変数は空文字になる |
headers |
url/httpUrl に付けるHTTPヘッダー |
timeout |
ミリ秒。既定は600,000(10分) |
trust |
true にすると、そのサーバーの道具呼び出しの確認をすべて飛ばす。既定は false |
includeTools |
このサーバーから使う道具の許可リスト |
excludeTools |
モデルから隠す道具。includeTools より優先される |
全体の許可と除外は、mcp.allowed(このサーバー名だけつなぐ)と mcp.excluded(このサーバー名にはつながない)で書けます。
公式の手順:GitHubのMCPサーバーをつなぐ(チュートリアルより)
前提は、Gemini CLI、Docker、リポジトリ権限のあるGitHubの個人用アクセストークン(PAT)です。公式は、細かい権限のPATを作り、MetadataとContentsを読み取り、IssuesとPull Requestsを読み書きにする、と書いています。トークンは環境変数に入れます。
export GITHUB_PERSONAL_ACCESS_TOKEN="github_pat_..."
~/.gemini/settings.json(またはプロジェクトの .gemini/settings.json)に、次を足します。
{
"mcpServers": {
"github": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"GITHUB_PERSONAL_ACCESS_TOKEN",
"ghcr.io/github/github-mcp-server:latest"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_PERSONAL_ACCESS_TOKEN}"
}
}
}
}
Gemini CLIを再起動し、/mcp list で、✓ github: docker ... - Connected と出れば成功です。Disconnected なら、Dockerが動いているか、トークンが有効かを見る、と公式にあります。使うときは、自然な文章で頼みます(公式の例は「List the open PRs in the google/gemini-cli repository.」)。道具が見つからないときは /mcp reload です。
コマンドで足す:gemini mcp
公式は、settings.json を手で書く代わりのコマンドも用意しています。gemini mcp add は、既定ではプロジェクトの .gemini/settings.json に書き、--scope user で ~/.gemini/settings.json に書けます(-s, --scope)。
# Stdio
gemini mcp add -e API_KEY=123 -e DEBUG=true my-stdio-server /path/to/server arg1 arg2 arg3
# HTTP
gemini mcp add --transport http --header "Authorization: Bearer abc123" secure-http https://api.example.com/mcp/
# SSE
gemini mcp add --transport sse sse-server https://api.example.com/sse/
gemini mcp add には、--include-tools と --exclude-tools(カンマ区切りで道具を絞る)、--trust(確認を全部飛ばす。使う前に下の「確認を飛ばす」の注意を読む)、--timeout、-H, --header(HTTP系)などのフラグもあります(公式のオプション一覧より)。
そのほかに、gemini mcp list(状態の一覧)、gemini mcp remove <name>、gemini mcp enable <name> と disable <name>(設定を消さずに切る。--session で今のセッションだけ)があります。list の注意として、stdioのサーバーは、信頼したフォルダの中でだけ「Connected」と表示される、とあります(フォルダの信頼は06を参照。gemini trust で今のフォルダを信頼する、と公式にあります)。
対話の中では /mcp(list、desc、schema、auth、enable、disable、reload)が使えます。公式の別ページの一覧より。
鍵の扱い:環境変数は、自動で取り除かれる
公式のMCPのページは、サーバーを起動するとき、ホストの環境から機密らしい変数を自動で取り除く、と書いています。対象は、GEMINI_API_KEY、GOOGLE_API_KEY などと、名前に *TOKEN*、*SECRET*、*PASSWORD*、*KEY*、*AUTH*、*CREDENTIAL* を含むものです。一方、サーバーの env に書いた変数は「信頼されたもの」として取り除かれません。公式は、鍵を直接書かず、"MY_KEY": "$MY_KEY" のように展開で渡すよう勧めています。上のGitHubの例が、まさにこの形です。
つまり、サーバーが動かないとき、「鍵がホストの環境にあるのに渡っていない」という原因がありえます。env に明示してあるかを見る、というのは、公式の説明から読める手順です。
使える道具を絞る、確認を飛ばす
道具の絞り込みは、サーバーの設定に "includeTools": ["safe_tool", "file_reader", "data_processor"] のように許可リストを書きます(公式の例の形)。
確認の出方は、trust が true なら出ません。false なら、「今回だけ」「この道具を常に許可」「このサーバーを常に許可」「キャンセル」から選ぶ、と公式にあります。trust について、公式は、完全に自分で管理しているサーバーにだけ使うよう書いています。環境変数の鍵と、権限の広すぎるPATについても、リポジトリをまたいで情報が漏れうる、という注意があります。
名前の付け方
公式は、サーバー名にアンダースコアを使わず、my-server のようにするよう書いています。MCPの道具は mcp_{サーバー名}_{道具名} という名前になり、ポリシーの解釈が、mcp_ の後ろの最初のアンダースコアで分かれるため、アンダースコアがあるとワイルドカードや安全のルールが「黙って効かなくなる」ことがある、とあります。
遠隔のサーバーとOAuth
url か httpUrl のサーバーが401を返すと、CLIが認可の入口を探し、ブラウザを開いてログインさせ、受け取ったトークンを保存します。トークンは ~/.gemini/mcp-oauth-tokens.json に置かれる、と公式にあります。/mcp auth と /mcp auth <サーバー名> で認証できます。
CIでの落とし穴。 公式は、この流れには、ブラウザを開け、http://localhost:<ポート>/oauth/callback へのリダイレクトを受けられる環境が要る、と書いています。ヘッドレスの環境、X11転送のないSSH、ブラウザのないコンテナでは失敗します。つまり、OAuthで入るMCPサーバーは、人のいないCIには、そのままでは向きません(公式の記述からの僕らの読みです)。公式のGitHub Actionの例が、GitHubのMCPサーバーにトークンを環境変数で渡しているのは、この制約と合っています。
このほか、Google Cloudの保護されたサービス向けに、authProviderType の google_credentials(ADC)と service_account_impersonation があります。設定の細部は、公式のページを見てください(僕らは例のうち、google_credentials の形までを確認しました)。
カスタムコマンド:よく使う頼み方を、TOMLに残す
公式の「Custom commands」のページの要点です。
置き場所と名前。 ~/.gemini/commands/(どのプロジェクトでも)と、<project>/.gemini/commands/(そのプロジェクト。リポジトリに入れて共有できる)があります。同じ名前なら、プロジェクト側が使われます。サブフォルダは名前空間になり、git/commit.toml は /git:commit です。編集したら /commands reload、一覧は /commands list です。
書き方(TOML)。 prompt は必須、description(/help に出る一行)は任意です。
差し込み。 公式は3種類を挙げています。
| 記法 | 働き | 公式の注意 |
|---|---|---|
{{args}} |
コマンド名の後ろに打った文字に置き換わる | !{...} の中では、自動でシェル用にエスケープされる |
!{...} |
シェルを実行し、出力をプロンプトに入れる | 実行前に確認の画面が出て、引数を埋めた後の実際のコマンドが見える。波かっこは釣り合っている必要がある |
@{...} |
ファイルの中身(フォルダなら再帰)を入れる | .gitignore と .geminiignore が有効なら従う。処理の順番は @{}、!{}、{{args}} |
{{args}} が書かれていないのに引数が渡されたときは、打った内容全体が、プロンプトの後ろに空行を挟んで足される、とあります。
公式の例の1つは、ステージ済みの差分から、コミットメッセージを作る git/commit.toml です(git diff --staged の出力を !{...} で差し込む形)。拡張の公式チュートリアルにも、検索結果を要約させる例があります。
prompt = """
Please summarize the findings for the pattern `{{args}}`.
Search Results:
!{grep -r {{args}} .}
"""
これは、拡張の中に commands/fs/grep-code.toml として置くと /fs:grep-code "some pattern" になる、と公式にあります。
非対話での動き。 !{...} の確認の画面が、-p のような非対話の実行でどう扱われるかは、読んだ範囲では見つかりませんでした。一方、公式のGitHub Actionの例は、prompt: '/pr-code-review' のように、スラッシュコマンドをそのままプロンプトに渡しています。非対話でもスラッシュコマンドが使える一例です(拡張が持つコマンドの例です)。
他人のTOML。 前のガイド(04)に書いたとおり、他人が作った .toml への注意書きは、見つかりませんでした。!{...} はシェルを走らせるので、他人のものは中身を見てから使うのが無難、というのは僕らの見立てです。
Extensions:まとめて配る、まとめて入れる
探す、入れる、管理する
公式の概要のページは、ギャラリー(geminicli.com/extensions)で探し、GitHubのリポジトリのURLで入れる、と案内しています。
gemini extensions install https://github.com/gemini-cli-extensions/workspace
公式の拡張のリファレンスにあるコマンドです。管理のコマンドは対話の中では使えず、対話では /extensions list を使います。変更は、セッションを再起動した後に効きます。
| コマンド | 主なフラグ・注意(公式) |
|---|---|
gemini extensions install <source> |
GitHubのURLかローカルのパス。--ref(ブランチ、タグ、コミット)、--auto-update、--pre-release、--consent(確認を飛ばす)、--skip-settings。コピーを入れる。GitHubからは git が要る |
gemini extensions enable/disable <name> |
--scope は user か workspace。既定では全体で有効 |
gemini extensions update <name>/--all |
入れた後の変更を取り込むには、更新が要る |
gemini extensions new <path> [template] |
雛形から作る(mcp-server、context、custom-commands など) |
gemini extensions link <path> |
開発中のフォルダへのシンボリックリンク。再インストール不要 |
CLI参照のページには、これに加えて gemini extensions validate <path> が載っていますが、拡張のリファレンスの表には見つかりませんでした。どの版から使えるかは、読めていません。
ギャラリーの警告。 公式のギャラリーのページは、載っている拡張が公開リポジトリと第三者の開発者のもので、「Googleは、これらの拡張の機能や安全性を審査も、推奨も、保証もしない」と書き、入れる前に、ソースコードと求める権限を調べるよう勧めています。ギャラリーに載せるには、公開のGitHubリポジトリに gemini-cli-extension というトピックを付け、gemini-extension.json をルートに置きます。タグを付けたリポジトリをクローラーが毎日確認し、検証に通れば載る、issueやメールでの申請は要らない、と公式のリリースの手引きにあります(人の審査があるかどうかは、そのページには書かれていません)。つまり「載っている」ことは、安全の目印にはなりません。
中身:gemini-extension.json と置き場所
公式のリファレンスの例(抜粋)です。
{
"name": "my-extension",
"version": "1.0.0",
"description": "My awesome extension",
"mcpServers": {
"my-server": {
"command": "node",
"args": ["${extensionPath}/my-server.js"],
"cwd": "${extensionPath}"
}
},
"contextFileName": "GEMINI.md",
"excludeTools": ["run_shell_command"]
}
| 置き場所・項目 | 働き(公式) |
|---|---|
mcpServers |
起動時に読み込む。同名が settings.json にあれば、settings.json が勝つ。trust 以外のMCPの項目が使える |
contextFileName |
拡張のフォルダから読む資料。未指定なら、あれば GEMINI.md |
excludeTools |
モデルから隠す道具。"run_shell_command(rm -rf)" のようにコマンド単位でも書ける |
commands/ |
TOMLのコマンド。commands/gcs/sync.toml は /gcs:sync |
hooks/hooks.json |
フック。マニフェストの中には書けない |
skills/<名前>/SKILL.md |
エージェントスキル |
agents/*.md |
サブエージェント。公式は preview feature と書いている |
policies/*.toml |
ポリシーのルール |
変数は、gemini-extension.json と hooks/hooks.json の中で、${extensionPath}(拡張のフォルダ)、${workspacePath}、${/}(パスの区切り)が使えます。コマンド名が、ユーザーやプロジェクトのコマンドと重なると、拡張側は /gcp.deploy のように拡張名と点が付きます。
設定と鍵:settings
拡張がAPIキーなどを必要とするときは、settings に書きます。
{
"name": "my-api-extension",
"version": "1.0.0",
"settings": [
{
"name": "API Key",
"description": "Your API key for the service.",
"envVar": "MY_API_KEY",
"sensitive": true
}
]
}
sensitive が true なら、値はシステムのキーチェーンに入り、画面ではぼかされます。公式は、拡張とそのMCPサーバーが、シェルの環境をそのまま受け取るわけではなく、HOME、PATH などの安全な標準の変数と、settings の envVar で宣言した変数だけを受け取る、と書いています。必要な変数は、宣言しないと渡りません。
拡張のポリシーは「許可」を増やせない
公式のリファレンスによると、拡張が持つポリシーは、層でいうと2番目(既定より上、ユーザーや管理者より下)です。そして、拡張のポリシーに書いた allow の決定と yolo の設定は、無視されます。拡張が、道具の呼び出しを勝手に自動承認できないようにするためです。公式のポリシーの例は、決定が ask_user のルールでした。
作る手順(公式のチュートリアル)
gemini extensions new my-first-extension mcp-server
cd my-first-extension
npm install
gemini extensions link .
new は、ツールを1つ登録するMCPサーバーの example.js、gemini-extension.json、package.json を作ります。link の後、CLIを再起動して試します。コマンド、GEMINI.md、スキルを足す手順も同じチュートリアルにあります。
配る手順(公式のリリースの手引き)
公式のリリースの手引きは、Gitのリポジトリで配る方法(--ref でブランチ・タグ・コミットを指定でき、既定のブランチを安定版として扱う)と、GitHub Releasesで配る方法(「Latest」のリリースで更新を判定し、プラットフォーム別のバイナリも含められる)を挙げています。更新の判定は、GitHub Releasesならリリースのタグ、Gitのクローンなら git ls-remote で最新のコミットとの比較、ローカルならマニフェストの version の比較です。リポジトリを引っ越すときは、migratedTo を使います。セキュリティの面では、公式のベストプラクティスのページは、権限は必要最小限にし、run_shell_command を使うなら excludeTools で rm -rf * のような危ないコマンドを塞ぎ、MCPサーバーの入力は検証する、と書いています。ただし、同じページには、利用者の同意(コンセント)の案内は見つかりませんでした。
GitHub Action:run-gemini-cli
何ができるか、始め方
公式のREADMEは、GitHubのワークフローにGeminiを組み込み、自律的なエージェント、または @gemini-cli というメンションで呼ぶ協力者として使える、と書いています。PRのレビュー、issueのトリアージ、コードの分析と変更が挙げられています。リポジトリはApache-2.0です。READMEのクイックスタートは5つです。
- Google AI StudioでGemini APIキーを取る。
- リポジトリのシークレット
GEMINI_API_KEYに入れる(Settings > Secrets and variables > Actions)。 .gitignoreに次を足す。
# gemini-cli settings
.gemini/
# GitHub App credentials
gha-creds-*.json
- ワークフローを選ぶ。Gemini CLIの中で
/setup-githubを打つか、examples/workflowsのものをコピーする。gemini-dispatch.ymlは、他のワークフローを呼び出す入口なので、必ず一緒にコピーする。 - PRやissueを開くか、
@gemini-cli /review、@gemini-cli /triage、または普通の依頼をコメントして試す。
/setup-github の公式の説明は「issueのトリアージとPRのレビューのためのGitHub Actionsを設定する」の一行で、手順は、読んだ範囲では見つかりませんでした。
認証:2つの軸
公式の認証のページは、Google側とGitHub側を分けています。
| 軸 | 方法 | 公式の位置づけ |
|---|---|---|
| Gemini APIキー | いちばん簡単。Google Cloudとの連携は不要 | |
| Vertex AIのAPIキー | 手早い設定。GOOGLE_API_KEY と、変数 GOOGLE_GENAI_USE_VERTEXAI=true |
|
| Workload Identity Federation | 最も安全。GitHubのOIDCトークンを使い、長く使う鍵を保存しない | |
| GitHub | 既定の GITHUB_TOKEN |
APP_ID と APP_PRIVATE_KEY がないとき、自動で使われる。権限は限られ、ジョブが終わると失効する |
| GitHub | 自作のGitHub App | 公式は、安全性と細かい制御のために「強く勧める」 |
公式の例のうち、APIキーとWIFの形は次のとおりです(Vertex AIのキーの例は省きます)。
- uses: 'google-github-actions/run-gemini-cli@v0'
with:
prompt: |-
Explain this code
gemini_api_key: '${{ secrets.GEMINI_API_KEY }}'
- uses: 'google-github-actions/run-gemini-cli@v0'
with:
gcp_workload_identity_provider: '${{ vars.GCP_WIF_PROVIDER }}'
gcp_service_account: '${{ vars.SERVICE_ACCOUNT_EMAIL }}'
gcp_project_id: '${{ vars.GOOGLE_CLOUD_PROJECT }}'
gcp_location: '${{ vars.GOOGLE_CLOUD_LOCATION }}'
use_vertex_ai: '${{ vars.GOOGLE_GENAI_USE_VERTEXAI }}'
prompt: |-
Explain this code
WIFの設定は、公式が用意したスクリプトで行います。
./scripts/setup_workload_identity.sh --repo "[OWNER]/[REPO]" --project "[GOOGLE_CLOUD_PROJECT]"
公式は、実行するユーザーに、プロジェクトのIAMポリシーの設定や、プールの作成などの権限が要る、と書いています。スクリプトがプールとプロバイダーとサービスアカウントを作り、出力された値を、リポジトリの変数に入れます。サービスアカウントなしの直接WIFは、gcp_token_format: '' にして、gcp_service_account を省く、と公式の注記にあります。Gemini Code Assistを使う方式は、有効なCode Assistの購読が要る、とあります。個人のGoogleログインの扱いは、05に書いたとおりで、確認が要ります。
GitHub Appは、Webhookの「Active」を外し、Contents、Issues、Pull requestsに必要な分だけ権限を付け、秘密鍵(.pem)を保存し、対象のリポジトリにだけ入れます。リポジトリの変数 APP_ID と、シークレット APP_PRIVATE_KEY を設定します(公式の手順より)。
入力(with:)の主なもの
READMEの入力の表から、使う頻度が高いものを選びました。
| 入力 | 既定 | 説明(公式の要点) |
|---|---|---|
prompt |
You are a helpful assistant. |
CLIの --prompt に渡す文 |
settings |
なし | .gemini/settings.json に書かれるJSON。プロジェクトの設定 |
gemini_api_key |
なし | Gemini APIキー |
gemini_cli_version |
latest |
latest、preview、nightly、版番号、またはgitのブランチ・タグ・コミット |
gemini_model |
なし | 使うモデル |
extensions |
なし | 入れるGemini CLIの拡張 |
upload_artifacts |
false |
成果物をActionの実行に添付する |
gemini_debug |
なし | デバッグのログと出力のストリーミング |
github_pr_number/github_issue_number |
イベントから | CLIが扱うPRの番号と、issueの番号(カンマ区切りで複数) |
出力は、summary(CLIの実行の要約)と error(エラーの出力)です。
READMEの警告が1つあります。環境変数 DEBUG は設定しないでください。Gemini CLIが、Nodeのデバッガーを待って止まってしまいます。デバッグのログを出したいときは、READMEのリポジトリ変数の表にある GEMINI_DEBUG(任意。デバッグログを有効にする)を使います。
extensions の公式の例です。入力の形は「GitHubのURLのJSON配列」で、Actionの実行時に、そのリポジトリから入れられます。
jobs:
main:
runs-on: ubuntu-latest
steps:
- id: gemini
uses: google-github-actions/run-gemini-cli@v0
with:
gemini_api_key: ${{ secrets.GEMINI_API_KEY }}
prompt: '/security:analyze'
extensions: |
[
"https://github.com/gemini-cli-extensions/security",
"https://github.com/gemini-cli-extensions/code-review"
]
公式の完成したワークフロー4つ
公式のリポジトリの examples/workflows には、4つあります。以下は、僕らが読めた、各ファイルの要約です(YAMLの全文ではありません)。
| ワークフロー | 働き | 読めた構造 |
|---|---|---|
| dispatch | 入口。イベントと @gemini-cli のコマンドで、他を呼び分ける |
PRのopen、issueのopen、各種コメントで動く。コメントは、投稿者が OWNER、MEMBER、COLLABORATOR のときだけ。forkのPRは対象外 |
| review | PRのレビュー | workflow_call。タイムアウト7分。権限は contents: read、id-token: write、issues: write、pull-requests: write。公式の拡張 code-review を入れて、プロンプトは /pr-code-review |
| triage | issueにラベルを付ける | Geminiはラベルを直接付けない。選んだラベル名を出力し、別のジョブが、リポジトリにあるラベルに限って付ける |
| invoke(assistant) | @gemini-cli への自由な依頼 |
変更が絡むときは、計画をコメントして、@gemini-cli /approve を待つ |
dispatchのコマンドの振り分けは、@gemini-cli /review が review、/triage が triage、/approve が承認、それ以外の @gemini-cli ... が invoke、でした。
入口の条件には、非対称な点があります。公式のdispatchのYAMLを読んだ範囲では、author_association(OWNER、MEMBER、COLLABORATOR)を確かめるのはコメント系のイベントだけで、PRのopen(forkは除外)とissueのopen、reopenには、投稿者の条件がありません。つまり、外部の人が立てたissueでも、triageは動きえます。triageのGemini実行ステップだけ GITHUB_TOKEN を空にしているのは、この入口と合わせて読むと筋が通ります(僕らの見立てです)。「入口」で絞る、「道具」で絞る、「信頼」で絞る、の3つの層を、1つに頼らず重ねる、という整理につながります。
公式のreviewのワークフローの設定(要約)には、安全のための部品が並んでいます。model.maxSessionTurns が25、tools.core は空の配列です。MCPは、ghcr.io/github/github-mcp-server:v0.27.0 というイメージを、バージョンを固定してDockerで起動し、使える道具を3つだけ(add_comment_to_pending_review、pull_request_read、pull_request_review_write)に絞っています。上のチュートリアルは :latest のイメージでしたが、ワークフローの例は版を固定しています。invokeのほうは、includeTools で、読み取りと検索を中心に11個の道具を許可する形でした。
triageのワークフローには、公式のコメントに「信頼できない入力で動くので、認証トークンはここで渡さない」という趣旨の書き込みがあり、Gemini実行のステップの GITHUB_TOKEN は空にされていました。そして、Geminiの出力したラベルを、リポジトリのラベル一覧で絞り込んでから、別のジョブが付けます。僕らが読んだ要約では、これはプロンプトインジェクションへの備えとして説明されていました。この構造は、僕らが「AIの出力をそのまま権限のある操作に使わない」形として、いちばん参考になると考える部分です(僕らの見立てです)。
信頼できない入力:公式の書いていること
公式のGitHub Actionの「信頼」のページ(trust guidance)の趣旨です。
- 公式のこのページの冒頭に、バージョン
0.39.1で、ヘッドレスのGemini CLI向けのセキュリティ制御が入った、とあります。手元の版が0.39.1より前かどうかで、このページの話がそのまま当てはまるかが変わりうるので、gemini --versionで確かめてください(版ごとの違いの詳細は、読めていません)。 - 高い信頼の入力(リポジトリの持ち主のコードやプロンプト)なら、
GEMINI_CLI_TRUST_WORKSPACE=trueを設定してよい。 - 信頼できない入力(コラボレーターでない人のissueやPR)は、先にワークフローを堅くしてから、その変数を設定する。
- 権限は最小に(例:
issues: read)。下げた権限(例:actions: write)でも、リスクがありうる。 - 認証情報の権限を絞る。メンテナーが意図して起動する形を、forkで自動に走らせる形より優先する。
- 道具は最小にする。公式が挙げる最小の組は
list_directory、read_file、grep_searchで、コマンドの許可リストは、必要なときだけ。
PRレビューのREADMEには、forkの扱いがあります。forkは、悪意ある人が作れるので、既定では動かしません。許可する方法は2つです。dispatchのforkの判定を外し、貢献者が自分のGoogle認証を設定する方法と、pull_request_target を使う方法です。後者について、公式は「細心の注意なく使うと、脆弱性になりうる」と警告しています。ベストプラクティスには、main ブランチの保護(PR必須、承認数、古い承認の取り消し、ステータスチェック)、CODEOWNERS、WIFの利用、秘密を書かないこと、最小権限、OpenTelemetryでの監視、そしてAction自体の版の固定(例:uses: google-github-actions/run-gemini-cli@v0)が並んでいます。なお、公式の例の @v0 は、メジャーの目印のタグで、コミットのSHAではありません。これで「特定の版」の勧めを満たすのかは、公式のページに書かれていません。リリースのページでは、最新が v0.1.22(4月24日付と表示)でした。
CIでの組み立て:公式の部品を、重ねる
ここからは、僕らの整理です。公式の例を読んで、「無人で動かす」ときに決めることを、層に分けました。
| 層 | 決めること | 公式の部品 |
|---|---|---|
| 入口 | 誰の、どの操作で動くか | dispatchのif条件、author_association、forkの除外 |
| 認証 | Googleと、GitHubの鍵をどう渡すか | WIF、GitHub App、GITHUB_TOKEN の permissions |
| 道具 | 何を触れるか | tools.core、MCPの includeTools、拡張の excludeTools、ポリシー |
| 上限 | どこで止めるか | model.maxSessionTurns、timeout-minutes、終了コード 53 |
| 出力 | AIの答えを、どう使うか | summary、--output-format json、出力を許可リストで絞る |
| 信頼 | 未信頼の入力か | GEMINI_CLI_TRUST_WORKSPACE、最小権限 |
下は、上の公式の部品(認証の例、settings、permissions)を、僕らがつなげた最小の例です。公式にこの形のまとまった例があるわけではなく、動かしても確かめていません。settings の中身は、公式のreviewのワークフローの設定の一部です。
name: gemini-readonly-summary
on:
workflow_dispatch:
permissions:
contents: read
jobs:
summarize:
runs-on: ubuntu-latest
timeout-minutes: 7
steps:
- uses: actions/checkout@v4
- id: gemini
uses: google-github-actions/run-gemini-cli@v0
with:
gemini_api_key: ${{ secrets.GEMINI_API_KEY }}
prompt: 'Summarize the open TODO comments in this repository.'
settings: |-
{
"model": { "maxSessionTurns": 25 },
"tools": { "core": [] }
}
この例は、人が手で起動する(workflow_dispatch)、リポジトリは読むだけ、ターン数とタイムアウトに上限、という形にしています。tools.core を空にした場合に、実際にどの道具が使えるかは、公式のreviewの例が空にしている、ということ以上は読めていません。動かす前に、自分の版で、安全なリポジトリで確かめてください。
最初の10分でやること
- 前提の確認(2分)。 使っている認証方式が今も使えるか。
gemini --versionの後、gemini -p "Say hello"が通るか。 - ヘッドレスを試す(3分)。
git diff | gemini -p "Summarize these changes"のように、読むだけの用途で動かす。次に--output-format jsonを付けて、jq -r '.response'で取り出す。終了コードはecho $?で見る。信頼するフォルダを有効にしている場合は、FatalUntrustedWorkspaceErrorで止まることがある(上の「-pが信頼の手前で止まる」を参照)。 - MCPを1つだけつなぐ(3分)。 公式のチュートリアルのGitHubの例を、まず読み取り中心のPATで。
/mcp listでConnectedを確かめ、includeToolsで道具を絞る。サーバー名にアンダースコアを入れない。 - カスタムコマンドを1つ作る(1分)。
~/.gemini/commands/に、promptだけの.tomlを置き、/commands reload。 - Actionは、後で。 先に、手元のヘッドレスと、道具の絞り込みが分かってから。GitHub Actionは、
workflow_dispatchで、読むだけのリポジトリから。
気をつけること
- 承認の扱いが、ヘッドレスのページに見つからない。 書き込みや実行を無人で通す設定は、公式の記載を確かめてから決める。僕らは、
--approval-mode=yoloを、とりあえず付ける使い方を勧めません(僕らの見立てです)。 - 鍵が渡らない/渡りすぎる。 MCPの起動時、
*TOKEN*、*KEY*などの名前の変数は自動で取り除かれる。渡したいものはenvに書く。広すぎるPATは、リポジトリをまたぐ情報の漏れにつながりうる、と公式にある。 - 拡張は第三者のコード。 ギャラリーの公式の文言は、審査も保証もしないというもの。入れる前にソースと権限を読む。
installには確認が出て、--consentは飛ばす。 - Actionの入力に、信頼できない文章が入る。 issueの本文、PRのタイトル、コメントは、他人が書ける。公式の例のように、AIの出力を許可リストで絞り、権限を最小にし、forkは既定で止める。
- 版の固定。 公式の例でも、MCPサーバーのイメージは版を固定している。チュートリアルは
:latest。Actionのgemini_cli_versionの既定はlatestで、自動で変わる。 - ヘッドレスは、信頼するフォルダで止まりうる。 機能を有効にしていて、未信頼のフォルダだと
FatalUntrustedWorkspaceErrorで終了する。--skip-trustかGEMINI_CLI_TRUST_WORKSPACE=trueで越えられるが、そのセッションだけで、信頼の判断は自分で持つ。 - 入口の条件は、イベントごとに違う。 dispatchでは、コメントだけが投稿者の関係を確かめ、issueのopenは確かめない。triageでトークンを空にしている理由と合わせて読む。
DEBUG環境変数を設定しない。 CLIが止まる、と公式のREADMEにある。ログが要るときはGEMINI_DEBUGを使う。- ページの日付が古い。 ヘッドレスと自動化のページは2026年3月の更新です。信頼のガイドは、版
0.39.1でヘッドレス向けの制御が入ったと書いています。今の版と合っているかは、手元のgemini --helpで確かめてください。 - 読めていない点。
examples/workflowsの各YAMLの全文(要約のみ)、gemini-triage、gemini-invokeなどのコマンドのプロンプトの中身、Observabilityのページ、カスタムコマンドの非対話での確認の扱い、gemini extensions validateの詳細。
出典
- Headless mode(Gemini CLI docs、Google、更新2026-03-10、確認日2026-10-24)
- Automate tasks with headless mode(Gemini CLI docs、Google、更新2026-03-09、確認日2026-10-24)
- Gemini CLI cheatsheet(CLI reference、Gemini CLI docs、Google、確認日2026-10-24)
- MCP servers with Gemini CLI(Gemini CLI docs、Google、確認日2026-10-24)
- Set up an MCP server(Gemini CLI docs、Google、確認日2026-10-24)
- Custom commands(Gemini CLI docs、Google、確認日2026-10-24)
- Command reference(Gemini CLI docs、Google、確認日2026-10-24)
- Gemini CLI extensions(Gemini CLI docs、Google、更新2026-02-17、確認日2026-10-24)
- Extension reference(Gemini CLI docs、Google、更新2026-05-14、確認日2026-10-24)
- Build extensions(Gemini CLI docs、Google、確認日2026-10-24)
- Extension best practices(Gemini CLI docs、Google、確認日2026-10-24)
- Release extensions(Gemini CLI docs、Google、確認日2026-10-24)
- Gemini CLI extension gallery(geminicli.com、Google、確認日2026-10-24)
- run-gemini-cli README(GitHub、google-github-actions、確認日2026-10-24)
- run-gemini-cli README(raw、GitHub、google-github-actions、確認日2026-10-24)
- run-gemini-cli:Authentication(GitHub、google-github-actions、確認日2026-10-24)
- run-gemini-cli:Best practices(GitHub、google-github-actions、確認日2026-10-24)
- Trusted Folders(Gemini CLI公式ドキュメント、日付の表示は読めていない、確認日2026-10-24)
- run-gemini-cli:Trust guidance(GitHub、google-github-actions、確認日2026-10-24)
- run-gemini-cli:Extensions(GitHub、google-github-actions、確認日2026-10-24)
- run-gemini-cli:gemini-dispatch.yml(GitHub、google-github-actions、確認日2026-10-24)
- run-gemini-cli:gemini-review.yml(GitHub、google-github-actions、確認日2026-10-24)
- run-gemini-cli:gemini-triage.yml(GitHub、google-github-actions、確認日2026-10-24)
- run-gemini-cli:gemini-invoke.yml(GitHub、google-github-actions、確認日2026-10-24)
- run-gemini-cli:PR review workflow README(GitHub、google-github-actions、確認日2026-10-24)
- run-gemini-cli:Gemini assistant workflow README(GitHub、google-github-actions、確認日2026-10-24)
- run-gemini-cli:Releases(GitHub、google-github-actions、確認日2026-10-24)