gh-cli について
GitHub `gh` で issue、プルリクエスト、ラベルを扱うエージェントや自動化向けのスキルです。操作前の確認と認証障害の診断を案内し、検証済みの結果または正確なエラーだけを報告する方針を示します。
主な機能
- 01認証とリポジトリアクセスの事前確認
- 02キーチェーンと設定の問題診断
- 03アカウント選択と SAML SSO 対応
- 04機械可読出力による結果確認
- 05サーバー側自動化の代替手段
活用シーン
- 01重複を避けた issue の作成・更新
- 02`gh` によるプルリクエストとラベルの管理
- 03サンドボックス Shell での認証失敗の診断
- 04CI や一括処理での GitHub 操作
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ bobmatnyc/ claude-mpm-skills --skill gh-cliインストール後、Claude Code で/gh-cliを入力して読み込まれたか確認します。
同梱ファイルmetadata.json
詳細
GitHub gh CLI
GitHub の gh CLI で issue、PR、ラベルを操作するための信頼性の高いパターンです。認証の失敗が気付かれないまま起きやすく、結果を捏造することが最悪の結果となる、自動化やサブエージェント環境向けに作られています。
使用する場面:gh を使って GitHub の issue/PR/ラベルを作成、一覧表示、表示、編集、クローズするときはいつでも使用してください。特に、サンドボックス化されたシェルや委任されたサブエージェント内での操作が対象です。
唯一のルール:結果を捏造しない
操作が成功したことを確認できない場合は、正確なエラーを添えて失敗を報告してください。issue 番号、URL、「作成に成功しました」というメッセージを決して捏造しないでください。正確な失敗を明確に伝えるほうが、偽の成功を報告するより常に優れています。後続のエージェントや人間は、報告された内容に基づいて行動します。
1. 事前確認(あらゆる操作の前に実行)
まず認証とリポジトリへのアクセスを必ず確認してください。これらは低コストの読み取り専用コマンドで、変更を加える前に大半の失敗を検出できます。
# 1. Confirm you are authenticated and see which account/scopes are active
gh auth status
# 2. Confirm you can actually reach the target repo (proves token + SSO + network)
gh repo view <org>/<repo> --json name,url
gh auth statusが 「not logged into any GitHub hosts」 または何らかのエラーを報告した場合は、停止してください。作成/編集/クローズを実行してはいけません。以下のセクションを使って原因を調べ、エラーを一字一句そのまま報告してください。gh repo viewが失敗した場合(404、SAML、Bad credentials)は、停止してください。トークンが有効でも、この組織/リポジトリへのアクセス権がない可能性があります。エラーを正確に報告してください。- 両方のコマンドが成功してから、変更を加える操作に進んでください。
サブエージェントの場合:事前確認の失敗は、絶対に先へ進んではならない状態として扱ってください。認証に失敗したのに「issue #42 を作成しました」と返すことこそ、このスキルが防ごうとしている失敗です。
2. 注意点:サンドボックス/OS キーチェーンへのアクセス
gh の OAuth(キーリング)トークンは、OS のキーチェーン(macOS Keychain、Linux Secret Service)に保存されています。サンドボックス化されたシェルはキーチェーンを読み取れないため、gh は「認証情報が見つからない」状態にフォールバックし、有効な認証情報が存在していても 「not logged into any GitHub hosts」 と報告します。
症状:gh auth status は未ログインと表示するが、通常のターミナルでは同じコマンドが動作する。
対処方法:キーチェーンにアクセスできるよう、サンドボックスを無効にして gh を実行してください。
- Claude Code では、
ghを実行する Bash ツール呼び出しにdangerouslyDisableSandbox: trueを設定してください。 - 続行する前に、サンドボックスを無効にして事前確認(
gh auth status)を再実行し、認証状態を確認してください。
3. 注意点:古い GH_CONFIG_DIR
gh は、環境変数が設定されている場合は GH_CONFIG_DIR から、それ以外の場合は ~/.config/gh から設定(認証情報を格納する hosts.yml の場所を含む)を読み込みます。存在しないディレクトリを指す古い、または誤った GH_CONFIG_DIR が設定されていると、別の場所に有効なキーリング認証情報が存在していても、gh は「not logged in」と報告します。
原因を調べる:
echo "$GH_CONFIG_DIR" # Is it set? To what?
ls "$GH_CONFIG_DIR" # Does the directory exist? Has hosts.yml?
認証情報が実際に格納されている設定ディレクトリを探す:
find ~ -maxdepth 5 -name hosts.yml -path '*gh*'
対処方法 — GH_CONFIG_DIR を正しい設定ディレクトリに設定するか、解除してデフォルトに戻します:
# Option A: point at the working config explicitly
GH_CONFIG_DIR=/path/to/real/gh-config gh auth status
# Option B: unset to use ~/.config/gh
unset GH_CONFIG_DIR && gh auth status
4. 複数アカウント
gh auth status に複数のアカウントが表示され、そのうち 1 つがアクティブとして示される場合があります。gh はアクティブなアカウントを使用します。アクティブなアカウントに対象の組織/リポジトリへのアクセス権がない場合は、切り替えてください。
gh auth status # see all accounts; note which is "Active account: true"
gh auth switch -u <username> # make the correct account active
gh repo view <org>/<repo> --json name,url # re-verify after switching
5. 注意点:組織の SAML SSO による PAT の拒否
.env ファイルから取得した Personal Access Token は、SAML SSO を強制する組織によって拒否されることがよくあります。
HTTP 403: Resource protected by organization SAML enforcement.
You must grant your Personal Access token access to this organization.
理由:有効な PAT であっても、ブラウザーで許可手続きを行い、対象の組織に対する SSO 認証を受ける必要があります。ヘッドレス環境で .env から注入されたトークンは、通常、その許可手続きを経ていません。
推奨する対処方法:組織の SSO 認証が済んだキーリング OAuth トークン(gh auth login)を使用してください。OAuth ログインでは、対話形式で SSO の許可を求められます。既存の PAT を認証するには、GitHub の設定で組織の SSO ブラウザー許可手続きを完了してください(Developer settings → PATs → Configure SSO)。
経験則:SSO を強制する組織では、.env の PAT よりキーリング OAuth を優先してください。
6. CI/一括操作向けのサーバー側フォールバック
ローカル認証が利用できない、不安定な場合や、堅牢な一括操作が必要な場合は、GitHub App のインストールトークンを保持するサーバーから gh を実行してください。App のインストールトークンはSSO の対象外で、インストールの範囲に限定されるため、自動化に最も信頼できる方法です。
よくある方法は、AWS SSM 経由でコマンドをサーバーにディスパッチすることです。
aws ssm send-command \
--instance-ids <instance-id> --region <region> \
--document-name "AWS-RunShellScript" \
--parameters '{"commands":["gh issue create --repo <org>/<repo> --title \"...\" --body \"...\""]}'
キーチェーンを利用したローカル認証が保証できない場合は、自動化/CI における堅牢な方法として扱ってください。
7. よく使うコマンドの早見表
--json <fields> --jq <filter> を使うと、機械で解析可能な出力を取得できます。また、終了コードだけを信頼せず、結果を確認できます。
Issue
# Create — capture the returned URL; do not invent it
gh issue create --repo <org>/<repo> --title "Title" --body "Body" --label bug
# List (parseable)
gh issue list --repo <org>/<repo> --state open --json number,title,url --jq '.[]'
# View a specific issue
gh issue view <number> --repo <org>/<repo> --json number,title,state,url
# Close
gh issue close <number> --repo <org>/<repo> --comment "Resolved"
# Edit (also the basis of upsert-by-title — see below)
gh issue edit <number> --repo <org>/<repo> --add-label triaged --body "Updated body"
タイトルに基づく Upsert パターン(冪等な Issue 作成)
重複した Issue の作成を避けるため、作成前に同じタイトルの未解決 Issue が存在するか確認します。
existing=$(gh issue list --repo <org>/<repo> --state open \
--search "in:title \"My exact title\"" \
--json number,title --jq '.[] | select(.title=="My exact title") | .number' | head -n1)
if [ -n "$existing" ]; then
gh issue edit "$existing" --repo <org>/<repo> --body "Refreshed body"
else
gh issue create --repo <org>/<repo> --title "My exact title" --body "..."
fi
Pull request
gh pr view <number> --repo <org>/<repo> --json number,title,state,url,mergeable
gh pr list --repo <org>/<repo> --state open --json number,title,headRefName --jq '.[]'
ラベル
gh label create "code-intelligence" --repo <org>/<repo> --color BFD4F2 --description "..."
gh label list --repo <org>/<repo> --json name,color --jq '.[].name'
トラブルシューティング/環境固有の注意事項
このセクションでは、上記の障害モードが実際に発生した具体例を説明します。チケット処理を行うサブエージェントが duettoresearch/code-intelligence で Issue を作成できなかった際に原因を調査したものです。実際に適用するのは上記の一般的な手順です。ここでは、それらがどのように組み合わさるかを事例として示します。
症状
チケット処理を行うサブエージェントから、「どの GitHub ホストにもログインしていない」、**「認証情報が無効です」**という報告があり、duettoresearch/code-intelligence で Issue を作成できませんでした。実行によっては、存在しない Issue URL を報告してしまう恐れもありました。これは絶対にしないでください。
判明した根本原因(複数の要因が重なって発生)
- 古い
GH_CONFIG_DIR— サブエージェントがGH_CONFIG_DIR=/Users/masa/.config/gh-duettoを引き継いでいました。このディレクトリは存在しないため、ghは認証情報を認識できませんでした。(§3 を参照。) - サンドボックスによるキーチェーンへのアクセス遮断 — Bash サンドボックスが OS のキーチェーンの読み取りを妨げ、誤って「ログインしていない」と判定されました。(§2 を参照。)
.env.localの PAT が SAML SSO により拒否 —.env.local内の PAT は、duettoresearch組織の SAML 強制設定により拒否されます。(§5 を参照。)- 古いキーチェーントークン — アカウント
bobmatnycの残存キーチェーントークンにより、HTTP 401 の認証情報エラーが返されました。(§4 を参照。アクティブなアカウントが誤っています。)
動作確認済みの設定
GH_CONFIG_DIR=/Users/masa/.config/gh-personal # real config dir with valid hosts.yml
sandbox: disabled # so gh can read the keychain
active account: bob-duetto # scopes: gist, read:org, repo, workflow
result: gh repo view duettoresearch/code-intelligence → succeeds
標準的な修正手順
# Run gh with the real config dir AND the sandbox disabled
# (in Claude Code: dangerouslyDisableSandbox: true on the Bash call)
GH_CONFIG_DIR=/Users/masa/.config/gh-personal gh auth status
# If the wrong account is active, switch first:
GH_CONFIG_DIR=/Users/masa/.config/gh-personal gh auth switch -u bob-duetto
# Then re-verify before any mutation:
GH_CONFIG_DIR=/Users/masa/.config/gh-personal gh repo view duettoresearch/code-intelligence --json name,url
事前確認が成功した後に限り、サブエージェントは gh issue create などを実行してください。また、実際に返された URL を報告し、決して捏造した URL を報告してはいけません。
アンチパターン
❌ してはいけないこと:確認せずに成功を報告する
gh issue create ... # exit code ignored
# "Created issue #42!" ← fabricated; the command may have failed silently
✅ すべきこと:結果を取得して確認する
url=$(gh issue create --repo <org>/<repo> --title "T" --body "B")
echo "Created: $url" # report the actual returned URL, or the actual error
❌ してはいけないこと:「ログインしていない」という表示だけで認証情報がないと決めつける
通常はサンドボックス/キーチェーン、または古い GH_CONFIG_DIR が原因です。まず原因を調べてください(§2、§3)。
❌ してはいけないこと:SSO を強制する組織で .env の PAT に頼る
キーチェーンの OAuth、またはサーバー側の App インストールトークンを優先してください(§5、§6)。
まとめ
- まず事前確認:操作を行う前に
gh auth statusとgh repo viewを実行します。 - 決して捏造しない:失敗時は正確なエラーを、成功時は実際の URL を報告します。
- 4 つの障害モードを把握する:サンドボックス/キーチェーン、古い
GH_CONFIG_DIR、複数アカウント、SAML SSO による PAT の拒否。 - 自動化の方法:CI/一括操作には、サーバー側の GitHub App インストールトークン(SSO の対象外)を使用します。