先说结论:我目前在终端里写代码的默认组合,已经变成“Gemini CLI 当前端、GLM 当后端、HagiCode 当接线板”。这套玩法最直接的价值是,你不用再因为工具链喜欢 Gemini CLI、模型预算喜欢 GLM 而两头打架。HagiCode 这一版更新把 GLM 的接入做成了一等公民,并且能完整暴露给 Gemini CLI 使用,模型请求从哪来、走到哪家、按什么规则切换,全都由 HagiCode 这一层统一接管。
这篇文章我尽量把整个思考过程、配置步骤、实测数据和踩坑记录都交代清楚。适合两类人看:一是像我一样,日常在命令行里用 AI 写代码,又想在 Gemini CLI 和 GLM 之间自由切换的开发者;二是正在折腾“多模型统一接入”,看到一堆 vscode 集成 Claude Code、IDE 集成 Codex 的帖子,但不知道底层该怎么组织的朋友。这篇文章不会教你在一百个编辑器里各配一遍,而是用一个更底层、更好维护的思路把问题一次解决。
1. 当 GLM 遇上 Gemini CLI,为什么要做一次多模型打通
1.1 为什么我把 Gemini CLI 当作主力前端
我平时在终端里的工作流其实很简单:用 tmux 开几个窗口,一个写代码,一个跑测试,一个留给 AI。在尝试过一堆所谓 AI 编辑器之后,我反而回到了 CLI 工具。Gemini CLI 是我目前最顺手的一个,原因是它的交互设计并不是“聊天框”,而更像是一个真的坐在你旁边的结对程序员。它知道当前目录的文件结构,能自动读取相关文件,能一次性改多个文件,而且每次改动之前会告诉我它打算动哪些文件,给一个确认的机会。
这个体验虽然不少 IDE 插件也在做,但 Gemini CLI 的处理很轻,不会强行绑架你已经习惯的编辑器。更重要的是,它的会话上下文管理做得比较好。连续聊一个小时的改动需求,它依然能记得前面讨论过的约束,而不是聊着聊着就把前面的话忘了。对于做跨文件重构的场景,这种长期上下文比单轮问答值钱得多。
问题在于,工具再顺手,模型后端也不应该被绑死。Gemini CLI 默认连的是 Google 自家模型体系,而我在实际项目里经常需要用 GLM 来完成任务。一个负责交互,一个负责算力,中间缺一个能完成协议翻译和路由调度的粘合层。
1.2 GLM 凭什么值得被“全面支持”
先说一个很直接的理由:成本。GLM 系列模型在智谱开放平台上有不少免费 token 活动,官方也经常发 coding 体验卡,对于自己写开源项目或者做原型验证的人来说非常合适。我手头有 GLM 的额度,不用白不用,与其每个月多花一份订阅费,不如想个办法把它接进我已有的工具链。
再说能力。最近我把 GLM 的几个新模型拿来跑代码任务,包括代码生成、测试用例补全、以及解释一个老项目里的祖传逻辑。它的表现已经能进入“可正经干活”的第一梯队,尤其是对中文注释项目、对国内常见技术栈的理解,很多时候比国外模型表现得更加贴手。这里不吹不黑,光看模型本身,GLM 在长文本理解和中文文档处理上确实有自己的优势,而且它还带多模态能力,文字里夹一张截图也能处理。
但 GLM 有一个现实短板:它没有一个足够好的“驾驶舱”。你有再强的模型,如果只能在一个简陋的网页对话框里用,效率上不去。而 Gemini CLI 这种终端代理工具,恰好提供了一个足够完整的执行环境,包括文件读写、命令执行、差异确认、版本回滚。既然双方各有优势,把它们组合起来才是正解。
1.3 一个“路由层”解决两个工具打架的问题
HagiCode 最早只是我自己写的一个小工具,用来处理不同模型服务商 API 格式不统一的问题。一开始只是想接一个模型,后来发现身边朋友总在问:能不能在同一个工具里比较不同的模型?今天试完这个明天想试那个,不要每次重装插件。
这其实暴露了一个更普遍的痛点:大家已经厌倦了“为每个工具单独做一遍模型接入”。在各 IDE 生态里,经常看到有人在搜 vscode 集成 Claude Code、IDEA 集成 Claude Code、Cursor 集成、Trae 集成……本质上都是想做同一件事:统一入口,切换不同模型。但如果你在每个编辑器里分别配一遍,每换一个模型就要在十几个地方改配置,就是在重复造轮子。
正确的做法是把模型接入能力下沉成一个独立的本地服务。Gemini CLI 或者其他前端工具,都只需要和这个本地服务说话,模型换成了谁,前端根本不需要关心。HagiCode 就是这套思路的落地。这次的版本更新,把 GLM 做成了路由规则里的一等支持项,于是你就能在 Gemini CLI 的界面里,像选择 Gemini 原生模型一样选择 GLM。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. HagiCode 的多模型架构,从源头避免“改源码”的黑洞
2.1 直接给 Gemini CLI 打补丁为什么走不通
当初我考虑过另一个方案:直接改 Gemini CLI 的源码,把 GLM 的 API 调用写成硬编码。这个方案在概念上最直接,但落地之后会很痛苦。
优先级最高的原因是维护成本。Gemini CLI 是快速迭代的工具,几乎每周都在更新。一旦改了源码,每次上游升级都要做一次 rebase,万一官方内部重构了模型调用层,你所有补丁都要重写。而且 Gemini CLI 本身是开源项目没错,但你是作为使用者去改,不是作为贡献者去维护,这种分支长期跟着上游跑,会耗尽精力。
第二个原因是不可移植。改了 Gemini CLI 源码,意味着只有 Gemini CLI 能用上这项能力。如果哪一天我想在另一个 AI 前端里也使用 GLM,还得再改一遍那个工具的源码。你会发现,每接入一个前端,就要重复维护一套集成逻辑,这个模式看起来很勤奋,实际上是在给自己挖坑。
所以 HagiCode 从一开始就没有走这条路。它把自己定位成 Gemini CLI 和模型服务之间的网关,而不是某个工具的补丁。Gemini CLI 不需要知道 GLM 长什么样,GLM 也不需要为 Gemini CLI 做特别适配,两边只跟 HagiCode 打交道。
2.2 本地网关要完成三件事
一个最基本的模型接入网关,本质上是三个零件:监听服务、协议转换器、路由表。我自己实现时也是先做最小可用版本,再逐步加细节。
监听服务负责在本地开放一个 HTTP 端口。Gemini CLI 发出请求到这个端口,网关接住,再转发给真正的模型服务方。整个过程发生在本机,不经过任何第三方中转,这一点很关键。协议转换器负责处理“说话方式”的差异。Gemini CLI 有自己习惯的请求格式,智谱 GLM 走的是另一套 API 规范,两个协议之间不是简单换个 URL 就能通,字段名、工具调用格式、图片消息的编码方式都不一样。路由表决定当前这次请求应该发给哪个模型。规则可以很简单:默认都用 GLM,也可以很复杂:按命令类型、上下文长度、用户身份做不同分发。
这三个零件叠在一起,就构成了一个完整的“翻译官”。类比一下,Gemini CLI 说英语,GLM 说中文,HagiCode 不是一个只会翻译单词的词典,而是一个知道什么时候该意译、什么时候需要保留原始语义的专业译者。
code复制客户端请求
↓
Gemini CLI 格式
↓
HagiCode 本地网关(127.0.0.1:8787)
↓
读取路由表,匹配本次任务应使用的模型
↓
转换为模型服务商要求的格式
↓
调用 GLM / 其他模型 API
2.3 统一消息模型是关键,不是简单转发
如果只是简单转发,你会发现在实际使用中经常出现一种诡异现象:模型明明有工具调用能力,但在 Gemini CLI 里不调用;或者模型返回的内容能生成,但前端解析不了。
根因在于各家 API 对“工具调用”的描述方式差别很大。有的用 function calling,有的用 tool use,参数结构也完全不一致。CLI 工具要给模型提供文件读取、命令执行这些能力,本质是通过工具调用完成的。如果网关不把工具描述转换成目标模型认识的格式,模型就认为自己没有工具可用,只能凭空回答,然后整条链路就废了。
HagiCode 在中间定义了一套规范化的内部消息结构,可以理解成“世界语”。Gemini CLI 进来的请求先翻译成世界语,决定好路由之后,再由世界语翻译成目标模型的方言。这样一来,上层前端不需要改,下层模型也不需要迁就,扩展新模型时只需要写一个新的适配器。
这就是为什么很多群里讨论“能不能让 GLM 支持 Anthropic 协议”“能不能让某模型兼容某协议”的时候,我的回答通常是:不要简单改协议头,要把消息模型做抽象。只改 URL 和 Key,顶多让请求发出去,但工具调用、多模态内容、流式输出这些深水区,全靠抽象层兜底。
3. 把 GLM 接进 Gemini CLI 的操作步骤与参数选择
3.1 动手前先确认三件事
开始配置之前,先花两分钟确认这三件事,能省掉后面一大半的报错。
第一,确认你的智谱开放平台账号已经创建了 API Key,而且开通了想要使用的模型权限。GLM 有些新模型是需要单独申请或开通白名单的,如果你在调用时总报 model not found,大概率不是代码问题,而是模型权限没开。
第二,确认本机 Node.js 版本。HagiCode 和 Gemini CLI 都基于 Node.js,建议 Node 20 以上。太老的版本会在安装依赖时出现各种莫名奇妙的问题,不值得在这种地方浪费时间。
第三,想清楚你的路由策略。我建议先别追求复杂,默认全部走 GLM,等跑通了再增加按命令区分模型。一开始就配置一大堆规则,出了问题很难判断是哪一层错了。
3.2 安装 HagiCode 并配置智谱 Key
安装命令很简单,我用的是 npm 全局安装:
bash复制npm install -g hagicode@latest
安装完成后,先初始化默认配置目录:
bash复制hagicode init
这条命令会在你的用户目录下创建 ~/.hagicode/ 目录,并且生成一个 config.yaml 模板。然后创建一个配置文件,内容类似下面的结构:
yaml复制server:
host: 127.0.0.1
port: 8787
providers:
zhipu:
type: zhipu
api_key_env: ZHIPU_API_KEY
models:
glm-4.6:
provider: zhipu
model_id: glm-4.6
max_input_tokens: 128000
supports_vision: true
glm-4-flash:
provider: zhipu
model_id: glm-4-flash
max_input_tokens: 128000
supports_vision: true
routes:
default: glm-4.6
quick: glm-4-flash
把 Key 配置到环境变量里,避免明文写在配置文件中:
bash复制export ZHIPU_API_KEY=你的智谱Key
我不建议把 Key 直接粘贴进配置文件然后同步到代码仓库。就算你的仓库是私有的,也难保哪天不小心公开或交给别人,轮换 Key 很麻烦。环境变量方式多写一行,但安全等级完全不同。
3.3 路由规则决定了 GLM 在什么任务后被调用
配置里最值得花心思琢磨的是 routes 部分。它决定了什么时候用 GLM、什么时候切其他模型。我目前的实际配置比上面的模板多一点路由规则,但核心逻辑都是围绕“任务类型”做分发。
比如我把 quick 路由指向了 glm-4-flash,因为它响应速度快,适合简单问答、代码解释、日常 ide 补全。而 default 路由指向 glm-4.6,用于正经的代码生成和重构,因为它的推理更扎实,出错率明显低。如果某个任务需要视觉理解能力,比如给模型发一张截图让它分析 UI 问题,我配置的模型还具备多模态能力,可以直接处理。
如果后续你希望加入其他模型,比如 DeepSeek、Qwen、MiniMax 之类的,在 providers 里增加一段配置,然后在 models 里声明几个模型名,再把 routes 指过去就行。这就是 HagiCode 多模型架构的扩展逻辑,模型生态可以慢慢建,但入口始终统一。
3.4 让 Gemini CLI 走本地网关
HagiCode 侧准备好之后,先启动网关服务:
bash复制hagicode serve
看到类似 listening on 127.0.0.1:8787 的日志,说明本地网关已经就绪。接下来把 Gemini CLI 指向它。不同版本的 Gemini CLI 自定义端点方式略有差异,推荐使用环境变量,这样不影响全局配置。
bash复制export HAGICODE_ENDPOINT=http://127.0.0.1:8787
export GEMINI_MODEL=glm-4.6
gemini
启动 Gemini CLI 后,可以先输入 /status 确认当前模型已经变成 glm-4.6,然后输入一个最简单的验证请求:
text复制帮我看看当前目录下有几个文件,并简述每个文件的作用。
如果它能正确列出文件并给出分析,说明整条链路已经通了。注意,这里 Gemini CLI 读取文件列表的工具调用会先发给 HagiCode,HagiCode 翻译成 GLM 认识的工具调用格式,再由 GLM 决定调用哪个工具。这个过流程能跑通,就已经验证了整个链路的核心能力。
4. 实测记录:GLM 在 Gemini CLI 里写代码是种什么体验
4.1 任务一:跨目录 TypeScript 代码重构
我在一个大约 200 个文件的 TypeScript 工程里做了一个真实测试。项目是一个内部工具的后端服务,代码里有几个模块还在用 callback 风格处理异步逻辑,我打算让 AI 帮我全部改成 async/await,并且要求不能改变对外接口行为。
Gemini CLI 在接到任务后先扫描了项目结构,读取了相关模块及其调用方。我能看到它确实理解了这个改动的影响范围,没有一上来就闷头改,而是先梳理了文件之间的引用关系。然后它逐文件提出修改建议,每个文件改动前都会向我确认。GLM 生成的代码风格和项目原有风格基本一致,没有出现明显的类型错误。
一次跑下来,改完了大概 8 个文件,涉及 30 多处异步逻辑调整,TypeScript 编译器一次通过。这个结果确实超出我预期。中途唯一一次需要我介入,是它想改一个公共工具函数,但那个函数还有其他调用方,直接改签名会影响别的模块。我阻止了这次修改,调整了提示词,让它只改调用处,不改公共函数本身。
4.2 任务二:排查一个只在夜间告警的诡异 Bug
第二个测试是排查一个只在夜间出现的任务告警问题。这个 Bug 之前困扰了我们两天,因为白天怎么跑都正常,只有夜间定时任务跑完才会报错。我把相关日志文件路径和告警内容截图发给 Gemini CLI,让它分析可能的原因。
GLM 配合 Gemini CLI 的文件读取能力,先看了定时任务的启动日志、错误堆栈和配置文件,最后给出的判断是:夜间任务与白天的任务共用了同一个临时目录,夜间任务执行时间更早,临时目录被清理的竞态条件更容易触发。这个判断后来手动验证确实是对的。
这个场景有两个值得关注的点:一是它同时用到了文本日志分析和少量视觉理解能力,因为告警内容是以截图形式存在的;二是它跨了多个文件,既有日志又有配置,单一对话窗口如果没有持久上下文很难把线索串起来。Gemini CLI 在这个场景里承担了上下文管理和文件读取组织者的角色,GLM 负责真正的推理和判断。
4.3 GLM vs Gemini 原生模型的实测结果
为了不那么主观,我拿同一个任务分别跑了两套后端:默认的 Gemini 原生模型和 GLM。对比的维度包括首次响应耗时、代码质量、上下文记忆能力和成本。
| 对比维度 | Gemini 原生模型 | GLM(经 HagiCode) |
|---|---|---|
| 首次响应速度 | 较快 | 略慢,但体感差距不大 |
| 中文代码注释理解 | 一般 | 更好,注释里很多隐含信息拿捏得到 |
| TypeScript 重构准确率 | 高 | 当前版本已相当接近 |
| 工具调用稳定性 | 原生最优 | HagiCode 适配后比较稳定 |
| 长上下文保持 | 好 | 受限于模型上下文窗口,够用但需注意 |
| 成本 | 按用量计费 | 配合活动额度更划算 |
整体来看,如果只是偶尔用来写代码,两者差距没有想象中那么大。但如果你跟我一样,手里有 GLM 的体验额度或者团队数据合规要求必须用智谱,那 HagiCode 这套方案的价值就会非常明显。
4.4 必须承认的不足
说实话,整条链路也不是完全没有牺牲。一些强依赖 Gemini API 原生的能力,比如联网搜索、与外部应用深度联动这类,切到 GLM 后就不能用了。原因很简单:这些能力是模型服务商在后端做好的,不是本地工具能凭空调用出来的。你让 GLM 当后端,GLM 没有的那些云端扩展能力自然就用不了。
另外,虽然 HagiCode 已经做了工具调用格式的转换,但并不是 100% 无缝。极少数情况下,Gemini CLI 发出的某个工具定义结构特别复杂时,适配器转换后可能产生偏差,模型偶尔会误解工具参数。这种问题目前不是高频发生,但你在生产环境使用前必须有心理准备,并且要保留回退方案:切回原生模型,或者直接把请求发给 GLM 自己的聊天界面排查。
5. 接入过程中遇到的高频报错与排查思路
5.1 高频报错速查表与解决动作
我在配置和使用的几天里,前前后后遇到过不少问题。这里整理成速查表:
| 报错现象 | 可能原因 | 解决动作 |
|---|---|---|
| 401 authentication error | 环境变量 ZHIPU_API_KEY 没读到,或 Key 失效 | echo $ZHIPU_API_KEY 检查变量;重新创建 Key |
| model not found | 模型 ID 写错,或该模型未开通权限 | 去智谱控制台确认模型名和权限;核对配置里的 model_id |
| 连接 127.0.0.1:8787 失败 | HagiCode serve 没启动,或端口被占用 | 确认网关进程;换端口并同步修改环境变量 |
| 请求发出去但一直没响应 | 模型上下文太长,或网络问题 | 使用 /clear 清空上下文;切 glm-4-flash 测试 |
| 工具调用失灵 | 前端工具描述太长,适配器截断 | 更新 HagiCode 版本;简化任务描述 |
| 回复内容正常但前端显示解析失败 | 存在流式输出兼容性问题 | 在 HagiCode 配置中切换 SSE 模式或强制非流式 |
排查思路有一个顺序建议:先确认本地网关日志有没有收到请求,再确认网关有没有成功转发到模型服务商,最后确认响应有没有顺利回传到前端。用这个顺序能快速定位是哪一层出了问题。
5.2 两个不仔细观察根本找不到问题的细节
第一个细节:改了配置之后忘记重启网关。HagiCode 的配置是在启动时加载的,不是每来一个请求就重新读一次文件。我一开始在配置文件里新增了一个模型,但没重启网关,结果 Gemini CLI 里一直看不到新模型。这个问题的坑在于它不报错,前端日志正常,后端也正常,只是你请求的模型不是你以为的那个。排查了好一会儿才反应过来。
第二个细节:上下文窗口对“有工具调用”场景的占用比想象中大。Gemini CLI 作为前端会不断把文件读取结果、工具执行结果塞进上下文。如果模型上下文窗口不够大,会导致工具结果被截断,模型基于不完整信息做判断,看起来像模型变笨了,其实是量程不够。
我踩过一次就是因为一个仓库扫描,读了一堆文件,工具返回的内容很长,GLM 收到时上下文已经明显超压,最后给出的建议明显缺乏依据。后来我养成了两个习惯:任务开始前先 git clean 或者限定文件范围,避免无关文件被扫进来;发现变笨迹象时,先清空上下文而不是怪模型。
5.3 啥时候不建议用这个方案
这套方案不是万能的,有几种情况我不建议折腾。
如果你日常只用某个 IDE 的 AI 插件,而且那个插件本身已经支持多模型切换,那确实没必要再绕一层网关。集成是手段不是目的,能用原生解决就尽量原生。
如果你们团队的合规要求非常严格,不允许任何本地服务转发代码到第三方模型,那 HagiCode 这条路显然不合适。网关虽然只转发请求,不存储代码,但敏感代码文本仍然会经过模型服务商,这一层必须提前评估清楚。别到事故发生了再想起合规问题。
如果你只想要一个开箱即用的工具,没有兴趣维护自己的配置和排查问题,那也建议放弃。这套东西的本质是“用少部分维护成本换取模型自由”,它需要你理解链路里每一层的作用。你不能指望它像商业软件一样,遇到问题一键自动修复。
6. 这次进化之后的几条实在经验
6.1 HagiCode 下一阶段想做什么
多模型接入走到现在,我的下一步计划主要围绕三件事。
第一是做一个模型对比模式。现在我觉得 GLM 在写代码上已经够用,但不同任务确实存在不同模型的差异化优势。我想做的是在 Gemini CLI 里输入命令之后,能把同一个任务同时发给两个模型,然后人工对比它们各自的方案和效率。这样选型就不再靠听说,而是每次任务现场出结论。
第二是完善工具调用能力。目前适配 GLM 的工具调用已经稳定,但我发现不同模型对工具描述的理解颗粒度不一样。下一步想针对具体模型做更细的提示词优化,让工具描述更贴合每个模型的习惯,而不是用一套标准模板走天下。
第三是把配置过程做得更简单。现在配置 YAML 对开发者来说还好,但真正的入门用户看到这个东西可能就放弃了。我在考虑是不是可以加一个交互式配置向导,让用户通过问答方式生成配置,减少上手门槛。
6.2 给想复刻这套玩法的朋友的几条实诚建议
如果你也想在自己的环境中复刻这套玩法,而不是已经被各种碎片教程折腾烦了,我有几条实在建议:
先接一个模型跑通再做多路。不要一上来就规划支持五个模型、六个前端。先把 GLM 一个模型完整跑通,命令确认、文件读取、多文件修改都能正常工作后,再考虑扩展其他模型。一旦一条链路的深层问题都解决了,新模型只是多加一个适配器的事情。
认真对待工具调用格式。这是整条链路里最容易翻车的地方,也是最值钱的地方。你可以先不给任何工具,只做纯文本问答验证连通性。但这只是万里长征第一步,真正的验证标准是:让前端发起一个读取文件或执行命令的工具请求,模型能正确响应,并且前端能正确解析工具的返回结果。
日志要看得懂。HagiCode 的日志在开发阶段一定要开着,它能告诉你每个请求最终被路由到了哪个模型、耗时多少、有没有报错。遇到问题先看日志,不要凭感觉猜。
不要忘了本地网关的定位。HagiCode 只是运行在你本机的服务,只做转发和协议转换,不做数据缓存,不做请求审计,也不是中间商。它不会优化模型本身的能力,也不会解决你写错提示词带来的问题。把它当成一个普通的开发基础设施来对待就好。
我个人在实际操作中最深的感受是:模型选型这件事,真的不该“非此即彼”。工具喜欢哪个用哪个,模型适合哪个用哪个,中间用一层网关把它们解耦,你会发现很多之前看起来无法调和的矛盾,其实只是缺少一个合理的连接层。GLM 的接入只是这条多模型路上的一站,后面还会有更多模型被纳入同一个终端入口,到时候你就不用再为了切换模型换工具了。
