mcpField
C
claude-code-proxy-patterns

claude-code-proxy-patterns

github.com/terrylica開発2105 回インストール今日更新
リポジトリ

claude-code-proxy-patterns について

Claude Code Proxy Patternsは、Claude Codeのリクエストをモデルに応じて異なるプロバイダーへ振り分けるローカルリバースプロキシのパターンを扱うスキルです。モデル別ルーティング、OAuth処理、リトライ、ヘルスチェックに加え、プロキシの設定とトラブルシューティングを説明します。

主な機能

  1. 01モデル名に基づくリクエスト振り分け
  2. 02Anthropic OAuthのパススルー
  3. 03Anthropic互換プロバイダーへの対応
  4. 04トークンのキャッシュと更新
  5. 05リトライと同時実行数の制限
  6. 06切り替えとヘルスチェックの手法

活用シーン

  1. 01Haikuを設定済みプロバイダーへ振り分け
  2. 02OAuth認証エラーの調査
  3. 03Anthropic互換プロバイダーの追加
  4. 04ローカルClaude Codeプロキシの運用

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/terrylica/cc-skills --skill claude-code-proxy-patterns

インストール後、Claude Code で/claude-code-proxy-patternsを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
anti-patterns.md
evolution-log.md
launchd-configuration.md
oauth-auto-refresh.md
oauth-internals.md
provider-compatibility.md
task-templates.md

詳細

Claude Code プロキシパターン

Claude Code のモデル階層を異なるバックエンドに振り分けるマルチプロバイダープロキシです。Haiku は、より低コストで高速な Anthropic 互換プロバイダーに、Sonnet/Opus は Anthropic に振り分けます(ネイティブの OAuth パススルー)。可用性を高めるため、launchd による自動再起動機能を備えた Go バイナリプロキシと、フェイルオーバー用ラッパーが含まれています。

対象範囲:OAuth サブスクリプション(Max プラン)を利用する Claude Code 用のローカルリバースプロキシです。リクエスト本文のモデル名に基づいて振り分けます。

実装例:

  • Go プロキシバイナリ:/usr/local/bin/claude-proxy(ポート 8082)

自己進化型スキル:このスキルは使用を通じて改善されます。手順に誤りがある場合、パラメーターが変わった場合、または回避策が必要になった場合は、先送りせず直ちにこのファイルを修正してください。実際に再現可能な問題がある場合にのみ更新してください。

このスキルを使用する場面

  • Claude Code のマルチプロバイダープロキシの構築やデバッグ
  • OAuth サブスクリプションモードでの ANTHROPIC_BASE_URL の設定
  • Anthropic 互換プロバイダーとの統合
  • プロキシ経由で発生する「OAuth not supported」や認証エラーの診断
  • Claude Code における OAuth トークンの保存方法と送信方法の理解

使用しない場面:Claude API キーのみを使う構成(プロキシは不要)、MCP サーバーの開発、Claude Code のフック(API レベルではなくツールレベルで動作)、企業 HTTPS プロキシ経由の通信。


アーキテクチャ

Claude Code (OAuth/Max subscription)
    |
    |  ANTHROPIC_BASE_URL=http://127.0.0.1:8082 (Go proxy)
    |  (unset ANTHROPIC_API_KEY to avoid auth conflict)
    v
+----------------------------------+
| Go proxy (:8082)                 |
| launchd managed, auto-restart   |
+----------------------------------+
    |
    | model =
    | claude-haiku-
    | 4-5-20251001
    v
+-----------+
| 3rd-party |
| provider  |
+-----------+

ポート設定:

  • :8082 - Go プロキシ(エントリーポイント、launchd による管理、自動再起動)

Go プロキシは、組み込みの再試行ロジックに cenkalti/backoff/v4 を使用します。

プロキシは、各 /v1/messages リクエスト本文から model フィールドを読み取ります。設定済みの Haiku モデル ID と一致する場合、リクエストは設定済みのプロバイダーに送信されます。それ以外はすべて、OAuth パススルーを使って実際の Anthropic に送信されます。


動作パターン

WP-01:Keychain からの OAuth トークン読み取り

Claude Code がトークンを保存する macOS Keychain から OAuth トークンを読み取ります。

