手摸手给 Claude Code 换芯:GLM + Headroom + cc-switch 省钱接入指南

手摸手给 Claude Code 换芯:GLM + Headroom + cc-switch 省钱接入指南

摘要:把 Claude Code 的 API 调用链路换成国产智谱 GLM,同时用 Headroom 压缩上下文进一步降低 token 消耗。本文记录完整的搭建过程与踩坑经验。


为什么要这么折腾

Claude Code 用起来确实爽,但 Claude API 的价格摆在那里------尤其是长上下文对话,token 跑得飞快。国内智谱 GLM 提供了 Anthropic 兼容接口,可以完全替代 Claude 的模型层,价格低了一大截。(当然你想继续用 Claude 也可以,这个方案同样兼容。)

但光替换模型还不够。Claude Code 默认会把完整对话历史每次都原封不动发上去,如果能在中间加一层压缩代理,把冗余上下文剪掉,token 消耗还能再省一笔。

所以最终的链路设计是这样的:

arduino 复制代码
Claude Code → Headroom (:8787,上下文压缩)
            → cc-switch (:15721,注入 GLM key)
            → https://open.bigmodel.cn/api/anthropic (glm-5.2)

三个组件各司其职:

  • Headroom:HTTP 代理,负责压缩发往上游的上下文内容,省 token。
  • cc-switch :GUI 应用,本地代理 :15721,保管真实的 GLM API key,并把 Claude 的各模型名映射成 glm-5.2
  • GLM:智谱开放平台提供的 Anthropic 兼容接口。

前置条件

  • macOS(Apple Silicon / Intel 均可)
  • 已安装 cc-switch/Applications/CC Switch.app)并配置好一个 GLM provider(本文使用 Anthropic 兼容模式)
  • 已有智谱 API key(在 open.bigmodel.cn 获取)
  • 系统自带 Python 3.9 不够用,Headroom 需要 Python ≥ 3.10,所以需要用 uv 单独建一个 Python 3.12 的虚拟环境

第一步:安装 uv

Headroom 通过 uv 安装。如果还没装 uv:

bash 复制代码
curl -LsSf https://astral.sh/uv/install.sh | sh

安装后 uv 在 ~/.local/bin/uv,确认一下:

bash 复制代码
~/.local/bin/uv --version

如果提示找不到命令,把 ~/.local/bin 加进 PATH,写入 ~/.zshrc

bash 复制代码
export PATH="$HOME/.local/bin:$PATH"

第二步:用 uv 创建 Python 3.12 环境并安装 Headroom

系统自带的 Python 3.9 太旧了,用 uv 自带的 Python 管理功能创建一个新环境:

bash 复制代码
uv venv ~/.headroom-venv --python 3.12
source ~/.headroom-venv/bin/activate
uv pip install headroom

验证安装:

bash 复制代码
~/.headroom-venv/bin/headroom --version
# 期望输出类似:headroom, version 0.28.0

第三步:配置 cc-switch

打开 CC Switch.app,添加一个 provider,类型选 Anthropic 兼容

  • Base URLhttps://open.bigmodel.cn/api/anthropic
  • API Key:你的智谱 key
  • 模型映射 :把 Opus / Sonnet / Haiku / Fable 全部映射到 glm-5.2

然后开启本地代理enableLocalProxy: true),cc-switch 会在 127.0.0.1:15721 启动一个代理。点应用后,cc-switch 会写入 ~/.claude/settings.json,内容大致长这样:

json 复制代码
{
  "env": {
    "ANTHROPIC_AUTH_TOKEN": "PROXY_MANAGED",
    "ANTHROPIC_BASE_URL": "http://127.0.0.1:15721",
    "ANTHROPIC_DEFAULT_OPUS_MODEL": "claude-opus-4-8",
    "ANTHROPIC_DEFAULT_OPUS_MODEL_NAME": "glm-5.2",
    "ANTHROPIC_DEFAULT_SONNET_MODEL": "claude-sonnet-4-6",
    "ANTHROPIC_DEFAULT_SONNET_MODEL_NAME": "glm-5.2",
    "ANTHROPIC_DEFAULT_HAIKU_MODEL": "claude-haiku-4-5",
    "ANTHROPIC_DEFAULT_HAIKU_MODEL_NAME": "glm-5.2",
    "ANTHROPIC_DEFAULT_FABLE_MODEL": "glm-5.2",
    "ANTHROPIC_DEFAULT_FABLE_MODEL_NAME": "glm-5.2"
  }
}

