这个组合我盯了很久。一边是终端里的编程助手交互方式干净利落另一边是代码能力不错、API 价格也友好的模型服务。把两者接起来之后我日常写小工具、查报错、改配置的效率明显上来了而且整个链路完全掌握在自己手里心里踏实。先给这篇文章定个位如果你会点命令行基础想用 Claude Code 的交互体验但又希望底层模型换成 DeepSeek 的 API那这篇就是给你准备的。我会从为什么能这么接开始讲清楚原理再给出每一步可复制的命令和代码最后把常见报错和排查思路都铺开。1. 先搞明白这套组合的来龙去脉1.1 Claude Code 到底是个什么工具Claude Code 本质上是一个跑在终端里的 AI 编程助手底层是用 Node.js 写的命令行工具。你在终端里输入自然语言它会读取当前目录下的文件、执行结果、报错信息等上下文然后组装成请求发给模型服务再把模型返回的内容格式化展示给你。它默认对接的是 Anthropic 官方的 Claude 系列模型这也是很多人叫它“Claude Code”的原因。但工具本身的架构其实留了口子API 地址是可配置的模型字段也是可覆盖的。这个口子就是整篇教程的钥匙。我经常跟朋友打比方Claude Code 像一个点菜系统它会生成订单、传菜、上桌但它不关心后厨是谁。我们要做的就是把“后厨”换成 DeepSeek让“点菜系统”继续运转。1.2 为什么非要把 DeepSeek 接进去很多人第一时间会问Claude Code 本来就配好了为什么还要折腾我自己的理由有三条。第一DeepSeek 的代码专项模型在代码生成、Bug 分析、中文注释这些场景表现确实不错尤其处理中文需求文档和代码注释的匹配比我之前用过的不少模型都自然。第二是成本个人开发者和自由职业者每天要调几十上百次模型API 费用是实打实的支出DeepSeek 的价格体系对高频调用友好得多。第三是想保留工具链的灵活性——模型服务不应该被某一家绑定今天接 DeepSeek明天换其他兼容服务也就是改个配置的事。这条方案的适用人群很明确个人开发者、独立开发者、小团队以及那些希望在本地拥有完整调试链路的技术爱好者。如果你只是偶尔用用那确实不用折腾但如果你想系统性地把 AI 编程成本和质量做平衡这套组合非常值得花半小时跑通。1.3 一个请求是怎么从终端走到 DeepSeek 的这里有个必须理解的技术点也是网上很多教程含糊其辞的地方Claude Code 默认使用的是 Anthropic 的 Messages API 协议而 DeepSeek 提供的是 OpenAI 兼容协议。这两种协议长得像但又不完全一样就像同样是点餐一家餐厅的菜单是全中文的另一家的菜单是中英双语直接拿着 A 餐厅的订单去 B 餐厅下单服务生看不懂。所以中间必须放一个“协议翻译层”我把这层叫本地协议网关。整体请求链路是这样的终端输入 → Claude Code 组装请求 → 发到本地网关 → 网关把协议翻译成 OpenAI 风格 → 发到 DeepSeek API → 网关把响应再翻译回 Anthropic 风格 → Claude Code 渲染显示这个网关不需要跑到公网去就留在你自己电脑上。它只负责翻译和转发模型推理的活全在 DeepSeek 那边完成。把这个逻辑想清楚后面配置环境变量和写网关代码的时候你就不会被各种参数绕晕。2. 安装前的准备工作与方案选型2.1 需要准备的东西清单动手之前我建议把下面这些东西一次性备齐免得中途来回跳。配置其实不复杂但缺一个环节都会卡住。一台能正常联网的电脑Windows 和 macOS 都行Linux 也可以。Node.js 18 或更高版本推荐直接用 20 LTSClaude Code 对这个版本支持最稳。npm一般装 Node.js 的时候会自带命令行输入 npm -v 能查版本就行。一个 DeepSeek 开放平台的账号用来创建 API Key这个 Key 是你的访问凭证相当于后厨的工牌。一个趁手的编辑器终端操作会涉及改文件VSCode 或者任何纯文本编辑器都行。一个简单测试 HTTP 请求的工具curl 命令就可以Windows 用户可以用 PowerShell 里的 curl.exe。大部分项目其实就这些东西。我见过很多人卡在 Node.js 版本上如果你之前装过很老的 Node建议先去官网把版本升上来别用系统自带的旧版否则后面装 Claude Code 会报一堆依赖错误。2.2 两个协议差异的通俗拆解很多人听到“Anthropic 协议”和“OpenAI 协议”就觉得头疼其实差异就那么几个点用一个例子就能讲明白。Anthropic Messages API 的请求结构大致是这样的把角色分成 system、user、assistant消息内容可以是字符串也可以是结构化数组响应体里 content 是一个数组里面每项有 type 和 text 字段。OpenAI Chat Completions 的结构则是把消息放在 messages 数组里每项有 role 和 content响应体里直接是 choices[0].message.content。所以协议翻译层需要做的主要是三件事把请求路径从 /v1/messages 映射到 DeepSeek 的 /chat/completions把消息列表从 Anthropic 格式转成 OpenAI 格式把返回的 choices 内容重新包成 Anthropic 风格的 message 对象。理解了这三件事后面代码哪怕有人给你一个复杂版你也一眼看穿核心。再说直白一点点菜系统只会说“我要一份水煮牛肉少辣”后厨只认“牛肉微辣编号 1024”中间的传菜员负责把两种叫法对应起来。这个传菜员就是我们要写的本地网关。2.3 网关方案怎么选自己写还是用现成的网上的相关脚本和教程很多但质量参差不齐我在选型这件事上吃过亏分享两个判断标准。第一个标准是看协议覆盖度。最原始的网关可能只处理纯文本对话你的日常提问没问题但 Claude Code 很多功能需要流式输出、工具调用、文件写入权限等如果网关不支持流式终端里就会一直转圈到最后才一股脑吐出来别扭得很。第二个标准是看维护活跃度。协议这东西会变网关也要跟着更新如果一个项目半年没动静多半已经不能用了。我的建议是这篇教程先用一个最小可用的自建脚本把链路跑通因为你只有理解了请求怎么走后面再用复杂网关才不容易被坑。跑通之后再根据实际需要选择更完整的方案。这样你的调试路径始终是清晰的先自己搭建再逐步替换而不是一上来就黑盒。3. 保姆级实操从零到跑通3.1 安装 Node.js 和 Claude Code先确认 Node.js 环境。打开终端运行下面两条命令有版本号输出就说明没问题。node -v npm -v如果提示找不到命令说明 Node.js 没装好去官网下载最新的 LTS 版本重新安装。macOS 用户也可以用包管理器安装。接着全局安装 Claude Codenpm install -g anthropic-ai/claude-code安装完成后验证一下版本claude --version这一步如果能输出版本号Claude Code 的安装就完成了。先别急着运行 claude 命令因为默认配置下它会直接向 Anthropic 官方服务发请求我们要先把它指到本地网关。3.2 获取并配置 DeepSeek API Key登录 DeepSeek 开放平台在控制台里找到 API Keys 管理页面创建一个新的 Key。创建完立刻复制保存因为很多平台只在创建的时候显示一次完整 Key。然后把这个 Key 写进环境变量里后面网关脚本会读取它。macOS 和 Linux 用户直接编辑终端配置文件Windows 用户可以在系统环境变量里配置。我先给出 macOS/Linux 的写法export DEEPSEEK_API_KEY你的keyWindows PowerShell 的写法是这样的$env:DEEPSEEK_API_KEY你的key环境变量只是临时方案终端一关就失效了。如果想长期使用可以把这条语句写进 .bashrc 或者 .zshrc 文件里。另外我还习惯在 DeepSeek 控制台里确认一下账户余额和模型配额避免测试中途欠费导致请求失败。3.3 搭建最小协议网关接下来是整篇教程的核心。我写了一个最小的 Node.js 网关脚本它监听本地 8080 端口接收 Anthropic 风格的请求翻译成 OpenAI 风格转发给 DeepSeek再把响应翻译回来。新建一个文件取名 gateway.js把下面的代码完整复制进去。const http require(http); const DEEPSEEK_API_KEY process.env.DEEPSEEK_API_KEY; const DEEPSEEK_BASE https://api.deepseek.com/v1; function toOpenAIMessages(messages) { const result []; for (const msg of messages || []) { let text typeof msg.content string ? msg.content : JSON.stringify(msg.content || ); result.push({ role: msg.role, content: text }); } return result; } http.createServer(async (req, res) { if (req.method ! POST || !req.url.startsWith(/v1/messages)) { res.writeHead(404); res.end(); return; } let body ; for await (const chunk of req) body chunk; const payload JSON.parse(body); const openaiPayload { model: deepseek-chat, messages: toOpenAIMessages(payload.messages || []), max_tokens: payload.max_tokens || 4096, temperature: payload.temperature || 0.7, }; const response await fetch(DEEPSEEK_BASE /chat/completions, { method: POST, headers: { Content-Type: application/json, Authorization: Bearer DEEPSEEK_API_KEY }, body: JSON.stringify(openaiPayload) }); const data await response.json(); if (!response.ok) { res.writeHead(502, { Content-Type: application/json }); res.end(JSON.stringify({ type: error, error: { message: data.error?.message || DeepSeek request failed } })); return; } const content data.choices?.[0]?.message?.content || ; const result { id: msg_ Date.now(), type: message, role: assistant, model: deepseek-chat, content: [{ type: text, text: content }], stop_reason: end_turn, usage: { input_tokens: data.usage?.prompt_tokens || 0, output_tokens: data.usage?.completion_tokens || 0 } }; res.writeHead(200, { Content-Type: application/json }); res.end(JSON.stringify(result)); }).listen(8080, () { console.log(local gateway running at http://127.0.0.1:8080); });这段代码有几个设计细节值得说。fetch 是 Node.js 18 之后原生支持的不需要额外安装依赖所以单文件就能跑。toOpenAIMessages 函数把所有角色的消息都压平成字符串格式这样能处理 Claude Code 传来的一些结构化 content。响应结果里我保留了 usage 字段方便观察每次请求的 token 消耗。运行网关的命令node gateway.js看到 terminal 输出 local gateway running 就说明成功了。先别关这个终端窗口我们还要让 Claude Code 指向它。3.4 配置环境变量让 Claude Code 和网关对接现在需要告诉 Claude Code别往官方服务发请求了改发到本地网关。这一步靠两个环境变量完成。macOS/Linux 终端里在这个已经设置了 DEEPSEEK_API_KEY 的终端窗口执行export ANTHROPIC_BASE_URLhttp://127.0.0.1:8080 export ANTHROPIC_API_KEYsk-ant-any-valueWindows PowerShell 对应写法$env:ANTHROPIC_BASE_URLhttp://127.0.0.1:8080 $env:ANTHROPIC_API_KEYsk-ant-any-valueANTHROPIC_BASE_URL 是 Claude Code 读取 API 地址的入口把值设成本地网关地址所有请求就会被劫持到我们的网关。ANTHROPIC_API_KEY 随便填一个非空字符串因为网关脚本没做鉴权校验但 Claude Code 内部如果不给这个变量一个值它可能自己走默认鉴权逻辑所以必须给一个占位值。这里有个常见误区不要在全局配置文件里加这两个环境变量至少测试阶段不要。因为你以后如果想用回官方服务还得记得把它们删掉。我建议测试阶段就在当前终端窗口临时设置跑通了再决定要不要写死。3.5 第一次跑通验证先手动测一下网关本身能不能正常工作用 curl 模拟一次简单请求curl -X POST http://127.0.0.1:8080/v1/messages \ -H Content-Type: application/json \ -d {model:claude-3-opus-latest,max_tokens:64,messages:[{role:user,content:你好}]}如果网关返回一段带 content 字段的 JSON并且 content 里有实际文本说明网关到 DeepSeek 的链路已经通了。然后启动 Claude Codeclaude进入交互界面后随意问一句“用中文解释一下什么是闭包”。正常情况下你会看到终端里以流式的形式输出回答。注意我们的最小网关没有实现流式转发所以回答可能会一次性跳出来这符合预期。看到回答内容之后再回头看看运行网关那个终端窗口你会发现多了一行请求日志说明 Claude Code 的请求确实经过了本地网关。到这一步整套链路就已经完整跑通了。4. 常见问题与排查技巧4.1 认证报错 401 和 403 怎么处理这是我最常遇到的第一类问题。现象是 Claude Code 启动后请求报 401或者 DeepSeek 那边返回 403。401 通常是网关没有正确把 DeepSeek API Key 带过去检查运行 node gateway.js 的那个终端窗口里DEEPSEEK_API_KEY 环境变量是否真的设置成功了最简单的办法是在网关脚本开头加一行 console.log(key length, DEEPSEEK_API_KEY?.length)看长度是否大于 0。403 则可能是 DeepSeek 那边拒绝了当前请求常见原因是账户余额不足、API Key 权限不够或者请求的模型名不正确。去控制台确认一下你的账户状态同时确认代码里 model 字段写的是 deepseek-chat 而不是随意编的模型名。4.2 请求到了网关但一直 404如果你的 curl 测试直接返回 404而网关终端没有任何报错那大概率是请求路径没匹配上。检查 curl 命令里的路径是不是 /v1/messages注意别写成了 /v1/message 或者漏了 v1。Claude Code 内部可能会对路径加上一些查询参数比如 /v1/messages?betatrue脚本里我用 startsWith 判断就是为兼容这个情况。如果你自己改写了脚本记得把路径判断写宽一点。4.3 响应正常但流式输出消失这个我在前面已经提过。最小网关没有实现流式转发Claude Code 里所有回答都是等待完整响应后一次性显示。这不影响基本使用但如果你经常处理长代码文件会明显觉得节奏变慢。想彻底解决流式问题有两个方向一是换用更完整的开源网关那些项目已经处理好了 SSE 流式转发和工具调用二是自己扩展脚本把 fetch 改为流式读取 DeepSeek 的返回再按 Anthropic 流式事件的格式转发给客户端。我个人的建议是先保持简单。流式只是体验差异不影响功能实现。等你对这套链路足够熟悉了再去升级网关排查起来也更有底气。4.4 工具调用能力缺失怎么办Claude Code 的核心功能不只是问答它还可以在终端里执行命令、读写文件、调用工具这些能力依赖工具调用协议。最小网关把所有请求都简化成了纯文本聊天所以工具调用这一块是缺失的。你可能会发现让它“读一下当前目录的文件”时它只是给你一段文本建议而不是真正去执行。解决办法同样是替换网关方案完整的协议转换项目会识别 Claude Code 请求里的 tools 字段把工具定义映射给 DeepSeek再把模型返回的工具调用指令翻译回 Claude Code 能识别的格式。这块逻辑比较复杂不太适合入门阶段手写。如果你现阶段只需要一个能对话、能改代码片段、能解释报错的终端助理最小网关完全够用。如果你需要自动执行命令的完整 Agent 能力那就要找支持工具的成熟网关这是另外一个话题了。4.5 一些容易忽略的坑Node.js 版本低于 18脚本里 fetch 不可用报 ReferenceError 或者 is not a function解决办法是升级 Node。网关终端和 Claude Code 终端必须同时开着关掉任一个链路就断了。我一般用两个独立的终端窗口并排摆放。环境变量只在当前终端有效如果你用另一个终端重新打开 Claude Code需要再设置一次 ANTHROPIC_BASE_URL 和 ANTHROPIC_API_KEY。DeepSeek API 自身的限流机制也要关注短时间内高频请求可能被限制出错时看看网关返回的 HTTP 状态码和 error.message 字段。5. 这套玩法还能怎么扩展5.1 快速切换 DeepSeek 的不同模型DeepSeek 开放平台有两个常用模型名deepseek-chat 和 deepseek-reasoner。前者适合日常对话和常规代码生成后者偏推理和复杂问题分析。在网关脚本里把 openaiPayload.model 写死成 deepseek-chat 就行也可以做成读取环境变量 DEEPSEEK_MODEL 的方式这样切换模型只需要改终端配置不用每次改代码。我个人用 deepseek-reasoner 的场景是遇到特别隐蔽的 Bug需要模型把上下文从头捋一遍给出推导过程。普通业务代码还是用 deepseek-chat速度快费用也低。5.2 把网关能力做完整如果你用了一段时间决定升级网关重点关注下面几个能力项是否齐全流式输出、工具调用、多轮上下文管理、错误码映射、超时控制。成熟的网关项目会把 DeepSeek 的 error 信息映射成 Anthropic 风格的错误结构Claude Code 才能正确显示报错不会满屏原始 JSON。升级网关不会改你现有的环境变量配置因为路径还是本地 8080 端口只是背后的服务更强了。这也是当时设计这套架构的额外好处客户端不需要改动太多就能替换后端。5.3 从个人使用走向团队共享网关不一定要只绑在 127.0.0.1 上。小团队内部你可以把网关部署在一台内部服务器上或者用 Docker 容器运行给团队成员统一提供一个内部地址。成员的环境变量只需要设置 ANTHROPIC_BASE_URL 指向团队网关然后用自己的 DeepSeek API Key 或者团队共享的 Key就能获得一致的体验。当然团队化之后要考虑的问题也会变多比如 Key 管理、并发控制、请求日志、成本统计。你可以给网关加一层简单的鉴权头Claude Code 发出的请求里携带 x-api-key网关检查这个值是否在允许名单里低成本实现访问控制。整个扩展路径下来你会发现最开始那个小小的本地脚本其实是一个完整的内部 AI 网关雏形。从个人跑到团队用只是加一些工程化能力的问题。最后再分享一个我个人的习惯每次换新模型服务或者改完网关我都会用一个体积很小的测试项目跑一遍完整流程从对话、报错分析到小函数生成五分钟验证完再切入正式项目避免在真正干活的时候才发现链路有问题。这个习惯帮我避过了很多次尴尬希望你也能用上。