Headroom + cc-switch + GLM:给 Claude Code 省钱的代理链路搭建指南

Headroom + cc-switch + GLM:给 Claude Code 省钱的代理链路搭建指南
周言志把 Claude Code 的 API 调用链路改成
Claude Code → Headroom → cc-switch → GLM,用国产模型替代 Claude 的同时,靠 Headroom 压缩上下文进一步降低 token 消耗。本文记录完整的搭建过程。
为什么要这么折腾
Claude Code 用起来很爽,但 Claude 的 API 价格摆在那里——尤其是长上下文对话,token 消耗很快。国内智谱 GLM 提供了 Anthropic 兼容接口,可以完全替代 Claude 的模型层,价格低很多。当然claude也可以用,同理。
但光替换模型还不够。Claude Code 默认会把完整对话历史每次都发上去,如果能在中间加一层压缩代理,剪掉冗余的上下文,token 消耗还能再省一笔。
所以最终链路设计成这样:
1 | Claude Code → Headroom (:8787,压缩上下文) |
三个组件各司其职:
- 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:
1 | curl -LsSf https://astral.sh/uv/install.sh | sh |
安装后 uv 在 ~/.local/bin/uv,确认一下:
1 | ~/.local/bin/uv --version |
如果提示找不到命令,把 ~/.local/bin 加进 PATH,写进 ~/.zshrc:
1 | export PATH="$HOME/.local/bin:$PATH" |
第二步:用 uv 创建 Python 3.12 环境并安装 Headroom
系统 Python 3.9 太旧了,用 uv 自带的 Python 管理功能建一个新环境:
1 | uv venv ~/.headroom-venv --python 3.12 |
验证安装:
1 | ~/.headroom-venv/bin/headroom --version |
第三步:配置 cc-switch
打开 CC Switch.app,添加一个 provider,类型选 Anthropic 兼容:
- Base URL:
https://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,内容大致长这样:
1 | { |
注意 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:
1 | cat > ~/.headroom-start.sh <<'EOF' |
几个关键环境变量:
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。
先手动跑一次,确认能起来:
1 | ~/.headroom-start.sh |
确认无误后 Ctrl+C 停掉,下一步交给 launchd 托管。
第五步:用 launchd 设置开机自启
创建 ~/Library/LaunchAgents/com.headroom.proxy.plist:
1 | cat > ~/Library/LaunchAgents/com.headroom.proxy.plist <<'EOF' |
加载并启动:
1 | launchctl load ~/Library/LaunchAgents/com.headroom.proxy.plist |
看到 com.headroom.proxy 出现在列表里就对了。plist 的几个关键配置:
RunAtLoad=true:开机或加载时自动启动。KeepAlive=true:进程意外退出会自动拉起。ThrottleInterval=10:崩溃重启的最小间隔 10 秒,防止重启风暴。- 日志统一写到
/tmp/headroom-proxy.log。
日常管理命令:
1 | # 停止 |
第六步:把 Claude Code 的 base URL 指向 Headroom
cc-switch 默认会把 ANTHROPIC_BASE_URL 写成 http://127.0.0.1:15721(直连 cc-switch)。要插入 Headroom,需要改成 :8787:
1 | python3 - <<'EOF' |
改完后必须重启 Claude Code——当前会话用的还是改之前的 base URL,不重启不生效。
第七步:验证整条链路
直接请求 Headroom,确认能拿到 GLM 的回复
1 | curl -s -X POST http://127.0.0.1:8787/v1/messages \ |
正常应该返回带 msg_... id 的 JSON,content 是 GLM 的回复内容。
Headroom 自检
1 | ~/.headroom-venv/bin/headroom doctor --port 8787 |
注意 doctor 的 /livez 探针对 Headroom 自己的端口有效,不要让它去探 cc-switch 的 15721。
检查 launchd 状态
1 | 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 ~/Library/LaunchAgents/com.headroom.proxy.plist;在但崩了就看 /tmp/headroom-proxy.log。
Q: 改了 cc-switch 后 Claude Code 不压缩了?
A: 检查 ~/.claude/settings.json 里 ANTHROPIC_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,配好之后几乎不用再管它。




