🥑

複数の GitHub リポジトリにある Claude Max 認証情報のシークレットをコマンドラインから一括更新する

に公開

はじめに

Claude Max サブスクリプションで Claude Code GitHub Actions を利用しているときに、このような経験はありませんか?

  • 認証情報の手動更新:期限切れのたびにリポジトリの設定画面を開いて認証情報を更新
  • 同じ作業の繰り返し:リポジトリの増加に伴い管理工数が増加
  • 更新の作業漏れ:気がついたら数日間ワークフローが動いていないことも...

この記事では、そんな「増え続ける認証情報の更新ストレス」を抱える Claude ユーザーの私が GitHub CLI を活用した コマンドライン操作のみで Claude Max 認証情報を一括更新する方法をご紹介します。

必要なツール

認証情報を一括更新する

# 更新対象リポジトリのリスト
REPOSITORIES=(
    "owner/repo1"
    "owner/repo2"
)

# GitHub 未認証の場合は認証
# gh auth login

# 認証情報が古い場合はログインにより更新
# claude /login

# 認証情報を取得(実行環境に応じて取得元が異なる)
OS="$(uname)"
if [[ "${OS}" == "Linux" ]]; then
    # Linux / WSL(ファイルから取得)
    CLAUDE_CODE_CREDENTIALS="$(cat ~/.claude/.credentials.json)"
elif [[ "${OS}" == "Darwin" ]]; then
    # macOS(キーチェーンから取得)
    CLAUDE_CODE_CREDENTIALS="$(security find-generic-password -s 'Claude Code-credentials' -a $(whoami) -w)"
else
    echo "認証情報が取得できませんでした(Linux または macOS のみをサポートしています)"
fi

# 認証情報からシークレットを抽出
CLAUDE_ACCESS_TOKEN="$(echo "${CLAUDE_CODE_CREDENTIALS}" | jq -r ".claudeAiOauth.accessToken")"
CLAUDE_EXPIRES_AT="$(echo "${CLAUDE_CODE_CREDENTIALS}" | jq ".claudeAiOauth.expiresAt")"
CLAUDE_REFRESH_TOKEN="$(echo "${CLAUDE_CODE_CREDENTIALS}" | jq -r ".claudeAiOauth.refreshToken")"

# リポジトリのシークレットを更新(または作成)
for repo in "${REPOSITORIES[@]}"; do
    echo "[ ${repo} ]"
    gh secret set CLAUDE_ACCESS_TOKEN --repo "${repo}" --body "${CLAUDE_ACCESS_TOKEN}"
    gh secret set CLAUDE_EXPIRES_AT --repo "${repo}" --body "${CLAUDE_EXPIRES_AT}"
    gh secret set CLAUDE_REFRESH_TOKEN --repo "${repo}" --body "${CLAUDE_REFRESH_TOKEN}"

    # リポジトリのシークレットの更新日を確認
    gh secret list --repo "${repo}" |
        grep -e "CLAUDE_ACCESS_TOKEN" -e "CLAUDE_EXPIRES_AT" -e "CLAUDE_REFRESH_TOKEN"
done

# 念のため、秘密情報を保持している変数を削除
unset CLAUDE_CODE_CREDENTIALS
unset CLAUDE_ACCESS_TOKEN
unset CLAUDE_EXPIRES_AT
unset CLAUDE_REFRESH_TOKEN

少しばかりの解説

macOS でキーチェーンから値を取得するコマンド

security find-generic-password コマンドの仕様は以下の通りです。
-a オプションの値(アカウント名)は whoami コマンドにより取得しています。

security find-generic-password --help
find-generic-password: illegal option -- -
Usage: find-generic-password [-h] [-a account] [-s service] [options...] [-g] [keychain...]
    -a  Match "account" string
    -c  Match "creator" (four-character code)
    -C  Match "type" (four-character code)
    -D  Match "kind" string
    -G  Match "value" string (generic attribute)
    -j  Match "comment" string
    -l  Match "label" string
    -s  Match "service" string
    -g  Display the password for the item found
    -w  Display only the password on stdout
If no keychains are specified to search, the default search list is used.

Claude Max 認証情報の形式

Claude Max の認証情報の形式は以下の通りです。
認証情報に含まれる 3 つのシークレットを jq により抽出しています。

{
  "claudeAiOauth": {
    "accessToken": "foo",
    "refreshToken": "bar",
    "expiresAt": 1234,
    "scopes": ["user:inference", "user:profile"],
    "isMax": true
  }
}

おわりに

いかがでしたでしょうか?
リポジトリが増えれば増えるほど、この自動化の価値は高まります。この方法を採用すれば、20 個のリポジトリでも 100 個のリポジトリでも、作業時間はほとんど同じです。

もしこの記事が皆さんの開発効率向上に貢献できましたら、ぜひ「いいね」で応援していただけますと嬉しいです。また、みなさんの環境での活用例や改善アイデアなどがありましたら、ぜひコメントで教えてください。

Discussion