mcpField
C
claude-code-proxy-patterns

claude-code-proxy-patterns

github.com/terrylica开发2105 次安装今天更新
代码仓库

关于 claude-code-proxy-patterns

Claude Code Proxy Patterns 是一项介绍本地反向代理模式的 Skill,可按模型将 Claude Code 请求路由到不同提供方。它涵盖模型路由、OAuth 处理、重试、健康检查,以及代理配置和故障排查指引。

主要功能

  1. 01按模型名称路由请求
  2. 02支持 Anthropic OAuth 透传
  3. 03支持兼容 Anthropic 的提供方
  4. 04介绍令牌缓存与刷新
  5. 05涵盖重试和并发限制
  6. 06包含开关与健康检查模式

适用场景

  1. 01将 Haiku 路由到配置的提供方
  2. 02排查 OAuth 身份验证失败
  3. 03接入兼容 Anthropic 的提供方
  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 直通)。包含 Go 二进制代理(由 launchd 自动重启)和用于增强可靠性的故障转移包装器。

范围:适用于使用 OAuth 订阅(Max plan)的 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 hooks(在工具层而非 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 匹配,请求就会发送到配置的提供商。其他所有请求都会转发到真正的 Anthropic,并通过 OAuth 直通。


可行模式

WP-01:读取 Keychain OAuth 令牌

从 macOS Keychain 中读取 Claude Code 存储的 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 Beta 标头

OAuth 令牌身份验证必须使用 anthropic-beta: oauth-2025-04-20 标头。否则,Anthropic 会拒绝 Bearer 令牌。

重要:将此标头追加到现有 beta 标头中,不要替换它们。

# 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 并不足够。Claude Code 还必须看到已设置的 ANTHROPIC_API_KEY,才能从仅 OAuth 模式切换到 API 密钥模式,之后才会遵循 ANTHROPIC_BASE_URL。

# 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 令牌缓存

将令牌缓存 5 分钟,避免重复调用 Keychain 子进程。

# 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 代理

Go 代理内置重试,使用 cenkalti/backoff/v4(指数退避: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 分钟刷新一次 OAuth 令牌,在令牌过期前 5 分钟进行刷新。如果 API 刷新失败,则回退到 Keychain。

完整实现和刷新逻辑:references/oauth-auto-refresh.md


反模式摘要

完整详情和代码示例:references/anti-patterns.md

ID严重程度易踩问题修复方案
CCP-01HIGH只设置 ANTHROPIC_BASE_URL,未设置 ANTHROPIC_API_KEY设置 ANTHROPIC_API_KEY=proxy-managed
CCP-02HIGH缺少 anthropic-beta: oauth-2025-04-20 标头将其追加到现有 beta 标头
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-06HIGH硬编码 OAuth 令牌令牌会过期;应动态读取并缓存
CCP-07HIGH在代理/钩子中使用 gh auth token会引发进程风暴(递归启动)
CCP-08HIGH设置 OAuth 令牌时仍在环境变量中设置 ANTHROPIC_API_KEYClaude 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. Beta 标头版本为当前版本(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. 参数或输出是否发生变化? — 如果底层工具的接口发生变化,请相应更新 Usage 示例和 Parameters 表。
  3. 是否需要变通处理? — 如果你必须临时调整(使用不同的标志、增加额外步骤),请更新此 SKILL.md,避免下次调用时需要采用相同的变通方法。

仅在问题确实存在且可复现时才更新,不要更新推测性问题。

评论

支持 Markdown