手摸手给 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

相关推荐
Avan_菜菜11 小时前
使用 Docker + rclone 自建 WebDAV
后端·agent·claude
浩风祭月17 小时前
AI 改代码总爱顺手重构?一份 Task Contract 把修改范围锁住
ai编程·claude·cursor
ServBay18 小时前
Claude Code 被曝植入后门,AI 时代如何安全打造本地 DevOps
后端·ai编程·claude
Fanta丶20 小时前
1.VibeCoding 终端命令基础使用
claude
colir020 小时前
被粉丝夸爆的超级 ai 个人工作站,原来这么多福利
开源·agent·claude
用户600071819101 天前
【翻译】循环(loops)入门指南
claude
洛卡卡了1 天前
Claude Code Hook,当 CLAUDE.md 规则不生效时,我们还需要强制拦截机制
后端·agent·claude
码哥字节1 天前
我拿 Opus 4.8、GPT-5.5、Gemini 3.1 Pro 测了同一套任务,输赢比你想的复杂
ai编程·claude
ZzT1 天前
Claude Sonnet 5 来了:Opus 级的能力,Sonnet 的价
人工智能·ai编程·claude