文章

SP-06 · Claude Code 本地代理接入实战

#119 · 2026-05-09 · 21ZHAO Blog

引言:不是“装个客户端”,而是把整条链路跑通

很多人第一次接触 Claude Code,会把它理解成“装一个命令行工具,然后直接用”。真正的大坑在于:很多演示视频只展示“一句话生成代码”的爽感,却不提醒你后台可能正在持续调用昂贵模型,复杂项目一跑就是连续烧 API 额度。

所以这篇文章的核心目标不是“再装一个 AI 工具”,而是把算力定价权先拿回手里。你这次手上的材料,本质上也不是单点安装,而是一条完整链路:

  • 本地先装好 claude-code
  • 再用 uv 管理 Python 运行环境
  • 启动 free-claude-code 这个本地代理服务
  • 最后通过环境变量,把 Claude Code 的请求转发到你的本地代理

这就像你家里不是只买了一台电视,而是把“机顶盒、路由器、网线、显示器”全接起来。任何一个环节没通,最后终端里那个 claude 命令都只会卡住、报错,或者根本连不上。

本文就把这条链路按“安装 -> 配置 -> 启动 -> 理解原理”的顺序拆开,整理成一篇可以直接照着跑的实战手册。


Step 1:先装底座,别一上来就碰代理

痛点解析:很多人看到“free-claude-code”就直接克隆仓库,结果后面才发现机器上连 brewclaude-codeuv 都没准备好。这样排错会非常乱,因为你根本不知道是代理没配好,还是基础工具没装对。

建议顺序是:先装系统级工具,再装 Python 工具链,最后再接代理服务

如果你是准备长期把这套链路当成 24 小时待命的私有 AI 工作台,一个很实用的硬件选择是:Mac mini M1 16G 起步,或者更新的 M4。原因不神秘:

  • 功耗低,适合常开
  • 稳定,适合做固定网关机
  • 数据落本地,排错和迁移都更可控

它不一定是“最强”的机器,但对大多数想先把 Claude Code 跑顺的人来说,是非常稳的起点。

1.1 安装 Homebrew

如果是第一次在 macOS 上配环境,先装 Homebrew:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
eval "$(/opt/homebrew/bin/brew shellenv)"

这里第二、第三行别省。它的作用就像把新装的工具目录写进系统“导航图”。如果不执行,后面你明明装好了 brew,终端却还是提示“command not found”。

如果你在国内网络环境下拉官方脚本很慢,或者直接失败,也可以先看镜像站的当前说明,再决定是否切换镜像。常见选择有清华镜像、阿里镜像这类公开源。这里一定要强调一句:镜像配置经常会迭代,最稳妥的做法永远是以镜像站当下的帮助页为准。

如果你只是想先跑通,可以参考这种阿里镜像示例

git clone https://mirrors.aliyun.com/homebrew/install.git brew-install
/bin/bash brew-install/install.sh
rm -rf brew-install

安装完成后,如果后续 brew update 或安装包依然很慢,可以再按镜像站文档配置 API / bottle 地址。比如阿里镜像常见写法会像这样:

export HOMEBREW_API_DOMAIN="https://mirrors.aliyun.com/homebrew-bottles/api"
export HOMEBREW_BOTTLE_DOMAIN="https://mirrors.aliyun.com/homebrew/homebrew-bottles"
brew update

你可以把它理解成:Homebrew 本体装好了,但“仓库索引”和“预编译包下载地址”也要走更近的路,速度才会明显改善。

1.2 安装 Claude Code

brew install --cask claude-code

装完以后,建议先确认命令已经进 PATH:

claude --version

如果这里还找不到命令,就不要继续往下装代理,先把 PATH 问题解决。

1.3 安装 uv 与 Python 3.14

curl -LsSf https://astral.sh/uv/install.sh | sh
uv self update
uv python install 3.14

uv 在这条链路里相当于“轻量级发动机舱”。后面的 free-claude-code 依赖 Python 环境跑起来,用它来装和管 Python 版本会比系统自带环境干净很多。


Step 2:拉下 free-claude-code,并补齐本地配置

痛点解析:很多开源代理项目真正难的不是 git clone,而是“克隆完以后要补哪些配置”。如果 .env 没配,服务虽然能启动,但内部参数是空的,效果和没配一样。

2.1 克隆仓库

git clone https://github.com/Alishahryar1/free-claude-code.git
cd free-claude-code

2.2 复制环境变量模板

cp .env.example .env
sudo nano .env

这一步的关键不是“会不会用 nano”,而是你要意识到:代理服务真正吃的是 .env 里的配置。模板只是空白表格,真正决定服务能不能工作的,是你后面填进去的参数。