注意 ANTHROPIC_AUTH_TOKEN: PROXY_MANAGED 是 cc-switch 的占位符------真实的 key 存在 cc-switch 内部的 SQLite 数据库里(~/.cc-switch/cc-switch.db),不会以明文出现在 settings.json 中。

此时链路已经是 Claude Code → cc-switch → GLM 了,但还没有压缩。下一步把 Headroom 插到中间。


第四步:编写 Headroom 启动脚本

新建 ~/.headroom-start.sh

bash 复制代码
cat > ~/.headroom-start.sh <<'EOF'
#!/usr/bin/env zsh
source "$HOME/.headroom-venv/bin/activate"

# Upstream = cc-switch 的本地代理(负责注入 GLM key)
export ANTHROPIC_TARGET_API_URL="http://127.0.0.1:15721"
export HEADROOM_HOST=127.0.0.1

# 输出压缩:默认关掉,设为 1 启用
export HEADROOM_OUTPUT_SHAPER="${HEADROOM_OUTPUT_SHAPER:-0}"

# 跳过上游可达性检查------cc-switch 是 loopback 代理,
# Headroom 的 /readyz 探活可能误报
export HEADROOM_SKIP_UPSTREAM_CHECK=1

exec headroom proxy --port 8787 --host 127.0.0.1
EOF

chmod +x ~/.headroom-start.sh

几个重要的环境变量:

  • ANTHROPIC_TARGET_API_URL :指向 cc-switch(:15721),而不是直连 GLM------key 注入仍由 cc-switch 负责,Headroom 只管压缩和转发。
  • HEADROOM_SKIP_UPSTREAM_CHECK=1 :cc-switch 是 loopback 代理,Headroom 对它做 /readyz 探活会误报,关掉换手动验证。
  • HEADROOM_OUTPUT_SHAPER :默认 0(不压缩输出),想连模型回包一起压缩就设 1

先手动跑一次,确认能起来:

bash 复制代码
~/.headroom-start.sh
# 另开终端验证:
curl -s http://127.0.0.1:8787/livez

确认无误后 Ctrl+C 停掉,下一步交给 launchd 托管。


第五步:用 launchd 设置开机自启

创建 ~/Library/LaunchAgents/com.headroom.proxy.plist

bash 复制代码
cat > ~/Library/LaunchAgents/com.headroom.proxy.plist <<'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.headroom.proxy</string>

    <key>ProgramArguments</key>
    <array>
        <string>/bin/zsh</string>
        <string>__HOME__/.headroom-start.sh</string>
    </array>

    <key>RunAtLoad</key>
    <true/>

    <key>KeepAlive</key>
    <true/>

    <key>ThrottleInterval</key>
    <integer>10</integer>

    <key>StandardOutPath</key>
    <string>/tmp/headroom-proxy.log</string>

    <key>StandardErrorPath</key>
    <string>/tmp/headroom-proxy.log</string>

    <key>ProcessType</key>
    <string>Background</string>
</dict>
</plist>
EOF

sed -i '' "s|__HOME__|$HOME|" ~/Library/LaunchAgents/com.headroom.proxy.plist

加载并启动:

bash 复制代码
launchctl load ~/Library/LaunchAgents/com.headroom.proxy.plist
launchctl list | grep headroom

看到 com.headroom.proxy 出现在列表里就对了。plist 的几个关键配置说明:

配置项 作用
RunAtLoad=true 开机或加载时自动启动
KeepAlive=true 进程意外退出自动拉起
ThrottleInterval=10 崩溃重启最小间隔 10s,防止重启风暴
日志统一写到 /tmp/headroom-proxy.log 方便排查

日常管理命令:

bash 复制代码
# 停止
launchctl unload ~/Library/LaunchAgents/com.headroom.proxy.plist

# 重启
launchctl unload ... && launchctl load ...

# 看日志
tail -f /tmp/headroom-proxy.log

第六步:把 Claude Code 的 base URL 指向 Headroom

cc-switch 默认会把 ANTHROPIC_BASE_URL 写成 http://127.0.0.1:15721(直连 cc-switch)。要插入 Headroom,需要改成 :8787

bash 复制代码
python3 - <<'EOF'
import json, pathlib
p = pathlib.Path.home() / ".claude" / "settings.json"
cfg = json.loads(p.read_text())
cfg.setdefault("env", {})["ANTHROPIC_BASE_URL"] = "http://127.0.0.1:8787"
p.write_text(json.dumps(cfg, indent=2, ensure_ascii=False))
print(p.read_text())
EOF

改完后必须重启 Claude Code------当前会话用的还是改之前的 base URL,不重启不生效。


第七步:验证整条链路

直接请求 Headroom,确认能拿到 GLM 的回复

