第一部分:一键换源(提速关键,或者自行找安装快的源安装)
安装的软件包
| | |
|---|
| apt install nodejs | |
| npm install -g @anthropic-ai/claude-code | |
没有安装任何 Python 第三方包(代理只用标准库)。
手动创建的文件(共 3 个)
| | |
|---|
| 代理脚本 | ~/deepseek-proxy.py | |
| Claude Code 配置 | ~/.claude/settings.json | 告诉 Claude Code 走本地代理(3 行 JSON) |
| 一键启动脚本 | ~/claude-deepseek.sh | |
修改的配置文件(共 3 个)
| | |
|---|
/etc/apt/sources.list | | |
~/.bashrc | | |
| npm config set registry | |
Kali 默认使用国外软件源,下载速度可能只有几十 KB/s。安装前先切换到国内镜像源,这是整个过程中最关键的提速步骤。
步骤 1:APT 切换清华大学镜像源[🕐 约 1 分钟]
备份原有源,替换为清华镜像:
sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak
编辑源文件:
sudo nano /etc/apt/sources.list
清空原有内容,替换为以下内容:
deb https://mirrors.tuna.tsinghua.edu.cn/kali kali-rolling main contrib non-free non-free-firmware deb-src https://mirrors.tuna.tsinghua.edu.cn/kali kali-rolling main contrib non-free non-free-firmware