サービス:「Claude Code-credentials」(ハイフンの前にスペースがあることに注意) アカウント:getpass.getuser() で取得する現在のユーザー名

import subprocess, json, getpass

result = subprocess.run(
    ["security", "find-generic-password",
     "-s", "Claude Code-credentials",
     "-a", getpass.getuser(), "-w"],
    capture_output=True, text=True, timeout=5, check=False,
)
if result.returncode == 0:
    data = json.loads(result.stdout.strip())
    oauth = data.get("claudeAiOauth")

詳しい説明は、references/oauth-internals.md を参照してください。

WP-02:トークンの JSON 構造

Keychain には、claudeAiOauth キーを含む JSON エンベロープが保存されます。

{
  "claudeAiOauth": {
    "accessToken": "eyJhbG...",
    "refreshToken": "rt_...",
    "expiresAt": 1740268800000,
    "subscriptionType": "claude_pro_2025"
  }
}

注:expiresAt はミリ秒単位(Unix エポック _ 1000)です。time.time() _ 1000 と比較するか、1000 で割って秒に変換してください。

WP-03:OAuth のベータヘッダー

OAuth トークン認証には、anthropic-beta: oauth-2025-04-20 ヘッダーが必須です。これがない場合、Anthropic は Bearer トークンを拒否します。

重要:既存のベータヘッダーを置き換えず、追加してください。

# proxy.py:304-308
existing_beta = original_headers.get("anthropic-beta", "")
beta_parts = [b.strip() for b in existing_beta.split(",") if b.strip()] if existing_beta else []
if "oauth-2025-04-20" not in beta_parts:
    beta_parts.append("oauth-2025-04-20")
target_headers["anthropic-beta"] = ",".join(beta_parts)
WP-04:ANTHROPIC_API_KEY=proxy-managed

OAuth モードでは、ANTHROPIC_BASE_URL を設定するだけでは不十分です。ANTHROPIC_BASE_URL が適用される API キーモードに切り替えるには、Claude Code から ANTHROPIC_API_KEY も設定済みとして認識される必要があります。

# In .zshenv (managed by proxy-toggle)
export ANTHROPIC_BASE_URL="http://127.0.0.1:8082"
export ANTHROPIC_API_KEY="proxy-managed"

"proxy-managed" はダミーのセンチネル値です。プロキシはこの値をインターセプトし(324 行目)、プロバイダーには転送しません。

WP-05:TTL 付き OAuth トークンキャッシュ

Keychain のサブプロセス呼び出しを繰り返さないよう、トークンを 5 分間キャッシュします。

# proxy.py:117-118
_oauth_cache: dict = {"token": None, "expires_at": 0.0, "fetched_at": 0.0}
_OAUTH_CACHE_TTL = 300  # Re-read from Keychain every 5 minutes

キャッシュの無効化条件:

  • TTL の期限切れ(前回の取得から 5 分経過)
  • トークンの expiresAt の経過
  • プロキシの再起動
WP-06:認証の優先順位

Anthropic 宛てのリクエストでは、プロキシは複数の認証情報源を順番に試します。

1. REAL_ANTHROPIC_API_KEY env var   -> x-api-key header (explicit config)
2. Keychain OAuth token             -> Authorization: Bearer + anthropic-beta
3. ~/.claude/.credentials.json      -> Authorization: Bearer (plaintext fallback)
4. Forward client Authorization     -> Pass through whatever Claude Code sent
5. No auth                          -> Will 401 (expected)

実装については proxy.py:293-314 を参照してください。

WP-07:count_tokens エンドポイントの認証

/v1/messages/count_tokens エンドポイントには、/v1/messages と同じ認証が必要です。Claude Code は、事前のトークン数カウントにこのエンドポイントを呼び出します。ここで認証情報が欠けていると、エラーが通知されずに失敗します。このエンドポイントを実装していない Anthropic 以外のプロバイダーには、501 を返します。

WP-08:Anthropic 互換プロバイダーの URL

Anthropic の /v1/messages API 形式に対応するサードパーティプロバイダーです。

プロバイダーベース URL備考
(使用するプロバイダー)https://<provider-host>/anthropic確認項目:モデルのエコー、追加のコンテンツブロック、cache_control、count_tokens

全体の一覧は、references/provider-compatibility.md をご覧ください。