如果你打算接入 NVIDIA 免费 API,这里通常就要把对应的 API Key、上游地址或项目要求的其它变量写进去。它的好处是对入门者门槛低:通常可以直接注册申请,不需要先绑信用卡,更适合拿来跑通第一条链路。

不同第三方项目字段名可能会变化,所以最稳妥的做法永远是:

  1. 先看仓库 README
  2. 再对照 .env.example
  3. 最后再写你自己的 .env

第一次用 nano 的读者,最容易卡在“改完了怎么保存”。流程其实很简单:

  1. 改完配置后按 Ctrl + X
  2. 终端提示是否保存时输入 Y
  3. 再按一次回车确认文件名

这样 .env 才是真的写回磁盘,不是只在屏幕上看起来改过了。

官方/项目入口:


Step 3:启动本地代理服务,让“中间层”先活起来

痛点解析:很多人会先跑 claude,再看见报错后才去想“代理是不是没开”。顺序反了。正确方式是:先让本地代理存活,再把客户端指过去

这里推荐你开两个终端窗口,别在一个窗口里来回切。一个专门负责跑网关,一个专门负责跑 Claude Code,排错会清楚很多。

在终端 A 中运行:

cd /Users/eight/free-claude-code
uv run uvicorn server:app --host 0.0.0.0 --port 8082

这条命令的角色很像“前台接待”。Claude Code 不直接去找远端服务,而是先把请求交给这个本地代理,再由代理决定如何转发。

这里有两个实战点值得记住:

  • --port 8082 意味着后续客户端要指向 http://localhost:8082
  • 这个终端需要保持运行,不要启动完就关掉

如果你希望先确认代理是否真的起来了,可以单独开一个窗口访问:

curl http://localhost:8082

至于返回什么,要看这个项目有没有默认根路由;但至少你可以先判断端口是不是活着。


Step 4:在另一个终端里把 Claude Code 指到本地代理

痛点解析:很多人会把“装好 Claude Code”误以为“它已经知道该连谁”。其实默认情况下,客户端并不知道你本地还有个代理服务。你必须明确告诉它:认证 token 是什么、上游地址是谁。

在终端 B 中运行:

ANTHROPIC_AUTH_TOKEN="freecc" \
ANTHROPIC_BASE_URL="http://localhost:8082" \
claude

这两行环境变量的作用可以这样理解:

  • ANTHROPIC_AUTH_TOKEN="freecc":给 Claude Code 一个占位认证值,让它满足调用流程
  • ANTHROPIC_BASE_URL="http://localhost:8082":把默认上游改成你的本地代理

也就是说,真正的请求路径已经变成:

Claude Code -> localhost:8082 -> free-claude-code -> 上游模型/API

这就像你打车时不是自己冲去机场,而是先坐接驳车到航站楼,再从航站楼接入后续航班。claude 只是前端入口,free-claude-code 才是这次链路里的中转站。

这里还有一个很容易让新手困惑的现象:你接进去的实际后端模型,和 Claude Code 在对话里“自称”的模型,不一定一致。这是因为你真正复用的是 Claude Code 这套终端交互和编程工作流 harness,而后端推理模型已经被你换成了兼容网关后面的其它模型。换句话说,前台招牌可能还是熟悉的那个名字,但后厨已经换人了。


Step 5:把它收成一个一键命令,别每次手敲整串环境变量

痛点解析:手动启动一次当然不难,但你只要连续用三天,就会开始嫌烦:要先看端口有没有占用、要判断代理有没有活着、要记住 ANTHROPIC_BASE_URL、还要手敲模型名。真正顺手的做法,是把这条链路封成一个 shell 函数。

如果你已经把 free-claude-code 放在 /Users/zhaosj/free-claude-code,可以把下面这段函数加进 ~/.zshrc~/.bashrc

start_free_claude_code() {
  local repo="/Users/zhaosj/free-claude-code"
  local host="127.0.0.1"
  local port="8082"
  local fallback_port="18082"
  local token="freecc"
  local base_url=""
  local provider_model="nvidia_nim/z-ai/glm-5.1"
  local gateway_model=""

  export PATH="$HOME/.local/bin:$PATH"
  gateway_model="anthropic/${provider_model}"

  if curl -fsS "http://${host}:${port}/health" >/dev/null 2>&1; then
    base_url="http://${host}:${port}"
  elif ! lsof -nP -iTCP:${port} -sTCP:LISTEN >/dev/null 2>&1; then
    (
      cd "$repo" || exit 1
      nohup uv run uvicorn server:app --host "$host" --port "$port" >/tmp/free-claude-code.log 2>&1 &
    )
    sleep 2
    if curl -fsS "http://${host}:${port}/health" >/dev/null 2>&1; then
      base_url="http://${host}:${port}"
    fi
  fi

  if [ -z "$base_url" ]; then
    if ! curl -fsS "http://${host}:${fallback_port}/health" >/dev/null 2>&1; then
      (
        cd "$repo" || exit 1
        nohup uv run uvicorn server:app --host "$host" --port "$fallback_port" >/tmp/free-claude-code.log 2>&1 &
      )
      sleep 2
    fi
    base_url="http://${host}:${fallback_port}"
  fi

  ANTHROPIC_BASE_URL="$base_url" \
  ANTHROPIC_API_URL="${base_url}/v1" \
  ANTHROPIC_API_KEY="$token" \
  CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1 \
  claude --bare --model "$gateway_model"
}