更新软件包索引,验证速度:
sudo apt update
# 正常速度:10~30 MB/s(清华教育网内可达 100 MB/s)
# 如果还是慢,换其他镜像:
# 中科大:mirrors.ustc.edu.cn
# 阿里云:mirrors.aliyun.com
# 网易:mirrors.163.com
步骤 2:npm 切换淘宝镜像源[🕐 约 10 秒]
npm 默认从 npmjs.org 拉包,国内极慢。配置为淘宝镜像一劳永逸:
npm config set registry https://registry.npmmirror.com
npm config get registry
https://registry.npmmirror.com
⚡ 配置后 npm install 速度从几十 KB/s → 10+ MB/s
步骤 3:pip 配置清华镜像源(备用)[🕐 约 10 秒]
虽然本方案不需要安装 Python 第三方包,但建议顺手配一下,日后用得上:
mkdir -p ~/.pip
cat > ~/.pip/pip.conf << EOF
[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple
[install]
trusted-host = pypi.tuna.tsinghua.edu.cn
EOF
第二部分:安装 Node.js 与 Claude Code
步骤 4:安装 Node.js(npm 包管理器)[🕐 约 1~2 分钟]
Kali 通常已预配 NodeSource 源。如果未配置,用下面命令添加(走官方源速度尚可)。安装时只装 nodejs,不要同时装 npm(会冲突)。
⚠ 不要执行 sudo apt install nodejs npm —— 会报依赖冲突!只装 nodejs 一个包即可。
sudo apt install -y nodejs
验证:
node --version
v22.23.2
npm --version
10.9.8
如果 apt 里没有 NodeSource 源,手动添加:
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install -y nodejs
步骤 5:配置 npm 全局安装到用户目录[🕐 约 20 秒]
让 npm install -g 安装到自有目录,以后不需要 sudo:
mkdir -p ~/.npm-global
npm config set prefix ~/.npm-global
echo 'export PATH=~/.npm-global/bin:$PATH' >> ~/.bashrc
source ~/.bashrc
npm config get prefix
/home/daiyq/.npm-global
步骤 6:安装 Claude Code[🕐 约 1~3 分钟(淘宝源)]
淘宝镜像加速,通常 1~2 分钟完成:
npm install -g @anthropic-ai/claude-code
# 预期:added XXX packages in 1~2m
claude --version
2.1.220 (Claude Code)
⚡ 如果之前没配淘宝源,这一步可能耗时 10~30 分钟!步骤 2 的镜像配置至关重要。
第三部分:部署协议转换代理
这是整个方案的核心——一个约 170 行的 Python 脚本,零依赖,负责在 Anthropic 和 OpenAI 两种 API 格式之间做双向翻译。
步骤 7:获取 DeepSeek API Key[🕐 约 2 分钟]
访问 https://platform.deepseek.com/api_keys,注册并创建 API Key。格式为 sk-xxxxxxxx。新用户通常赠送免费额度。
⚠ API Key 是敏感凭据,不要分享给任何人,也不要提交到公开仓库。
步骤 8:创建代理脚本[🕐 约 3 分钟]
nano ~/deepseek-proxy.py
粘贴以下完整代码(注意修改第 12 行 API Key):
#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ DeepSeek 代理 — Anthropic Messages API ↔ OpenAI Chat Completions 纯 Python 标准库 · 零依赖 · 不破坏 Kali 现有工具 监听 4000 端口,Claude Code 所有 API 请求通过此代理转发到 DeepSeek """ import json from http.server import HTTPServer, BaseHTTPRequestHandler from urllib.request import Request, urlopen from urllib.error import HTTPError # ========================================== DEEPSEEK_KEY = "sk-你的api-key"# ← 改这里! DEEPSEEK_URL = "https://api.deepseek.com/v1/chat/completions" PORT = 4000 # ========================================== class Proxy(BaseHTTPRequestHandler): # ── HEAD: Claude Code 启动时先发 HEAD 探测连通性 ── def do_HEAD(self): ok = self.path in ("/", "/api/hello", "/v1/messages") self._send(ok and 200 or 404, None) # ── GET: 健康检查 / 模型列表 ── def do_GET(self): if self.path in ("/", "/api/hello"): self._send(200, {"status": "ok", "target": "DeepSeek"}) elif self.path.startswith("/v1/models"): self._send(200, {"data": [ {"id": "claude-sonnet-4-20250514", "object": "model"}, {"id": "claude-3-5-sonnet-20241022", "object": "model"}, ]}) else: self._send(404, {"error": "not found"}) # ── POST: 核心翻译逻辑 ── def do_POST(self): # 1. 读取 Anthropic 请求 n = int(self.headers.get("Content-Length", 0)) body = json.loads(self.rfile.read(n)) if n else {} messages = [] for m in body.get("messages", []): role = m.get("role", "user") content = m.get("content", "") # system 直接透传 if role == "system": text = self._text(content) if text: messages.append({"role": "system", "content": text}) continue # assistant: text + tool_use → tool_calls if role == "assistant": texts, tcs = [], [] if isinstance(content, str): texts.append(content) elif isinstance(content, list): for c in content: if c.get("type") == "text": texts.append(c.get("text", "")) elif c.get("type") == "tool_use": tcs.append({ "id": c.get("id", ""), "type": "function", "function": { "name": c.get("name", ""), "arguments": json.dumps( c.get("input", {}), ensure_ascii=False) } }) msg = {"role": "assistant", "content": "\n".join(texts) or None} if tcs: msg["tool_calls"] = tcs messages.append(msg) continue # user: text + tool_result → tool 消息 if role == "user": if isinstance(content, str): messages.append({"role": "user", "content": content}) elif isinstance(content, list): for c in content: if c.get("type") == "text": messages.append({ "role": "user", "content": c.get("text", "") }) elif c.get("type") == "tool_result": rc = c.get("content", "") if isinstance(rc, list): rc = "\n".join( x.get("text", "") for x in rc if x.get("type") == "text" ) messages.append({ "role": "tool", "tool_call_id": c.get("tool_use_id", ""), "content": str(rc), }) continue # 2. 构建 OpenAI 请求 req_body = { "model": "deepseek-chat", "messages": messages, "max_tokens": body.get("max_tokens", 4096), "stream": False, } # 工具定义翻译 if "tools" in body: req_body["tools"] = [{ "type": "function", "function": { "name": t.get("name", ""), "description": t.get("description", ""), "parameters": t.get("input_schema", {}), } } for t in body["tools"]] # 3. 发到 DeepSeek try: req = Request( DEEPSEEK_URL, data=json.dumps(req_body, ensure_ascii=False).encode(), headers={ "Authorization": f"Bearer {DEEPSEEK_KEY}", "Content-Type": "application/json", }) resp = urlopen(req, timeout=180) data = json.loads(resp.read()) choice = data["choices"][0]["message"] # 4. OpenAI 响应 → Anthropic 格式 content_list = [] if choice.get("content"): content_list.append({ "type": "text", "text": choice["content"] }) if "tool_calls" in choice: for tc in choice["tool_calls"]: args = tc["function"]["arguments"] if isinstance(args, str): try: args = json.loads(args) except: pass content_list.append({ "type": "tool_use", "id": tc.get("id", ""), "name": tc["function"]["name"], "input": args, }) stop_map = {"stop": "end_turn", "length": "max_tokens", "tool_calls": "tool_use"} self._send(200, { "id": data.get("id", "msg_001"), "model": body.get("model", "claude-sonnet-4-20250514"), "type": "message", "role": "assistant", "stop_reason": stop_map.get( choice.get("finish_reason", "stop"), "end_turn"), "content": content_list, "usage": { "input_tokens": data.get("usage", {}).get("prompt_tokens", 0), "output_tokens": data.get("usage", {}).get("completion_tokens", 0), } }) except HTTPError as e: self._send(e.code, {"error": e.read().decode()}) except Exception as e: self._send(500, {"error": str(e)}) # ── 辅助 ── def _text(self, content): if isinstance(content, str): return content if isinstance(content, list): return "\n".join( c.get("text", "") for c in content if c.get("type") == "text") return str(content) def _send(self, code, data): self.send_response(code) self.send_header("Content-Type", "application/json") self.end_headers() if data is not None: self.wfile.write( json.dumps(data, ensure_ascii=False).encode()) def log_message(self, fmt, *args): print(f"[{self.log_date_time_string()}] {args[0]}") if __name__ == "__main__": print(f"[*] 代理已启动 → http://localhost:{PORT}") print(f"转发目标: {DEEPSEEK_URL}") HTTPServer(("0.0.0.0", PORT), Proxy).serve_forever()
chmod 600 ~/deepseek-proxy.py
步骤 9:启动代理并验证[🕐 约 30 秒]
在第一个终端窗口启动代理(保持运行,不要关闭):
python3 ~/deepseek-proxy.py
[*] 代理已启动 → http://localhost:4000
转发目标:https://api.deepseek.com/v1/chat/completions
另开第二个终端,测试代理连通性:
curl -s http://localhost:4000/api/hello
{"status": "ok", "target": "DeepSeek"}
⚡ 至此,代理层跑通。如果 curl 无响应,检查代理终端是否有报错。
第四部分:配置 Claude Code 连接代理
步骤 10:写入 Claude Code 配置[🕐 约 1 分钟]
告诉 Claude Code 把请求发给本地代理而非 api.anthropic.com:
mkdir -p ~/.claude
cat > ~/.claude/settings.json << 'EOF'
{
"env":{
"ANTHROPIC_BASE_URL":"http://localhost:4000",
"ANTHROPIC_API_KEY":"any-key"
}
}
EOF
验证 JSON 格式正确:
python3 -c "import json; json.load(open('$HOME/.claude/settings.json')); print('OK')"
OK
第五部分:启动与验证
步骤 11:启动 Claude Code[🕐 约 30 秒]
确保代理在另一个终端运行中,然后在当前终端执行:
export ANTHROPIC_BASE_URL="http://localhost:4000"
export ANTHROPIC_API_KEY="any-key"
claude
首次启动会依次出现三屏确认界面:
第 1 屏 — 主题选择
用方向键选 "2. Dark mode",回车。
❯ 2. Dark mode ✔
第 2 屏 — API Key 安全提示
选 "2. No (recommended)",不直连 Anthropic 官方,而是走代理。
❯ 2. No (recommended)
第 3 屏 — 工作区信任
选 "1. Yes, I trust this folder",回车。
❯ 1. Yes, I trust this folder
三屏确认后进入对话界面,出现空提示符 ❯ 即成功。
步骤 12:纯文本对话验证[🕐 约 10 秒]
在 ❯ 后输入:
你好,请用中文回复,帮我确认当前连接是否正常。
正常回复 + 代理终端有 POST 日志 → 基础链路跑通。
步骤 13:工具调用验证(关键)[🕐 约 20~30 秒]
测试 Claude Code 的核心能力——自动执行 Bash、读取文件、发出 curl 请求等:
检查一下当前的 API 配置,确认实际使用的是哪个模型。
Claude Code 会自动执行环境变量查询 → 读取 settings.json → curl 验证代理 → 搜索日志等操作,并在 15~30 秒后回复确认实际模型是 DeepSeek。所有工具调用成功即表明代理的工具翻译也完美工作。
第六部分:一键启动 & 退出
步骤 14:创建一键启动脚本[🕐 约 1 分钟]
cat > ~/claude-deepseek.sh << 'EOF'
#!/bin/bash
sudo fuser -k 4000/tcp 2>/dev/null# 停旧代理
python3 ~/deepseek-proxy.py &# 启新代理
sleep 2# 等代理就绪
export ANTHROPIC_BASE_URL="http://localhost:4000"
export ANTHROPIC_API_KEY="any-key"
claude
EOF
chmod +x ~/claude-deepseek.sh
以后每次使用只需要:
~/claude-deepseek.sh
⚡ 一口气完成:停旧代理 → 启动新代理 → 启动 Claude Code
步骤 15:退出方式[🕐 约 5 秒]
结束使用后两步退出:
# 在 Claude Code 内按 Ctrl+D(或输入 /exit 回车)
退出 Claude Code 后,关掉代理:
sudo fuser -k 4000/tcp
附录 :技术架构
B.1 数据流
B.2 协议转换核心
代理需要处理三种 Anhtropic ↔ OpenAI 的消息格式差异:
① 消息结构差异
Anthropic 使用 content[] 数组封装所有内容(文本、工具调用、工具结果都在里面),OpenAI 则用独立的 tool_calls 字段和 tool role。
Anthropic:OpenAI: {{ "role": "assistant","role": "assistant", "content": ["content": "结果是...", {"type": "text", "text": "..."},"tool_calls": [{ {"type": "tool_use","id": "tool_001", "name": "Bash","function": { "input": {"cmd": "ls"}}"name": "Bash", ]"arguments": "{\"cmd\":\"ls\"}" }}] }
② 工具结果差异
Anthropic 把工具执行结果放在 user 消息的 content[] 里(type=tool_result),OpenAI 要求用独立的 role=tool 消息,且 tool_call_id 必须和上一条 tool_calls 的 id 严格对应。
Anthropic:OpenAI: {{ "role": "user","role": "tool", "content": [{"tool_call_id": "tool_001", "type": "tool_result","content": "file1.txt\nfile2.txt" "tool_use_id": "tool_001",} "content": "file1.txt..." }] }
③ 停止原因差异
Anthropic stop_reason←→OpenAI finish_reason ───────────────────────────────────────────── "end_turn"←→"stop" "max_tokens"←→"length" "tool_use"←→"tool_calls"
附录 C:常见问题排查
Q1: npm install 报 EACCES
权限不足,npm 尝试写 /usr/lib/node_modules/。回到步骤 5 配置 npm 全局路径到 ~/.npm-global/。
Q2: 启动 Claude Code 提示 Unable to connect
代理未运行或环境变量未生效。检查:① ps aux|grep deepseek-proxy;② ss -tlnp|grep 4000;③ cat ~/.claude/settings.json;④ curl localhost:4000/api/hello。
Q3: API Error 400 — tool_calls must be followed by tool messages
代理版本过旧(v1),工具调用翻译不完整。回到步骤 8 用 v2 完整代码替换 ~/deepseek-proxy.py。
Q4: 代理启动报 Address already in use
端口被旧进程占用。sudo fuser -k 4000/tcp 杀掉后重试。
Q5: 下载速度仍然很慢
检查:npm config get registry 是否显示淘宝源;cat /etc/apt/sources.list 是否用的国内镜像。ping mirrors.tuna.tsinghua.edu.cn 确认延迟 <100ms。如不行换阿里云源。
Q6: 怎么确认跑的真是 DeepSeek 不是 Anthropic?
输入 "检查 API 配置,确认实际模型",Claude Code 会自动查代理返回的 target 字段确认。
Q7: DeepSeek API 余额/Key 怎么查?
访问 https://platform.deepseek.com/usage 查看用量和余额。
—— 全文完 ——