bash 复制代码
curl -s -X POST http://127.0.0.1:8787/v1/messages \
  -H "x-api-key: PROXY_MANAGED" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{"model":"glm-5.2","max_tokens":16,"messages":[{"role":"user","content":"say ok"}]}'

正常应该返回带 msg_... id 的 JSON,content 是 GLM 的回复内容。

Headroom 自检

bash 复制代码
~/.headroom-venv/bin/headroom doctor --port 8787

注意 doctor/livez 探针对 Headroom 自己的端口有效,不要让它去探 cc-switch 的 15721

检查 launchd 状态

bash 复制代码
launchctl list | grep headroom

第二列是 0 表示运行正常;非零说明崩了,去看 /tmp/headroom-proxy.log 排查。


⚠️ 一个必踩的大坑

cc-switch 有一个很坑的行为:如果你在 GUI 里切换 provider 或重新点「应用」,它会重写 ~/.claude/settings.json,把 ANTHROPIC_BASE_URL 改回 http://127.0.0.1:15721直接绕过了 Headroom

解决办法

  • 每次在 cc-switch 里动过之后,重新执行第六步把 base URL 改回 :8787,然后重启 Claude Code。
  • 或者干脆配好之后就不要再动 cc-switch,只在 GLM key 过期需要更新时才进 GUI。

文件清单

路径 作用
~/.local/bin/uv uv 安装器
~/.headroom-venv/ Headroom 专用 Python 3.12 venv
~/.headroom-start.sh Headroom 启动脚本
~/Library/LaunchAgents/com.headroom.proxy.plist launchd 自启配置
/tmp/headroom-proxy.log Headroom 运行日志
~/.claude/settings.json Claude Code 配置(base URL 指向 :8787
~/.cc-switch/ cc-switch 数据库与配置(含真实 GLM key)

常见问题

Q: Claude Code 启动报连接 :8787 失败?

A: Headroom 没起来。launchctl list | grep headroom 看进程在不在,不在就 launchctl load;在但崩了就看 /tmp/headroom-proxy.log

Q: 改了 cc-switch 后 Claude Code 不压缩了?

A: 检查 ~/.claude/settings.jsonANTHROPIC_BASE_URL 是不是被改回 :15721 了,改回 :8787 并重启 Claude Code。

Q: 想连模型输出也压缩?

A: 编辑 ~/.headroom-start.sh,把 HEADROOM_OUTPUT_SHAPER 改成 1,然后 launchctl unload && load 重启 Headroom。

Q: 怎么临时停掉压缩直连 GLM?

A: 把 ANTHROPIC_BASE_URL 临时改回 http://127.0.0.1:15721 并重启 Claude Code,用完再改回来。Headroom 进程本身不用停。


最后的效果

全部配好之后,每次 Claude Code 发请求都会经过 Headroom 压缩再转发到 cc-switch,最后由 cc-switch 注入 GLM key 送到智谱。实际使用下来,上下文压缩能省掉相当可观的 token 量,再加上 GLM 本身比 Claude 便宜很多,这套链路长期用下来确实能省不少。

唯一需要留意的就是那个 cc-switch 覆写 base URL 的坑,记住每次动过 cc-switch 后改回来就行。如果只是稳定用同一个 GLM provider,配好之后几乎不用再管它。


关于作者

本文作者 tenxiaodao,专注 AI 工程化与开发者工具效率实践。更多技术文章可访问:tenxiaodao.top

相关推荐
武子康16 小时前
Pi vs Claude Code vs Codex 正确读法:6 组同模型匹配 + 2.08×/1.46×/1.20×/1.54×/1.22×/1.44× 成
人工智能·ai编程·claude
码哥字节16 小时前
Superpowers 6.0 的 SDD 重写,我扒了源码才知道:token 砍半不是优化,是设计哲学的转向
ai编程·claude
寅时码1 天前
一次配置,同步到七个 AI CLI【ClaudeCode、Codex、OpenCode...】
openai·ai编程·claude
武雄(小星Ai)3 天前
2026年7月 AI 编程工具横评:Claude Code vs Cursor vs GitHub Copilot 实测对比
ai·开发工具·claude·cursor·对比评测
redreamSo3 天前
32 个 AI 编程工具的配置都放哪,这个仓库整理清楚了
ai编程·claude·cursor
9i编程3 天前
国内直连 Claude Code 本地部署完整实操手册 ——DeepSeek 兼容接口版
ai编程·claude
武子康3 天前
Claude Code 权限分析器为什么必须 Fail Closed:v2.1.214 暴露的 5 类边界 + 6 类不能推出的结论
人工智能·ai编程·claude