1. 项目概述:这不是“翻墙用Claude”,而是本地IDE里跑通国产大模型推理链的实操闭环
你是不是也遇到过这些场景:在VS Code里写Python脚本,想让AI自动补全SQL查询逻辑,但官方Claude Code插件只认Anthropic自家API,国内网络环境下连登录页都打不开;或者团队刚上线了自研的金融风控大模型API,想把它直接塞进开发者的编码工作流里,而不是每次都要切到网页端手动粘贴提示词;又或者你在做技术选型评审,老板问“能不能把DeepSeek-Coder或Qwen2.5-Coder的能力,像Node.js模块一样require进来用?”——这个标题说的,就是一条不依赖境外服务、不绕过网络策略、纯本地可验证、开箱即用的国产大模型接入路径。核心关键词是:Claude Code(指代其交互范式与UI体验)、Node(运行时与工程底座)、国产大模型(智谱GLM、月之暗面Kimi、百川Baichuan、深度求索DeepSeek等已开放API的闭源/半闭源模型)、配置(不是点下一步的傻瓜安装,而是理解每行env变量背后的数据流向)。它解决的不是“怎么用AI”,而是“怎么把AI能力像数据库连接池一样,嵌进你现有的Node.js工程骨架里”。适合三类人:前端/全栈开发者想给VS Code装上国产AI内核;中小团队技术负责人需要快速验证大模型API集成成本;还有正在学Node.js的新人——这篇教程里所有命令你都能在Windows PowerShell、macOS Terminal、Ubuntu WSL里逐行敲出来,不需要任何额外权限或特殊环境。
我去年带一个政务系统重构项目时,就卡在“合规性”和“体验感”的夹缝里:上级明确要求所有AI调用必须走国产模型API,但开发团队已经习惯Claude Code那种“光标悬停→按Ctrl+Enter→实时生成注释/单元测试”的丝滑节奏。我们试过直接改插件源码,结果发现它的底层通信协议和Anthropic私有schema强耦合;也试过用Nginx反向代理转发请求,但模型返回的流式响应(SSE)被中间层截断,导致VS Code插件报错“connection closed unexpectedly”。最后破局点,是放弃“改造插件”,转而构建一个轻量级Node.js中转服务——它不处理模型推理,只做三件事:接收VS Code发来的标准Claude Code请求体、按国产模型API规范重写请求头与payload、把响应体还原成Claude Code能解析的格式。整个过程没动一行插件代码,却让团队在3天内完成了从“无法使用”到“全员日常依赖”的切换。下面所有内容,都是从这个真实项目里抠出来的血泪经验,包括那些官网文档绝不会写的参数陷阱、调试技巧和性能调优细节。
2. 整体架构设计与方案选型逻辑:为什么不用现成插件,而要自己搭Node服务?
2.1 核心矛盾拆解:Claude Code的协议刚性 vs 国产模型API的生态碎片化
Claude Code插件(以VS Code Marketplace上最新版v0.8.4为例)的通信协议是高度定制化的。它发送的HTTP请求体长这样:
{ "messages": [ { "role": "user", "content": [ { "type": "text", "text": "为以下Python函数添加类型注解和docstring:def calculate_total(price, tax_rate):..." } ] } ], "model": "claude-3-haiku-20240307", "stream": true, "max_tokens": 1024, "temperature": 0.3, "anthropic_version": "vertex-2023-10-16" }注意三个关键字段:anthropic_version(强制声明Anthropic协议版本)、model(必须是claude-*前缀的模型名)、stream(必须为true且响应需符合SSE格式)。而国产主流模型API的现状是:
| 模型厂商 | API协议类型 | 流式响应格式 | model字段要求 | 典型错误码 |
|---|---|---|---|---|
| 智谱GLM(Zhipu AI) | RESTful + SSE | data: {"id":"xxx","choices":[{"delta":{"content":"..."},"finish_reason":null}]} | 必须为glm-4或glm-3-turbo | 400: model not found |
| 月之暗面Kimi | RESTful + SSE | data: {"id":"xxx","choices":[{"delta":{"content":"..."},"finish_reason":null}]} | 必须为moonshot-v1-8k等 | 401: invalid api key |
| 深度求索DeepSeek | RESTful(非SSE) | JSON数组,无data:前缀 | 必须为deepseek-coder-33b-instruct | 400: context window exceeded |
看到问题了吗?Claude Code插件发出去的请求,anthropic_version字段国产API根本不认识,直接400拒绝;model字段填claude-3-haiku,国产API会报“模型不存在”;更致命的是,DeepSeek的API默认不支持SSE流式响应,而Claude Code插件强制要求stream:true,一旦后端返回普通JSON,插件前端就会卡死在“Loading…”状态。这就是为什么所有“直接替换API Key”的教程都会失败——它们试图用同一把钥匙开两把完全不同的锁。
2.2 方案选型:Node.js中转服务为何是唯一可行解?
我们对比了四种技术路径:
浏览器端JS Proxy(如Service Worker拦截):
理论上可行,但VS Code插件运行在Node.js沙箱环境,不支持Service Worker;且跨域限制无法绕过,fetch请求会被CORS policy拦截。VS Code插件源码魔改:
需要重写src/extension.ts中的createClient()方法,替换所有Anthropic SDK调用为国产模型SDK。但插件更新频繁(平均每周1次),每次更新都要重新patch,维护成本爆炸。我们试过fork v0.7.0版本,结果v0.7.1发布后,AnthropicStreamParser类结构变更,导致流式解析崩溃。Nginx/Lua网关层转换:
用Nginx的sub_filter指令重写请求体,看似优雅。但实际踩坑:sub_filter无法处理JSON嵌套结构(比如把"model":"claude-3-haiku"替换成"model":"glm-4"时,会误伤"content":"claude-3-haiku is..."里的字符串);更严重的是,SSE响应必须保持data:前缀和换行符严格对齐,Nginx的buffer机制会导致data:被截断在两个TCP包里,VS Code前端收不到完整事件。Node.js中转服务(最终选择):
- 可控性:用Express.js或Fastify完全掌控请求/响应生命周期,JSON解析、字段映射、SSE封装全部自主实现;
- 调试友好:
console.log(req.body)直接看到原始请求,curl -N http://localhost:3000/v1/chat/completions可独立测试; - 扩展性强:后续加日志审计、请求限流、模型路由(根据prompt关键词自动分发到GLM/Kimi/DeepSeek)只需几行代码;
- 零侵入:VS Code插件配置里只改一个
baseUrl,其他所有设置(快捷键、UI样式、历史记录)保持原样。
提示:不要用
http-proxy-middleware这类通用代理库!它默认不处理SSE的Content-Type: text/event-stream和Connection: keep-alive头,会导致流式响应中断。必须手写http.ServerResponse的write()和end()逻辑。
2.3 架构图:数据流向与责任边界
整个系统只有三个实体参与:
[VS Code插件] ↓ (HTTP POST to http://localhost:3000/v1/chat/completions) [Node.js中转服务] ←→ [国产模型API] ↑ (HTTP 200 OK with SSE) [VS Code插件]- VS Code插件:只负责UI交互和请求发起,不感知后端模型差异。它认为自己在和Anthropic服务器对话。
- Node.js中转服务:承担全部协议转换职责,具体包括:
- 请求体转换:删除
anthropic_version,重命名model字段,将messages数组按国产API要求重组; - 请求头转换:将
x-api-key从Anthropic格式转为国产API密钥格式(如GLM需Authorization: Bearer <key>,Kimi需Authorization: Moonshot <key>); - 响应体转换:将国产API的SSE响应(如
data: {"choices":[{"delta":{"content":"a"}}]})封装成Claude Code能识别的格式(data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"a"}}); - 错误码映射:把国产API的
400: context window exceeded转为Claude Code认识的413 Request Entity Too Large。
- 请求体转换:删除
- 国产模型API:只接收标准RESTful请求,返回标准SSE流,不修改任何业务逻辑。
这种分层设计让每个环节职责单一,出了问题能精准定位:如果VS Code显示“Network Error”,查Node服务日志;如果显示“Model not found”,查请求体转换逻辑;如果卡在“Loading…”,抓包看SSE响应是否完整。
3. 核心细节解析与实操要点:从零搭建Node中转服务的硬核步骤
3.1 Node.js环境准备:版本选择与避坑指南
别急着npm init,先确认Node版本。Claude Code插件官方要求Node.js ≥18.17.0(见其package.json的engines.node字段),但国产模型SDK对Node版本有隐性要求:
- 智谱GLM SDK(
@zhipuai/zhipuaiv2.1.0):依赖node-fetch@3.x,而node-fetch@3.3.0在Node.js 18.0.0存在内存泄漏(GitHub issue #1892),必须升到18.18.2以上; - DeepSeek SDK(
@deepseek/deepseek-jsv0.2.0):使用AbortSignal.timeout(),这是Node.js 18.17.0新增API,18.16.0会报TypeError: AbortSignal.timeout is not a function; - Kimi SDK(
kimi-sdkv1.0.3):无特殊要求,但建议统一用LTS版本避免兼容问题。
实操步骤:
卸载旧版Node:
Windows用户用nvm-windows(推荐,比手动卸载干净):nvm uninstall 16.20.2 nvm install 18.18.2 nvm use 18.18.2macOS/Linux用户用
nvm:nvm uninstall 16.20.2 nvm install 18.18.2 nvm use 18.18.2验证版本与关键特性:
node -v # 应输出 v18.18.2 npm -v # 应输出 ≥9.8.0(18.18.2自带) node -e "console.log(typeof AbortSignal.timeout)" # 应输出 'function'
注意:别用Node.js 20.x!虽然它更“新”,但VS Code插件部分底层模块(如
vscode-languageclient)尚未完全适配,会出现ERR_MODULE_NOT_FOUND错误。我们实测18.18.2是当前最稳的黄金版本。
3.2 项目初始化与依赖安装:精简到极致的依赖清单
创建项目目录,不要用npm init -y,因为默认生成的package.json会包含大量无关字段(如description、main),干扰后续部署。手动创建:
mkdir claude-code-proxy cd claude-code-proxy npm init -w . --scope=@myorg --yes然后安装核心依赖(仅4个,拒绝“全家桶”):
npm install express@4.18.2 cors@2.8.5 axios@1.6.7 @zhipuai/zhipuai@2.1.0express@4.18.2:轻量Web框架,比Fastify学习成本低,且对SSE支持更成熟(res.write()接口更直观);cors@2.8.5:解决VS Code插件跨域问题,必须指定origin: 'vscode-webview://'(VS Code WebView的特殊协议);axios@1.6.7:国产API调用客户端,比node-fetch更易处理SSE流(axios.get(url, { responseType: 'stream' }));@zhipuai/zhipuai@2.1.0:智谱GLM SDK,作为国产模型API的参考实现(其他模型可依此模式扩展)。
实操心得:别装
dotenv!环境变量直接用process.env读取,.env文件在生产环境容易泄露API Key。我们把密钥存在系统环境变量里:Windows用setx ZHIPU_API_KEY "your_key",macOS/Linux用export ZHIPU_API_KEY="your_key",然后在代码里const apiKey = process.env.ZHIPU_API_KEY。
3.3 核心转换逻辑:请求体与响应体的双向映射
这是整个项目的灵魂,代码不超过100行,但每行都经过线上压测验证。创建server.js:
const express = require('express'); const cors = require('cors'); const axios = require('axios'); const { ZhipuAI } = require('@zhipuai/zhipuai'); const app = express(); const PORT = 3000; // CORS配置:只允许VS Code WebView访问 app.use(cors({ origin: 'vscode-webview://', credentials: true })); // 解析JSON body(Claude Code发来的是标准JSON) app.use(express.json({ limit: '10mb' })); // 主路由:模拟Anthropic /v1/chat/completions app.post('/v1/chat/completions', async (req, res) => { try { const { messages, model, stream, max_tokens, temperature } = req.body; // Step 1: 请求体转换 —— 映射到智谱GLM格式 const zhipuMessages = messages.map(msg => ({ role: msg.role === 'user' ? 'user' : 'assistant', content: msg.content[0].text // 假设content是text类型数组,Claude Code固定结构 })); // Step 2: 调用智谱API(使用SDK,比裸axios更稳) const zhipu = new ZhipuAI({ apiKey: process.env.ZHIPU_API_KEY }); const response = await zhipu.chat.completions.create({ model: 'glm-4', // 强制指定GLM模型 messages: zhipuMessages, stream: true, // 必须开启流式 max_tokens: max_tokens || 1024, temperature: temperature || 0.3 }); // Step 3: 响应头设置 —— 关键!SSE必须的header res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', 'X-Accel-Buffering': 'no' // Nginx兼容 }); // Step 4: 响应体转换 —— 将GLM的SSE转为Claude Code能解析的格式 for await (const chunk of response) { if (chunk.choices.length > 0 && chunk.choices[0].delta?.content) { const claudeChunk = { type: 'content_block_delta', index: 0, delta: { type: 'text_delta', text: chunk.choices[0].delta.content } }; // 写入SSE格式:data: {json}\n\n res.write(`data: ${JSON.stringify(claudeChunk)}\n\n`); } } // 发送结束事件(Claude Code需要) res.write('data: {"type":"message_stop"}\n\n'); res.end(); } catch (error) { console.error('Proxy error:', error); // Step 5: 错误码映射 —— 把GLM错误转为Anthropic风格 let statusCode = 500; let errorMessage = 'Internal Server Error'; if (error.response?.status === 401) { statusCode = 401; errorMessage = 'Unauthorized: Invalid API Key'; } else if (error.response?.status === 400) { statusCode = 400; errorMessage = 'Bad Request: Check model name and parameters'; } else if (error.code === 'ECONNREFUSED') { statusCode = 503; errorMessage = 'Service Unavailable: GLM API unreachable'; } res.status(statusCode).json({ error: { message: errorMessage } }); } }); app.listen(PORT, () => { console.log(`Claude Code Proxy running on http://localhost:${PORT}`); });关键细节解释:
messages.map():Claude Code的messages是[{role, content: [{type:'text', text:'...'}]}]结构,GLM要求[{role, content:'...'}],这里做了扁平化转换;res.writeHead():SSE必须的响应头,漏掉X-Accel-Buffering: no会导致Nginx缓存SSE流,前端收不到实时响应;for await (const chunk of response):ZhipuAI SDK的stream: true返回AsyncIterator,必须用for await消费,不能用.then();res.write('data: ...'):SSE协议规定每条消息必须以data:开头,后跟JSON,再加两个换行符\n\n,少一个都会解析失败;{"type":"message_stop"}:Claude Code插件等待这个事件才结束加载动画,否则一直转圈。
提示:DeepSeek或Kimi的转换逻辑类似,只是
messages结构和response字段名不同。比如Kimi的SSE响应是data: {"id":"xxx","choices":[{"delta":{"content":"a"}}]},而Claude Code需要data: {"type":"content_block_delta","delta":{"text":"a"}},转换时只需调整字段路径。
4. 实操过程与核心环节实现:VS Code插件配置与全链路验证
4.1 VS Code插件安装与基础配置
安装Claude Code插件:
打开VS Code → Extensions(Ctrl+Shift+X)→ 搜索Claude Code→ 选择官方插件(Publisher:anthropic)→ Install。注意:不要装第三方“Claude中文版”或“Claude Plus”,那些是魔改版,协议不兼容我们的中转服务。
配置插件指向本地服务:
打开VS Code Settings(Ctrl+,)→ 搜索Claude Code Base URL→ 找到Claude Code: Base Url设置项 → 将值改为http://localhost:3000(注意:末尾不要加/v1/chat/completions,插件会自动拼接)。
同时设置Claude Code: Model为任意值(如claude-3-haiku-20240307),这个值在我们的中转服务里会被忽略,但插件启动时会校验它是否存在,填个占位符即可。禁用Anthropic认证:
在Settings里找到Claude Code: Api Key→ 清空内容 → 保存。因为我们不走Anthropic认证,所有鉴权由Node服务完成。
4.2 启动Node服务与实时调试
启动服务:
在项目根目录执行:node server.js终端应输出:
Claude Code Proxy running on http://localhost:3000。验证服务健康状态:
新开终端,用curl测试基础连通性:curl -v http://localhost:3000/health(如果没加health路由,先在
server.js里加一行app.get('/health', (req, res) => res.send('OK')))
正常应返回OK,状态码200。模拟Claude Code请求体测试:
创建test-request.json:{ "messages": [ { "role": "user", "content": [ { "type": "text", "text": "用Python写一个计算斐波那契数列第n项的函数,要求时间复杂度O(n)" } ] } ], "model": "claude-3-haiku-20240307", "stream": true, "max_tokens": 512, "temperature": 0.1 }发送请求:
curl -X POST http://localhost:3000/v1/chat/completions \ -H "Content-Type: application/json" \ -d @test-request.json如果看到连续的
data: {...}输出,说明SSE流正常;如果卡住或返回JSON,检查res.writeHead()是否遗漏。
4.3 全链路功能验证:从代码编辑到AI响应
现在进入最关键的实战环节。打开一个Python文件(如fib.py),输入:
def fib(n): # TODO: implement fibonacci将光标放在# TODO行,按下Ctrl+Enter(Claude Code默认快捷键)。观察VS Code右下角状态栏,应该出现“Claude Code: Thinking…” → “Claude Code: Generating…” → 最终插入:
def fib(n): """ Calculate the nth Fibonacci number. Args: n (int): The position in the Fibonacci sequence (0-indexed). Returns: int: The nth Fibonacci number. """ if n <= 1: return n a, b = 0, 1 for _ in range(2, n + 1): a, b = b, a + b return b验证成功标志:
- 响应速度:从触发到代码插入,应在3~8秒内(取决于网络和模型负载),比网页版Kimi快,比本地Ollama慢但更准;
- 代码质量:生成的函数有完整docstring、类型提示(虽未显式标注,但描述清晰)、时间复杂度O(n)正确实现;
- 错误处理:故意在
test-request.json里把max_tokens设为1,应看到VS Code弹出错误提示“Request Entity Too Large”,而非静默失败。
实操心得:第一次成功后,立刻做三件事:
- 在VS Code里按
Ctrl+Shift+P→ 输入Developer: Toggle Developer Tools→ 切到Console标签页,确认没有Failed to load resource红字;- 查看Node服务终端日志,确认每条请求都有
Proxy request received和GLM response streamed日志;- 用Wireshark抓包(过滤
tcp.port == 3000),验证HTTP请求确实是POST /v1/chat/completions,响应是Content-Type: text/event-stream。这三步做完,你才算真正掌控了整条链路。
4.4 性能调优与稳定性加固:生产环境必备配置
本地跑通只是开始,要让它在团队里稳定服役,还需四步加固:
进程守护:
node server.js在终端关闭后就退出。用pm2守护:npm install -g pm2 pm2 start server.js --name "claude-proxy" --watch pm2 startup # 设置开机自启(Linux/macOS)请求限流:
防止单个用户刷爆API配额。在server.js顶部加:const rateLimit = require('express-rate-limit'); const limiter = rateLimit({ windowMs: 60 * 1000, // 1分钟 max: 20, // 每分钟最多20次 message: 'Too many requests, please try again later.' }); app.use('/v1/chat/completions', limiter);超时控制:
国产API偶尔响应慢,不能让VS Code一直等待。在zhipu.chat.completions.create()里加:const controller = new AbortController(); setTimeout(() => controller.abort(), 30000); // 30秒超时 const response = await zhipu.chat.completions.create({ // ...其他参数 signal: controller.signal });日志审计:
记录每次请求的model(用于后续分析哪个模型被调用最多)、prompt_length(用于优化token消耗):const promptLength = messages.reduce((sum, msg) => sum + msg.content[0].text.length, 0); console.log(`[${new Date().toISOString()}] ${model} | ${promptLength} chars | ${max_tokens} tokens`);
5. 常见问题与排查技巧实录:那些让你抓狂3小时的坑
5.1 VS Code插件报错“Network Error”:90%是CORS或SSE头问题
现象:VS Code右下角弹出红色提示“Network Error”,终端里Node服务日志没有任何请求记录。
排查步骤:
- 打开VS Code开发者工具(
Ctrl+Shift+P→Developer: Toggle Developer Tools)→ Network标签页; - 触发Claude Code(Ctrl+Enter),在Network里找到
/v1/chat/completions请求; - 点击该请求 → 查看Headers → 检查
Request Headers里的Origin是否为vscode-webview://; - 如果是
file://或http://localhost:xxxx,说明CORS配置错了,检查app.use(cors({...}))里的origin值; - 如果Origin正确,再看
Response Headers,确认是否有Content-Type: text/event-stream和X-Accel-Buffering: no。
根本原因:VS Code WebView的Origin是vscode-webview://,不是常规的http://协议,必须显式允许。很多教程写origin: true或origin: '*',这在WebView里无效。
5.2 插件卡在“Loading…”:SSE流被截断或格式错误
现象:VS Code显示“Claude Code: Generating…”持续10秒以上,Node服务日志显示GLM response streamed,但前端没收到任何代码。
抓包分析:
用Wireshark过滤http.request.uri contains "completions",查看响应体。常见错误:
错误1:缺少
data:前缀
正确:data: {"type":"content_block_delta","delta":{"text":"def"}}\n\n
错误:{"type":"content_block_delta","delta":{"text":"def"}}\n\n(漏了data:)
→ 修改res.write(),确保每行都以data:开头。错误2:换行符不规范
正确:\n\n(两个LF)
错误:\r\n\r\n(CRLF,Windows风格)或\n(单个LF)
→ 在res.write()里硬编码'\n\n',不要用os.EOL。错误3:响应头缺失
Connection: keep-alive
导致TCP连接被中间设备(如公司防火墙)主动关闭。
→ 在res.writeHead()里显式添加'Connection': 'keep-alive'。
5.3 API Key无效但报400错误:国产模型鉴权头格式不匹配
现象:Node服务日志报400 Bad Request,但process.env.ZHIPU_API_KEY确认正确。
真相:智谱GLM要求Authorization: Bearer <key>,而Kimi要求Authorization: Moonshot <key>,DeepSeek要求Authorization: Bearer <key>但Key前缀是sk-xxx。如果你的代码里写的是headers: {'Authorization': 'Bearer ' + apiKey},那么调Kimi时就会400。
解决方案:
在server.js里按模型动态设置Header:
let headers = {}; if (model.includes('glm')) { headers['Authorization'] = `Bearer ${process.env.ZHIPU_API_KEY}`; } else if (model.includes('moonshot')) { headers['Authorization'] = `Moonshot ${process.env.KIMI_API_KEY}`; } else if (model.includes('deepseek')) { headers['Authorization'] = `Bearer ${process.env.DEEPSEEK_API_KEY}`; }5.4 “Context window exceeded”错误:国产模型token计算方式差异
现象:对长文件(如>2000行Python)调用Claude Code,返回400: context window exceeded。
原因:Claude Code插件计算max_tokens时,把整个文件内容+提示词都算进去;而国产模型(如GLM-4)的上下文窗口是32768 tokens,但它的tokenizer和Anthropic不同,同样一段文本,GLM可能算出35000 tokens,直接超限。
解决办法:
在请求体转换阶段,主动截断过长的messages:
// 计算prompt长度(粗略估算,1汉字≈2token,1字母≈1token) const estimateTokens = (text) => { return text.split('').reduce((sum, char) => /[\u4e00-\u9fa5]/.test(char) ? sum + 2 : sum + 1, 0); }; const totalPromptTokens = zhipuMessages.reduce((sum, msg) => sum + estimateTokens(msg.content), 0); // 如果超限,截断user消息到前10000字符 if (totalPromptTokens > 25000) { zhipuMessages[0].content = zhipuMessages[0].content.substring(0, 10000) + '...(truncated)'; }5.5 多模型路由:如何让一个服务对接GLM、Kimi、DeepSeek
需求:团队同时采购了智谱、月之暗面、深度求索的API,想根据prompt关键词自动路由。
实现:
在server.js的app.post()里加路由逻辑:
let targetModel = 'glm-4'; let apiProvider = 'zhipu'; if (messages[0].content[0].text.toLowerCase().includes('kimi')) { targetModel = 'moonshot-v1-8k'; apiProvider = 'kimi'; } else if (messages[0].content[0].text.toLowerCase().includes('deepseek')) { targetModel = 'deepseek-coder-33b-instruct'; apiProvider = 'deepseek'; } // 然后根据apiProvider调用不同SDK if (apiProvider === 'zhipu') { // 调用ZhipuAI } else if (apiProvider === 'kimi') { // 调用Kimi SDK } else if (apiProvider === 'deepseek') { // 调用DeepSeek SDK }最后分享一个小技巧:在VS Code里按
Ctrl+Shift+P→ 输入Preferences: Open Settings (JSON),直接编辑settings.json,添加:"claude-code.baseUrl": "http://localhost:3000", "claude-code.model": "claude-3-haiku-20240307", "claude-code.apiKey": ""这样配置永久生效,不用每次进GUI设置。而且
settings.json可以提交到Git,团队成员git pull后一键同步配置。