WP-09:並行処理セマフォ

プロバイダーごとのレート制限により、サードパーティ API への過剰なリクエストを防ぎます。Anthropic は独自にレート制限を処理するため、セマフォはありません。

# proxy.py:207-209
MAX_CONCURRENT_REQUESTS = int(os.getenv("MAX_CONCURRENT_REQUESTS", "5"))
haiku_semaphore = asyncio.Semaphore(MAX_CONCURRENT_REQUESTS)
opus_semaphore = asyncio.Semaphore(MAX_CONCURRENT_REQUESTS)
sonnet_semaphore = asyncio.Semaphore(MAX_CONCURRENT_REQUESTS)
WP-10:proxy-toggle の有効化/無効化

proxy-toggle スクリプトは、.zshenv のエントリーとフラグファイルをアトミックに管理します。

~/.claude/bin/proxy-toggle enable    # Adds env vars, creates flag file, checks health
~/.claude/bin/proxy-toggle disable   # Removes env vars, removes flag file
~/.claude/bin/proxy-toggle status    # Shows routing flag, proxy process, .zshenv state

重要:切り替え後は Claude Code を再起動する必要があります。ANTHROPIC_BASE_URL は起動時に読み込まれるためです。

WP-11:ヘルスエンドポイント

/health エンドポイントは、監視用にプロバイダーの設定状態を返します。

curl -s http://127.0.0.1:8082/health | jq .
WP-12:リトライ機能付き Go プロキシ

cenkalti/backoff/v4 を使用したリトライ機能を内蔵する Go プロキシです(指数バックオフ:500ms → 1s → 2s、経過時間の上限は 5s)。

import "github.com/cenkalti/backoff/v4"

backoffConfig := backoff.NewExponentialBackOff(
    backoff.WithInitialInterval(500 * time.Millisecond),
    backoff.WithMultiplier(2),
    backoff.WithMaxInterval(2 * time.Second),
    backoff.WithMaxElapsedTime(5 * time.Second),
)
err := backoff.Retry(operation, backoffConfig)

場所:/usr/local/bin/claude-proxy | 環境:.zshenv 内の ANTHROPIC_BASE_URL=http://127.0.0.1:8082

WP-13:Launchd サービスの設定

Go プロキシは macOS の launchd デーモンとして実行され、クラッシュ時の自動再起動と起動時の永続化に対応します。

Plist:/Library/LaunchDaemons/com.example.claude-proxy.plist

Plist の設定全体、コマンド、検証チェックリスト、デバッグについては、references/launchd-configuration.md をご覧ください。

WP-14:OAuth トークンの自動更新

バックグラウンドの goroutine が 30 分ごとに、トークンの有効期限が切れる 5 分前に OAuth トークンを更新します。API による更新に失敗した場合は、Keychain にフォールバックします。

実装全体と更新ロジックについては、references/oauth-auto-refresh.md をご覧ください。


アンチパターンの概要

コード例を含む詳細については、references/anti-patterns.md を参照してください。

ID重大度問題点対処方法
CCP-01HIGHANTHROPIC_BASE_URL のみで、ANTHROPIC_API_KEY が設定されていないANTHROPIC_API_KEY=proxy-managed を設定する
CCP-02HIGHanthropic-beta: oauth-2025-04-20 ヘッダーがない既存のベータヘッダーに追加する
CCP-03MEDIUM/api/oauth/claude_cli/create_api_key エンドポイントを使用しているorg:create_api_key スコープが必要(ユーザーが持つのは user:inference のみ)
CCP-04HIGHキーチェーンのサービス名に小文字の "claude-code-credentials" を使用している実際の名前にはスペースが含まれます:"Claude Code-credentials"
CCP-05MEDIUM~/.claude/.credentials.json をプライマリとして読み込んでいるキーチェーンが唯一の信頼できる情報源(SSoT)です。認証情報ファイルは古いフォールバックです
CCP-06HIGHOAuth トークンをハードコードしているトークンは期限切れになるため、キャッシュを使って動的に読み込む
CCP-07HIGHプロキシ/フックで gh auth token を使用しているプロセスストーム(再帰的な起動)が発生する
CCP-08HIGHOAuth トークンがある状態で、環境変数に ANTHROPIC_API_KEY が設定されているClaude Code で認証の競合に関する警告が表示されます。設定を解除してください
CCP-09MEDIUM対応していないプロバイダーに cache_control パラメーターを送信しているプロバイダーに拒否されるため、allowedParams から削除する
CCP-10MEDIUMプロキシの実行中に ANTHROPIC_API_KEY に実際のキーを設定しているプロキシがすべてのプロバイダーに転送するため、キーが漏えいする
CCP-11MEDIUM/v1/messages/count_tokens を処理していない事前リクエストで認証エラーが発生する
CCP-12LOWプロキシを 0.0.0.0 で実行しているセキュリティのため、127.0.0.1 にバインドする