alias fcc='start_free_claude_code'

加完以后执行:

source ~/.zshrc

后面你只需要输入:

fcc

它做的事情其实很完整,不只是“起一个命令别名”:

  • 先检查 8082 上的健康接口是否已经可用
  • 如果主端口空着,就自动拉起 uvicorn
  • 如果主端口不可用但又没成功接管,就切到 18082
  • 自动拼出 ANTHROPIC_BASE_URLANTHROPIC_API_URLANTHROPIC_API_KEY
  • 自动把模型名包装成 gateway 识别格式:anthropic/nvidia_nim/z-ai/glm-5.1

这段函数最像什么?像一个“终端里的前台值班员”。你只说一句 fcc,它会自己先看门开没开、服务活没活、备用门牌能不能顶上,最后再把 Claude Code 送进去。

这也是为什么很多人会觉得“明明换了模型,为什么 Claude Code 用起来还是那个味道”。因为真正被你保留下来的,不只是一个 API 壳,而是它整套终端交互、上下文编排和代码工作流。模型换了,驾驶舱没换。

如果你不是用 zsh,而是 bash,那就把它写进 ~/.bashrc,然后执行 source ~/.bashrc


Step 6:最容易出错的 4 个点

痛点解析:这类链路不是“命令不会写”,而是细节特别容易漏。一旦漏掉,看起来每一步都像没问题,实际上整条线就是不通。

6.1 Homebrew 安装后没执行 shellenv

现象:

  • brew 装完了
  • 新开终端却提示找不到 brew

原因就是 PATH 没刷进去。前面那两条 shellenv 命令一定要执行。

6.2 Claude Code 已装,但命令不可用

先检查:

claude --version

如果这里就不通,问题还停留在客户端安装层,不是代理层。

6.3 代理服务没起来,就先跑客户端

如果 localhost:8082 上没有服务,你再怎么改环境变量也没用。客户端只是被正确地指到了一个不存在的门牌号。

6.4 .env 只复制了模板,没有真正填值

这是最常见的“看起来都做了,实际上没做”的问题。.env.example 是说明书,不是配置结果。真正运行时吃的是 .env


Step 7:这套链路为什么适合放进教程,而不是只发一段命令

只发一段命令清单,读者很容易照抄,但不知道为什么这么做。一旦某一步失败,就只能在终端里“玄学重试”。

写成教程型博客的价值在于,它把原本分散的信息重组为三层:

  1. 动作层:具体命令怎么敲
  2. 链路层:请求到底经过了哪些节点
  3. 排错层:出问题时先查客户端、代理,还是 .env

再往上一层,其实还有第 4 层:

  1. 成本层:你是否真的掌握了模型选择权和费用上限

这也是技术博客和聊天记录最大的区别:聊天记录只解决“你当时怎么装”,教程文章要解决“别人下次为什么也能装通”。


推荐的最终操作顺序

如果你要把这套流程真正跑起来,建议按下面这个顺序执行:

  1. 安装 Homebrew,并执行 shellenv
  2. 安装 Claude Code,确认 claude --version
  3. 安装 uv 和 Python 3.14
  4. 克隆 free-claude-code
  5. 复制 .env.example.env 并补齐配置
  6. 先用双终端方式手动跑通一次
  7. 再把 start_free_claude_code()alias fcc=... 写进 shell 配置
  8. 以后统一用 fcc 启动

只要你把这个顺序守住,整条链路就不会乱。


参考来源


架构师结语

很多“环境搭不起来”的问题,表面上看是命令没记住,实际上是没有把系统当成一条链路来理解。一旦你知道客户端、代理、配置文件、上游模型各自扮演什么角色,排错就不再像在黑屋里摸开关,而像顺着电路图一段一段排查。

工具会变,命令也会变,但这种“先建链路、再谈体验”的工程习惯,不会过时。