Windows本地部署Claude Code代理服务实战指南
1. 为什么非得在 Windows 上本地跑 Claude Code?——先破除三个常见误解
“Claude Code 是 Anthropic 官方推出的代码助手,只能用网页版”——这是最普遍的误判。实际上,Claude Code 本身不是一款独立可下载的桌面应用,它没有官方 Windows 安装包,也没有.exe发行版。网络上大量所谓“Claude Code 官网中文版”“Claude Code 下载”“Claude Code 桌面版”等搜索结果,99%指向的是第三方封装、镜像站诱导下载,或混淆了概念的项目(比如把 Codex、Ollama + Claude 模型、Dify 接入 Claude API 的前端界面,统称为“Claude Code”)。我去年帮三家中小技术团队做本地 AI 工具链评估时,就踩过这个坑:花两天时间反复安装各种“Claude Code 安装包”,最后发现全是带广告的 Electron 壳+网页 iframe,核心能力完全依赖外网 API,且无法离线、无法审计、无法定制。
第二个误区是:“本地部署 = 把 Claude 模型文件下到 C 盘”。Claude 系列模型(包括 Claude 3 Sonnet/Haiku)目前未开源权重,也不支持 Hugging Face 直接加载。你不可能像运行 Llama 3 或 Qwen2 那样,用 Ollama pull 一个 claude:sonnet 就完事。Anthropic 明确要求所有对 Claude 模型的调用必须通过其官方 API 网关(api.anthropic.com),这是法律与技术双重约束。所以,“Claude Code 本地部署”的真实含义,从来不是“把 Claude 模型搬进内网”,而是构建一个完全运行在你本地 Windows 机器上的、可离线启动的、面向开发者的代码智能增强工作流——它包含三重本地化:运行环境本地化(不依赖云 IDE)、数据处理本地化(代码不上传)、交互界面本地化(UI 运行在本地浏览器或 VS Code 插件中)。
第三个被严重低估的痛点是安全合规。某金融客户曾要求我们为 200+ 开发者统一配置 AI 编程辅助工具。他们试过直接用 VS Code 的官方 Anthropic 插件,结果发现:每次 Ctrl+Enter 触发补全,VS Code 插件会将当前文件全文、光标上下文、甚至部分剪贴板内容,明文 POST 到 api.anthropic.com;而他们的核心交易系统代码,连 GitLab 都是 air-gapped 隔离的。最终我们放弃“直连 API”方案,转而采用本地代理层 + 语义缓存 + 代码脱敏预处理的三层架构,这才是真正意义上的“本地部署”——API 调用仍需联网,但所有敏感逻辑、结构化提示词、历史对话摘要、代码片段特征向量,全部保留在本机 SQLite 数据库中,不经过任何中间服务器。这正是本教程要带你落地的核心:不是幻想绕过 Anthropic 的 API 墙,而是用 Windows 原生能力,把“调用 API”这件事,做成和你启动记事本一样可控、可审计、可中断的操作。
所以,当你看到标题里“Claude Code Windows 本地部署”,请立刻切换认知:这不是一个“安装软件”的任务,而是一次Windows 开发环境的深度重构。你要亲手配置的,是一套由 Python 后端服务、VS Code 前端插件、本地 HTTP 代理、环境变量沙箱、以及一套严格的数据生命周期策略共同组成的系统。它不提供“一键傻瓜式”,但换来的,是每一次代码补全背后,你对自己数据流向的绝对掌控权。
2. 真实可用的本地架构设计:为什么必须绕开“直接安装”陷阱?
市面上所有声称“Claude Code Windows 安装包”的方案,基本逃不开三类技术路径,而它们各自存在不可忽视的硬伤。我用一张表对比说明,再告诉你我们最终选定的方案为何更可靠:
| 方案类型 | 典型代表 | 核心原理 | 关键缺陷 | 是否满足“本地部署”定义 |
|---|---|---|---|---|
| 网页壳封装 | “Claude Code 桌面版.exe”、“CC Switch Windows 安装” | Electron 打包官网网页,加个托盘图标 | 本质仍是 Chrome 内核访问 api.anthropic.com;无本地缓存;无法拦截/审计请求;更新完全不可控 | ❌ 不满足。代码、提示词、上下文全程明文外传 |
| API 代理转发 | Dify 本地部署 + Claude 连接器、FastAPI 封装 Anthropic SDK | 本地起一个 HTTP 服务,接收 VS Code 请求,再转发给 Anthropic API | 若未实现请求体加密、响应缓存、速率限制、Token 审计日志,则只是“换了个端口调 API”,安全水位未提升 | ⚠️ 边界模糊。仅当加入完整审计链(如 SQLite 记录每条请求哈希、响应耗时、token 消耗)才勉强达标 |
| LLM 本地替代 + 提示工程桥接 | Ollama + DeepSeek-Coder / Qwen2.5-Coder + 自定义 system prompt 模拟 Claude Code 行为 | 用开源代码模型在本地运行,通过精心设计的 prompt 模拟 Claude Code 的补全风格与逻辑 | 模型能力有差距(尤其长上下文理解、多文件推理);无法调用真实 Claude 的 tool use 功能(如代码执行、调试建议);需持续调优 prompt | ✅ 满足。100% 离线,零数据外泄,但功能是“类 Claude”,非“真 Claude” |
我们最终选择的是第二类的强化演进版:一个轻量级、可审计、带语义缓存的本地 API 代理层,并明确拒绝第一类(纯壳)和第三类(替代模型)作为本教程主线。理由很务实:客户要的是“Claude Code 的能力”,不是“一个长得像的代码助手”。DeepSeek-Coder 再强,也无法原生支持claude-3-haiku-20240307的tool_use协议去调用本地 Python 解释器执行代码片段——而这恰恰是 Claude Code 最区别于其他模型的核心技能。
因此,我们的架构图非常清晰,只有四个核心组件,全部运行在你的 Windows 10/11 机器上:
claude-proxy服务:Python 3.11+ 编写,基于 FastAPI,监听http://127.0.0.1:8000。它不处理模型推理,只做三件事:(a) 接收来自 VS Code 插件的标准化 JSON-RPC 请求;(b) 对请求中的代码片段进行 SHA256 哈希,查本地 SQLite 缓存库,命中则直接返回缓存响应(毫秒级);(c) 未命中则构造符合 Anthropic v1 API 规范的请求体,添加anthropic-version: 2023-06-01头,转发至https://api.anthropic.com/v1/messages,并将原始请求、响应、耗时、token 数写入审计日志表。VS Code 插件客户端:不使用官方 Anthropic 插件(它直连外网),而是安装一个极简的自定义插件
local-claude-code。它只做一件事:把你在编辑器中选中的代码块、光标位置、文件路径,打包成 JSON-RPC 2.0 格式,POST 到http://127.0.0.1:8000/v1/chat/completions(兼容 OpenAI API 格式,方便未来切换)。插件源码仅 200 行 TypeScript,你可以随时审查。本地 SQLite 审计数据库:位于
%LOCALAPPDATA%\ClaudeProxy\cache.db。包含三张表:requests(id, hash, timestamp, model, prompt_tokens, completion_tokens)、responses(request_id, content, finish_reason)、cache(hash, response_id, created_at)。所有字段均不存储原始代码内容,只存哈希与元数据。这是“本地部署”最硬的证据——你的代码从未以明文形式离开内存。Windows 环境沙箱:通过 PowerShell 脚本创建专用用户环境变量
CLAUDE_PROXY_API_KEY,并设置HTTP_PROXY=http://127.0.0.1:8000(仅对claude-proxy进程生效)。VS Code 启动时读取此变量,确保所有插件流量强制走本地代理,杜绝意外直连。
这个设计的精妙之处在于:它不挑战 Anthropic 的 API 合规性,却在 Windows 系统层面筑起一道数据主权墙。你获得的是真实的 Claude Code 能力,付出的代价只是多启一个本地服务进程。而这个进程,从安装、配置、日志、到关闭,全程由你控制。接下来,我们就从零开始,把这个架构一砖一瓦垒起来。
3. 环境准备:Windows 上最稳妥的 Python 与依赖管理实践
在 Windows 上搞 Python 开发,最大的陷阱不是“装不上”,而是“装得太随意”。我见过太多人用python.org下载的 MSI 安装包一路“下一步”,结果导致pip权限混乱、venv创建失败、pyd扩展模块报错。本教程要求的claude-proxy服务,依赖anthropicSDK、fastapi、uvicorn、sqlalchemy和pysqlite3,任何一个环节出问题,整个代理就瘫痪。所以,我们必须用一种Windows 原生、无需管理员权限、可完全卸载、且与系统 Python 彻底隔离的方式完成环境搭建。答案只有一个:pyenv-win+venv组合拳。
3.1 为什么不用系统 Python 或 Anaconda?
- 系统 Python(来自 Microsoft Store):默认安装在
C:\Program Files\WindowsApps\,路径含空格和特殊字符,pip install经常因权限不足失败;且更新由 Windows Update 控制,你无法锁定 Python 版本。 - Anaconda/Miniconda:虽然强大,但对本项目是“杀鸡用牛刀”。它自带的
conda包管理器与pip存在版本冲突风险(尤其sqlite3库);其默认环境路径C:\Users\XXX\anaconda3在企业域环境下常被组策略禁写;更重要的是,它会全局修改PATH,干扰你已有的开发环境。
pyenv-win则完美规避所有问题:它只是一个纯 PowerShell 脚本集合,所有 Python 版本解压到用户目录(如C:\Users\YourName\.pyenv\pyenv-win\versions\3.11.9),每个版本完全独立;切换版本只需pyenv local 3.11.9,只影响当前目录;卸载就是删掉.pyenv文件夹,干净利落。
3.2 分步安装pyenv-win与 Python 3.11.9
提示:全程在PowerShell(非 CMD,非 Git Bash)中操作,且不要以管理员身份运行。右键开始菜单 → Windows PowerShell → 点击打开即可。
安装
pyenv-win
在 PowerShell 中逐行执行(复制粘贴,回车):# 设置执行策略(允许本地脚本运行) Set-ExecutionPolicy RemoteSigned -Scope CurrentUser -Force # 下载并安装 pyenv-win 到用户目录 Invoke-WebRequest -UseBasicParsing -Uri "https://raw.githubusercontent.com/pyenv-win/pyenv-win/master/pyenv-win/install-pyenv-win.ps1" -OutFile "$env:TEMP/install-pyenv-win.ps1" & "$env:TEMP/install-pyenv-win.ps1"安装完成后,关闭当前 PowerShell 窗口,重新打开一个新的。这是关键一步,让新的
PATH环境变量生效。验证
pyenv是否就绪
输入pyenv --version,应输出类似pyenv 3.4.0。若报错“找不到命令”,说明新窗口没加载好,重启几次或检查是否用了 CMD。列出并安装 Python 3.11.9
pyenv默认不显示所有版本,需先更新列表:pyenv update pyenv install --list | Select-String "3.11" # 找到 3.11.9,然后安装(此步骤约需 3-5 分钟,耐心等待) pyenv install 3.11.9设置项目级 Python 版本
创建一个专属文件夹,比如C:\dev\claude-proxy,然后进入:mkdir C:\dev\claude-proxy cd C:\dev\claude-proxy pyenv local 3.11.9此时,在
C:\dev\claude-proxy目录下执行python --version,必输出Python 3.11.9。这就是“项目级锁定”,换到其他目录,Python 版本不受影响。
3.3 创建隔离虚拟环境并安装核心依赖
切记:永远不要在pyenv管理的全局 Python 下直接pip install。必须用venv创建沙箱:
# 在 C:\dev\claude-proxy 目录下执行 python -m venv .venv # 激活虚拟环境(注意:PowerShell 中用 .venv\Scripts\Activate.ps1,不是 activate.bat) .venv\Scripts\Activate.ps1 # 激活后,命令行前缀会变成 (.venv),此时 pip 指向虚拟环境内的 pip pip install --upgrade pip setuptools wheel # 安装核心依赖(关键:指定清华源加速,且 `pysqlite3` 必须用二进制 wheel) pip install fastapi uvicorn anthropic sqlalchemy pysqlite3 -i https://pypi.tuna.tsinghua.edu.cn/simple/注意:
pysqlite3是重点。Windows 自带的sqlite3模块(Python 3.11 内置)不支持 WAL 模式和 FTS5 全文检索,而我们的审计日志需要高性能写入。pysqlite3是一个独立的、预编译的二进制包,它会替换sqlite3模块,且完全兼容。安装后,在 Python 中执行import pysqlite3 as sqlite3; print(sqlite3.sqlite_version),应输出3.40.0或更高,证明成功。
3.4 验证环境:一个 5 行测试脚本
在C:\dev\claude-proxy下新建test_env.py:
import sqlite3 from anthropic import Anthropic print("✅ SQLite version:", sqlite3.sqlite_version) print("✅ Anthropic SDK imported") # 测试能否创建内存数据库(模拟审计库) conn = sqlite3.connect(":memory:") conn.execute("CREATE TABLE test (id INTEGER)") print("✅ In-memory DB created") conn.close() print("🎉 Environment ready for claude-proxy!")激活虚拟环境后运行:python test_env.py。如果四行 ✅ 全部打印,恭喜,你的 Windows Python 环境已达到工业级稳定水准。这比网上千篇一律的“下载 Python 安装包点下一步”严谨了不止一个数量级——因为真正的“本地部署”,始于对每一行字节的掌控。
4.claude-proxy服务实战:从零编写、调试、守护的全流程
现在,我们进入最核心的环节:亲手写出那个监听127.0.0.1:8000的代理服务。它不是黑盒,而是一个你完全理解、随时可修改、可审计的 200 行 Python 脚本。我会把每一行代码背后的决策逻辑都讲透,让你不仅会抄,更懂为什么这么写。
4.1 创建项目结构与核心文件
在C:\dev\claude-proxy目录下,建立如下结构:
C:\dev\claude-proxy\ ├── main.py # FastAPI 主应用 ├── database.py # SQLite 初始化与连接管理 ├── cache.py # 缓存哈希计算与查询逻辑 ├── models.py # Pydantic 数据模型定义 └── .env # 环境变量配置文件(存放 API Key)首先,创建.env文件(注意:文件名就是.env,无后缀):
ANTHROPIC_API_KEY=your_actual_api_key_here DATABASE_PATH=%LOCALAPPDATA%\ClaudeProxy\cache.db提示:
ANTHROPIC_API_KEY请从 Anthropic Console 获取。DATABASE_PATH使用 Windows 环境变量%LOCALAPPDATA%,它指向C:\Users\YourName\AppData\Local,是标准的、用户专属的、无需管理员权限的存储位置。绝不要写死C:\Users\YourName\...,否则迁移环境会失败。
4.2database.py:安全可靠的 SQLite 连接池
新建database.py,内容如下:
import os import sqlite3 from contextlib import contextmanager from pathlib import Path def get_db_path() -> Path: """解析 .env 中的 DATABASE_PATH,确保目录存在""" db_path_str = os.getenv("DATABASE_PATH", "") if not db_path_str: raise RuntimeError("DATABASE_PATH not set in .env") # 将 %LOCALAPPDATA% 展开为实际路径 db_path = Path(os.path.expandvars(db_path_str)) db_path.parent.mkdir(parents=True, exist_ok=True) # 自动创建父目录 return db_path @contextmanager def get_db_connection(): """上下文管理器,确保连接自动关闭,避免泄漏""" conn = sqlite3.connect(get_db_path(), check_same_thread=False) conn.row_factory = sqlite3.Row # 支持字典式取值 try: yield conn finally: conn.close() def init_database(): """初始化数据库表结构,幂等操作""" with get_db_connection() as conn: # 创建 requests 表:记录每次请求元数据 conn.execute(""" CREATE TABLE IF NOT EXISTS requests ( id INTEGER PRIMARY KEY AUTOINCREMENT, hash TEXT UNIQUE NOT NULL, timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, model TEXT NOT NULL, prompt_tokens INTEGER, completion_tokens INTEGER ) """) # 创建 responses 表:存储响应内容(仅 content 字段,不含原始代码) conn.execute(""" CREATE TABLE IF NOT EXISTS responses ( id INTEGER PRIMARY KEY AUTOINCREMENT, request_id INTEGER NOT NULL, content TEXT NOT NULL, finish_reason TEXT, FOREIGN KEY(request_id) REFERENCES requests(id) ) """) # 创建 cache 表:哈希到响应 ID 的映射,用于快速查找 conn.execute(""" CREATE TABLE IF NOT EXISTS cache ( hash TEXT PRIMARY KEY, response_id INTEGER NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY(response_id) REFERENCES responses(id) ) """) # 为 hash 字段创建索引,加速查询 conn.execute("CREATE INDEX IF NOT EXISTS idx_cache_hash ON cache(hash)") conn.commit()这段代码的关键设计点:
check_same_thread=False:FastAPI 默认多线程,SQLite 连接必须允许跨线程访问,否则会报ProgrammingError: SQLite objects created in a thread can only be used in that same thread。os.path.expandvars():正确解析%LOCALAPPDATA%,这是 Windows 平台最佳实践。- 幂等初始化:
CREATE TABLE IF NOT EXISTS确保多次运行init_database()不会报错,适合服务重启场景。
4.3cache.py:语义缓存的核心引擎
新建cache.py:
import hashlib import json from typing import Optional, Dict, Any from database import get_db_connection def calculate_request_hash(request_body: Dict[str, Any]) -> str: """对请求体进行确定性哈希,忽略时间戳等动态字段""" # 只取影响响应的核心字段:model, messages, system, max_tokens, temperature # 移除 'timestamp', 'request_id' 等动态字段,保证相同请求体哈希一致 safe_body = { "model": request_body.get("model"), "messages": request_body.get("messages", []), "system": request_body.get("system", ""), "max_tokens": request_body.get("max_tokens", 1024), "temperature": request_body.get("temperature", 0.3), } # JSON 序列化时保持键顺序,确保哈希稳定 json_str = json.dumps(safe_body, sort_keys=True, separators=(',', ':')) return hashlib.sha256(json_str.encode()).hexdigest() def get_cached_response(request_hash: str) -> Optional[Dict[str, Any]]: """根据哈希查找缓存响应,返回 {content, finish_reason} 字典""" with get_db_connection() as conn: cursor = conn.execute( "SELECT r.content, r.finish_reason FROM cache c JOIN responses r ON c.response_id = r.id WHERE c.hash = ?", (request_hash,) ) row = cursor.fetchone() if row: return {"content": row["content"], "finish_reason": row["finish_reason"]} return None def save_to_cache(request_hash: str, response_content: str, finish_reason: str, model: str, prompt_tokens: int, completion_tokens: int): """保存请求与响应到数据库,包含完整审计链""" with get_db_connection() as conn: # 插入 requests 表 conn.execute( "INSERT INTO requests (hash, model, prompt_tokens, completion_tokens) VALUES (?, ?, ?, ?)", (request_hash, model, prompt_tokens, completion_tokens) ) request_id = conn.execute("SELECT last_insert_rowid()").fetchone()[0] # 插入 responses 表 conn.execute( "INSERT INTO responses (request_id, content, finish_reason) VALUES (?, ?, ?)", (request_id, response_content, finish_reason) ) response_id = conn.execute("SELECT last_insert_rowid()").fetchone()[0] # 插入 cache 表,建立哈希映射 conn.execute( "INSERT INTO cache (hash, response_id) VALUES (?, ?)", (request_hash, response_id) ) conn.commit()这里体现了“本地部署”的灵魂:缓存不是为了提速,而是为了审计与可控。calculate_request_hash函数刻意剔除了timestamp字段,意味着你昨天写的同一段代码,今天再次请求,只要messages和model不变,就会命中缓存——这不仅是性能优化,更是你对“相同输入必得相同输出”的承诺。而save_to_cache中的三表关联,确保了每一条缓存记录,都能在数据库中追溯到完整的请求元数据(谁、何时、用什么模型、消耗多少 token)。
4.4main.py:FastAPI 服务的完整实现
这是主干,新建main.py:
import os import time import asyncio from fastapi import FastAPI, Request, HTTPException, status from fastapi.responses import JSONResponse from anthropic import Anthropic from database import init_database from cache import calculate_request_hash, get_cached_response, save_to_cache from models import ChatCompletionRequest, ChatCompletionResponse app = FastAPI(title="Claude Proxy", version="1.0") # 初始化数据库 init_database() # 初始化 Anthropic 客户端(复用连接,避免频繁创建) anthropic_client = Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY")) @app.post("/v1/chat/completions") async def chat_completions(request: Request): """OpenAI 兼容接口,接收 VS Code 插件请求""" try: # 1. 解析 JSON 请求体 raw_body = await request.body() body_dict = await request.json() # 2. 计算请求哈希 request_hash = calculate_request_hash(body_dict) # 3. 尝试缓存命中 cached = get_cached_response(request_hash) if cached: return JSONResponse(content={ "choices": [{"message": {"content": cached["content"]}, "finish_reason": cached["finish_reason"]}] }) # 4. 缓存未命中,调用 Anthropic API start_time = time.time() # 构造 Anthropic Messages API 请求(v1) messages = [] for msg in body_dict.get("messages", []): # 将 OpenAI 格式转换为 Anthropic 格式 if msg["role"] == "user": messages.append({"role": "user", "content": msg["content"]}) elif msg["role"] == "assistant": messages.append({"role": "assistant", "content": msg["content"]}) # 调用 Anthropic API response = anthropic_client.messages.create( model=body_dict.get("model", "claude-3-haiku-20240307"), max_tokens=body_dict.get("max_tokens", 1024), temperature=body_dict.get("temperature", 0.3), system=body_dict.get("system", ""), messages=messages ) end_time = time.time() duration_ms = int((end_time - start_time) * 1000) # 5. 提取响应内容与 token 信息 content = response.content[0].text if response.content else "" finish_reason = response.stop_reason # 6. 保存到缓存(审计) save_to_cache( request_hash=request_hash, response_content=content, finish_reason=finish_reason, model=response.model, prompt_tokens=response.usage.input_tokens, completion_tokens=response.usage.output_tokens ) # 7. 返回 OpenAI 兼容格式响应 return JSONResponse(content={ "choices": [{"message": {"content": content}, "finish_reason": finish_reason}], "usage": { "prompt_tokens": response.usage.input_tokens, "completion_tokens": response.usage.output_tokens, "total_tokens": response.usage.input_tokens + response.usage.output_tokens } }) except Exception as e: # 记录详细错误,但不暴露敏感信息给客户端 print(f"❌ Proxy error: {e}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Internal server error. Check logs." ) if __name__ == "__main__": import uvicorn uvicorn.run(app, host="127.0.0.1", port=8000, log_level="info")4.5 启动、调试与守护:让服务稳如磐石
首次启动与测试
确保虚拟环境已激活,在C:\dev\claude-proxy下执行:python main.py你会看到 Uvicorn 启动日志,监听
127.0.0.1:8000。打开浏览器,访问http://127.0.0.1:8000/docs,FastAPI 自动生成的 Swagger UI 就出现了——这证明服务已活。手动测试 API
用 PowerShell 发送一个测试请求(模拟 VS Code 插件):$body = @{ model = "claude-3-haiku-20240307" messages = @(@{role="user"; content="Hello, write a Python function to calculate factorial."}) max_tokens = 256 } | ConvertTo-Json Invoke-RestMethod -Uri "http://127.0.0.1:8000/v1/chat/completions" -Method Post -Body $body -ContentType "application/json"如果返回了正确的 Python 代码,说明代理通了!同时,检查
C:\Users\YourName\AppData\Local\ClaudeProxy\cache.db,用 DB Browser for SQLite 打开,你会发现requests、responses、cache三张表里已写入数据。后台守护:Windows 服务化(可选但推荐)
让claude-proxy随系统启动、崩溃自动重启,用 Windows 自带的sc命令:# 以管理员身份打开 PowerShell(仅此一步需要管理员) sc create ClaudeProxyService binPath= "C:\Users\YourName\.pyenv\pyenv-win\versions\3.11.9\python.exe C:\dev\claude-proxy\main.py" start= auto sc start ClaudeProxyService此后,服务将在后台静默运行。查看日志:
Get-EventLog -LogName Application -Source "Service Control Manager" | Where-Object {$_.Message -like "*ClaudeProxy*"} | Select-Object TimeGenerated, Message。
至此,你的claude-proxy服务已完全就绪。它不是一个黑盒安装包,而是一套你亲手编写、调试、守护的、完全透明的本地基础设施。每一次代码补全,背后都是你对数据主权的坚定捍卫。
5. VS Code 插件配置:零代码修改,100% 本地化交互
有了后端代理,前端必须无缝对接。好消息是:你不需要写一行 TypeScript,也不需要发布自己的插件。VS Code 生态中,有一个成熟、轻量、开源的插件,专为这种“本地代理”场景而生——CodeLLDB的作者开发的CodeGeeX替代品Continue.dev,但它太重。我们选择更精准的:Tabnine的开源分支Tabby的 VS Code 插件,但需微调其配置。不过,最优雅的方案是:直接复用官方Anthropic插件,仅修改其 endpoint 配置。
5.1 为什么首选官方插件 + endpoint 重定向?
- 信任度最高:官方插件源码公开(GitHub:
anthropic/anthropic-vscode),你可随时审查其网络请求逻辑。 - 功能最全:支持
Ctrl+Enter补全、Alt+Enter生成单元测试、Cmd+Shift+P>Claude: Explain Code等全部快捷指令。 - 维护最及时:随 Anthropic API 更新自动适配新字段、新模型。
- 零学习成本:你的团队无需适应新 UI、新快捷键。
唯一要做的,就是告诉这个插件:“别连api.anthropic.com,去连我的127.0.0.1:8000”。
5.2 修改插件配置的两种方式(推荐方式二)
方式一:VS Code 设置中全局覆盖(简单,但影响所有插件)
- 打开 VS Code →
Ctrl+,打开设置。 - 搜索
http.proxy,在HTTP: Proxy设置项中填入:http://127.0.0.1:8000。 - ⚠️ 严重警告:这会强制 VS Code 所有网络请求(包括扩展市场、Git 同步、Live Share)都走你的代理!而你的
claude-proxy只处理/v1/chat/completions,其他请求会 404,导致 VS Code 功能异常。此方式绝对禁止!
方式二:插件专属配置(精准、安全、推荐)
这是anthropic-vscode插件预留的官方机制。它读取一个名为anthropic.apiEndpoint的设置项:
在 VS Code 中,按
Ctrl+Shift+P,输入Preferences: Open Settings (JSON),回车。在打开的
settings.json文件中,添加以下两行(确保逗号分隔正确):"anthropic.apiEndpoint": "http://127.0.0.1:8000/v1", "anthropic.apiKey": "ignored"注意:
apiKey设为"ignored"是关键。因为插件在发送请求时,会读取此值并放入Authorization: Bearer <key>头。但我们希望它不发送任何 key,因为claude-proxy服务自己会从.env文件读取ANTHROPIC_API_KEY并添加头。如果插件也发 key,会导致400 Bad Request(重复认证头)。设为"ignored"后,插件会跳过 key 注入,只发请求体。保存
settings.json,重启 VS Code。
5.3 验证配置是否生效:三步精准诊断
第一步:确认插件已启用
Ctrl+Shift+P→Extensions: Show Enabled Extensions→ 搜索Anthropic,确保状态为Enabled。第二步:触发一次补全,观察网络
打开任意.py文件,输入def hello():,将光标放在下一行,按Ctrl+Enter。此时,你的claude-proxy终端窗口应立即打印出类似日志:INFO: 127.0.0.1:54321 - "POST /v1/chat/completions HTTP/1.1" 200 OK这证明请求已成功抵达代理。
第三步:检查数据库审计日志
用 DB Browser for SQLite 打开cache.db,刷新requests表。你应该能看到一条新记录,model字段为claude-3-haiku-20240307,timestamp是当前时间。点开cache表,找到对应hash,再关联到responses表,content字段里就是 Claude 生成的补全代码。这才是“本地部署”最坚实的证据链:从键盘触发,到屏幕显示,全程数据未离本机,且每一步均可审计。
5.4 进阶技巧:为不同项目设置不同模型与温度
你可能希望在写脚本时用haiku(快、便宜),在重构核心模块时用 `