TodoWrite タスクテンプレート

セットアップ、プロバイダーの追加、診断、無効化のテンプレートについては、references/task-templates.md を参照してください。


リファレンス実装

稼働中の本番デプロイ(Go プロキシがプライマリ):

ファイル用途
/usr/local/bin/claude-proxyGo プロキシのバイナリ(約960行)
~/.claude/tools/claude-code-proxy-go/main.goGo プロキシのソース
~/.claude/tools/claude-code-proxy-go/oauth_refresh.goOAuth の自動更新(80行)
~/.claude/tools/claude-code-proxy-go/.envプロバイダー設定(chmod 600)
/Library/LaunchDaemons/com.example.claude-proxy.plistlaunchd の設定
~/.zshenv環境変数(ANTHROPIC_BASE_URL)

変更後のチェックリスト

このスキルを変更した後、次を確認してください。

  1. アンチパターンの表が references/anti-patterns.md と一致している
  2. 動作するパターンを proxy.py のソースと照合して検証している
  3. 例に OAuth トークンがハードコードされていない
  4. ベータヘッダーのバージョンが最新である(oauth-2025-04-20)
  5. すべての内部リンクが相対パス(./references/...)を使用している
  6. リンク検証ツールに合格している
  7. スキル検証ツールに合格している
  8. 変更内容を references/evolution-log.md に追記している

トラブルシューティング

問題原因解決策
Claude Code が ANTHROPIC_BASE_URL を無視するANTHROPIC_API_KEY が設定されていない(CCP-01).zshenv で ANTHROPIC_API_KEY=proxy-managed を設定する
Anthropic から 401 Unauthorized が返されるanthropic-beta ヘッダーがない(CCP-02)プロキシが oauth-2025-04-20 を追加することを確認する
Keychain の読み取り結果が空になるサービス名が誤っている(CCP-04)"Claude Code-credentials"(スペースあり)を使用する
プロキシが実際の API キーを転送するANTHROPIC_API_KEY に実際のキーが設定されている(CCP-10)proxy-managed のセンチネル値を使用する
count_tokens の認証に失敗するエンドポイントハンドラーがない(CCP-11)プロキシが /v1/messages/count_tokens を処理する必要があります
ネットワークからプロキシにアクセスできる0.0.0.0 にバインドされている(CCP-12)127.0.0.1 のみにバインドする
有効化時にプロセスが大量に起動するフック内の gh auth トークン(CCP-07)フック/認証情報ヘルパーから gh CLI を呼び出さない
5 分後にトークンの有効期限が切れるキャッシュ TTL(WP-05)通常の動作です。プロキシが Keychain から再読み込みします
Claude Code で認証の競合に関する警告が表示されるANTHROPIC_API_KEY が設定されている(CCP-08).zshenv で ANTHROPIC_API_KEY の設定を解除する
cache_control.ephemeral.scope エラープロバイダーが cache_control に対応していない(CCP-09)allowedParams から cache_control を削除する

実行後の振り返り

このスキルの実行後、終了する前に以下を確認してください。

  1. コマンドは成功しましたか? — 成功しなかった場合は、失敗の原因となった指示またはエラーテーブルを修正します。
  2. パラメーターや出力に変更はありましたか? — 基盤となるツールのインターフェイスに変更があった場合は、それに合わせて使用例とパラメーターテーブルを更新します。
  3. 回避策が必要でしたか? — 工夫が必要だった場合(異なるフラグや追加手順など)は、次回の実行で同じ回避策が不要になるよう、この SKILL.md を更新します。

実際に再現可能な問題がある場合に限り、更新してください。推測で更新しないでください。

コメント