
1. 一次工具链的“平替”实验从Claude到Gemini CLI最近在折腾一个老项目用的是Jeecg-Boot这个框架。熟悉国内低代码开发的朋友应该对它不陌生一套基于Spring Boot的快速开发平台。我的日常开发流里有一个环节是重度依赖Claude的API来辅助生成一些基础代码、SQL语句或者进行简单的代码审查。但最近遇到点小麻烦Claude的API调用偶尔不太稳定响应速度也时快时慢对于一个追求效率的“懒人”开发者来说这有点影响心情。于是我萌生了一个想法能不能找个“平替”谷歌的Gemini模型风头正劲其API也开放了而且官方还提供了一个命令行工具gemini-cli。这玩意儿听起来就挺对胃口——命令行意味着可以无缝集成到我的终端工作流、脚本里甚至是一些自动化工具链中。如果它能达到Claude七八成的功力那在稳定性和集成便利性上可能就是一次不错的升级。说干就干我决定用我手头这个Jeecg-Boot项目作为“试金石”来一场从Claude到Gemini CLI的迁移实验。我的核心诉求很简单在不改变现有Jeecg-Boot项目核心开发逻辑的前提下将原先依赖Claude API完成的那些琐碎、重复的代码辅助任务迁移到Gemini CLI上来完成。我预想的场景包括根据数据库表结构描述生成对应的JAVA实体类、生成简单的增删改查Service层代码、根据错误日志片段快速定位可能的问题、以及解释一段复杂的业务逻辑代码。如果这些“基本功”Gemini CLI都能顺畅跑通那这个“平替”就算成功了一大半。实验的初步结果标题已经剧透了——“基本通畅”。这意味着在大多数常规的、结构化的任务上Gemini CLI的表现可圈可点甚至在某些方面因为其命令行集成的特性让我感觉更顺手。但标题里也埋了个“彩蛋”“波浪血案”。这不是什么恐怖故事而是一个在代码生成场景下由中英文标点符号差异引发的、令人哭笑不得的“惨案”。它暴露了在使用大模型工具时一个极其细微却又影响深远的细节问题。这个“血案”的来龙去脉以及如何“止血”恰恰是本次迁移实验中最有价值的经验之一。接下来我就把这趟“平替”之旅的完整过程、核心操作、顺畅之处以及那个让我调试了半个多小时的“波浪血案”毫无保留地分享出来。2. 环境搭建与初体验Gemini CLI上手实录工欲善其事必先利其器。要把Gemini CLI用起来第一步肯定是把它请到自己的开发环境里。整个过程比想象中要简单直接对于习惯在终端里操作的开发者来说几乎没有学习成本。2.1 安装与配置五分钟搞定API密钥Gemini CLI是一个Node.js包所以前提是你的系统里得有Node.js环境建议版本在16以上。安装它只需要一行命令npm install -g google/generative-ai-tools安装完成后你会在全局命令中找到一个叫gemini的可执行文件。不过在它能开口说话之前你得先给它一张“身份证”——Google AI Studio的API密钥。获取API密钥访问Google AI Studio的网站登录你的谷歌账号。在界面中应该能找到创建API密钥的入口。生成后务必立即复制并妥善保存因为它只显示一次。配置密钥有了密钥配置方式非常灵活。最直接的是设置环境变量export GEMINI_API_KEY你的_API_密钥_内容你可以把这行命令加到你的shell配置文件如~/.bashrc,~/.zshrc里实现永久配置。另一种方式是在每次调用时通过--api-key参数指定但显然不如环境变量方便。验证安装和配置是否成功可以运行一个简单的交互式对话gemini chat如果终端进入了对话模式并且模型能正常回复说明一切就绪。你也可以用单次命令测试gemini -m gemini-1.5-pro-latest 你好请回复‘配置成功’这里有个小细节-m参数用于指定模型。Gemini提供了多个模型比如gemini-1.5-pro、gemini-1.5-flash等。-latest后缀会自动选择该系列的最新版本。对于代码生成这类任务gemini-1.5-pro系列在逻辑和代码质量上通常表现更好而flash系列速度更快适合简单问答。我大部分时间用的是gemini-1.5-pro-latest。2.2 初战告捷用Jeecg-Boot的实体类生成试刀环境配好了迫不及待想试试它的“码力”。我选择了Jeecg-Boot开发中最常见的一个场景根据MySQL数据库表结构生成对应的JAVA实体类。在Jeecg-Boot中实体类通常继承一个基础类并使用特定的注解如TableName,TableId等。我手头有个sys_user用户表结构比较简单。我先把表结构描述整理成一个清晰的提示词Prompt请根据以下MySQL表结构生成一个符合Jeecg-Boot框架规范的JAVA实体类。要求 1. 类名使用大驼峰命名法例如表名sys_user对应类名SysUser。 2. 继承jeecg-boot框架中常用的基础实体类例如 com.baomidou.mybatisplus.extension.activerecord.Model。 3. 使用lombok的Data注解。 4. 使用mybatis-plus的注解TableName(表名)标识表TableId(type IdType.ASSIGN_ID)标识主键。 5. 字段使用对应的JAVA类型如String, Integer, LocalDateTime并添加TableField注解映射列名。 6. 表结构如下 - id: bigint, 主键自增 - username: varchar(50), 用户名非空 - password: varchar(255), 密码 - realname: varchar(50), 真实姓名 - status: tinyint, 状态1启用0禁用 - create_time: datetime, 创建时间 - update_time: datetime, 更新时间我将这个提示词保存到一个文件prompt_sys_user.txt中然后使用Gemini CLI来生成代码gemini -m gemini-1.5-pro-latest -f prompt_sys_user.txt SysUser.java命令执行后我迫不及待地打开SysUser.java文件查看。结果令人满意它生成的代码几乎可以直接使用import com.baomidou.mybatisplus.annotation.*; import lombok.Data; import java.time.LocalDateTime; Data TableName(sys_user) public class SysUser extends ModelSysUser { TableId(type IdType.ASSIGN_ID) private Long id; TableField(username) private String username; TableField(password) private String password; TableField(realname) private String realname; TableField(status) private Integer status; TableField(create_time) private LocalDateTime createTime; TableField(update_time) private LocalDateTime updateTime; }生成的代码完全符合我的要求正确的类名、继承了Model、使用了Data、TableName、TableId注解字段名和类型映射准确甚至将数据库的下划线命名create_time自动转换为了JAVA的驼峰命名createTime。这个“开门红”让我对Gemini CLI的代码理解与生成能力有了初步的信心。它不仅能理解Jeecg-Boot这个相对小众的国内框架的约定还能准确应用MyBatis-Plus的注解规范这超出了我的预期。3. 深度集成将Gemini CLI嵌入开发工作流仅仅能生成代码片段还不够一个优秀的工具应该能无缝嵌入现有的开发流程成为提升效率的“倍增器”。接下来我重点探索了如何将Gemini CLI与我的日常开发环境结合起来。3.1 打造专属的代码生成脚本手动写提示词、执行命令、保存文件这个流程还是有点繁琐。我决定写一个Shell脚本让它变得更自动化。我的目标是输入数据库表名和简短描述脚本自动调用Gemini CLI生成实体类、基本的Service接口和实现类骨架。我创建了一个脚本文件gen_jeecg_code.sh#!/bin/bash # 用法./gen_jeecg_code.sh 表名 表描述 # 例如./gen_jeecg_code.sh sys_order “订单主表” TABLE_NAME$1 TABLE_COMMENT$2 PROMPT_FILE/tmp/prompt_${TABLE_NAME}.txt CLASS_NAME$(echo $TABLE_NAME | sed -r s/(^|_)([a-z])/\U\2/g) # 下划线转大驼峰 # 构建提示词 cat $PROMPT_FILE EOF 你是一个Jeecg-Boot专家。请为MySQL表“${TABLE_NAME}”${TABLE_COMMENT}生成以下JAVA代码 1. 实体类 ${CLASS_NAME}。要求 - 继承 com.baomidou.mybatisplus.extension.activerecord.Model。 - 使用 Data, TableName(${TABLE_NAME})。 - 假设主键字段名为‘id’类型为bigint使用 TableId(type IdType.ASSIGN_ID)。 - 其他字段请根据常见业务逻辑合理推断并生成至少包含createTime和updateTime字段。 - 使用标准的JAVA类型和MyBatis-Plus注解。 2. Service接口 I${CLASS_NAME}Service。要求 - 继承 com.baomidou.mybatisplus.extension.service.IService${CLASS_NAME}。 - 包含常见的分页查询方法声明。 3. Service实现类 ${CLASS_NAME}ServiceImpl。要求 - 实现 I${CLASS_NAME}Service 接口。 - 继承 com.baomidou.mybatisplus.extension.service.impl.ServiceImpl${CLASS_NAME}Mapper, ${CLASS_NAME}。 - 添加 Service 注解。 请将三部分代码分别用‘// Entity ’‘// Service Interface ’‘// Service Impl ’分隔。 EOF # 调用Gemini CLI生成代码 echo “正在为表 ${TABLE_NAME} 生成代码...” gemini -m gemini-1.5-pro-latest -f $PROMPT_FILE “/tmp/${CLASS_NAME}Generated.java” # 简单处理输出这里可以更复杂比如分割成不同文件 echo “代码已生成至 /tmp/${CLASS_NAME}Generated.java” cat “/tmp/${CLASS_NAME}Generated.java”这个脚本虽然简单但已经实现了核心的自动化。我运行./gen_jeecg_code.sh product_info “产品信息表”它成功调用Gemini CLI生成了一份包含实体类、Service接口和实现类的复合代码文件。我只需要复制粘贴稍作调整比如补充具体的字段即可。这比手动编写或复制旧文件修改要快得多而且减少了因疏忽导致的注解遗漏或拼写错误。3.2 与IDE的快捷联动以VS Code为例在终端里切来切去还是不够“丝滑”。作为VS Code的重度用户我希望能直接在编辑器里触发Gemini。这可以通过配置VS Code的“任务”Tasks来实现。我在项目根目录的.vscode/tasks.json文件中添加了一个自定义任务{ “version”: “2.0.0”, “tasks”: [ { “label”: “Ask Gemini”, “type”: “shell”, “command”: “gemini”, “args”: [ “-m”, “gemini-1.5-pro-latest”, “-p”, “${input:geminiPrompt}” ], “presentation”: { “echo”: true, “reveal”: “always”, “focus”: false, “panel”: “shared”, “showReuseMessage”: false, “clear”: true } } ], “inputs”: [ { “id”: “geminiPrompt”, “type”: “promptString”, “description”: “Enter your prompt for Gemini:” } ] }配置完成后我可以通过CtrlShiftP打开命令面板输入Run Task选择Ask Gemini然后直接在弹出的输入框中输入我的问题比如“解释下面这段Spring事务注解的传播行为”结果会直接输出在VS Code的终端面板里。更进一步我可以为特定操作绑定快捷键。或者利用一些已有的VS Code扩展如Shell Command或CodeGPT的替代方案实现更复杂的交互比如选中一段代码后右键选择“Send to Gemini for review”。虽然Gemini CLI没有官方的VS Code扩展但通过这种“任务”的方式已经能够实现相当便捷的集成满足了在编码过程中随时提问、随时生成的需求。4. “波浪血案”始末标点符号引发的编译灾难前面提到的一切都很顺利直到我尝试一个更复杂的场景生成一个包含复杂逻辑的Controller方法比如一个根据多条件分页查询订单的接口。提示词中我详细描述了查询参数订单号、用户ID、时间范围、状态和返回格式。Gemini CLI一如既往地快速给出了代码。我粗略一看结构清晰注解正确逻辑似乎也没问题。于是我将生成的代码复制到我的IDE中。项目编译——失败控制台报错信息指向一行看起来完全正常的代码GetMapping(“/list”) public ResultIPageOrderVo queryPageList(OrderQueryDto queryDto, RequestParam(name “pageNo”, defaultValue “1”) Integer pageNo, RequestParam(name “pageSize”, defaultValue “10”) Integer pageSize) { // ... 方法体 }IDE在GetMapping这一行标记了错误“非法字符 ‘\u201c’”。\u201c和\u201d是Unicode字符分别代表左双引号和右双引号。我瞬间明白了Gemini CLI在输出代码时使用了中文全角的弯引号“ ”而不是英文半角直引号 。在JAVA源码中字符串字面量、注解参数值都必须使用半角双引号。全角引号在视觉上看起来和半角引号很像尤其是在某些等宽字体下但编译器会将其视为非法字符。这就是我称之为“波浪血案”的原因——那些弯弯的引号像波浪一样悄无声息地“淹死”了我的编译过程。4.1 问题根因与排查为什么会出现这个问题我回顾了整个过程输入我在终端或提示词文件中使用的都是半角引号。处理Gemini模型在生成文本时可能基于其训练数据其中包含大量自然语言文本自然语言中常用弯引号或输出格式化逻辑“智能”地使用了更美观的弯引号。输出Gemini CLI原封不动地将模型输出传给了我。结果看起来完美的代码隐藏着编译炸弹。这个问题非常隐蔽因为在终端里快速浏览代码时肉眼很难区分全角和半角引号。错误信息\u201c对不熟悉Unicode的开发者来说有点晦涩。问题不是逻辑错误而是最基础的语法字符错误容易让人忽略。我花了差不多半小时在排查业务逻辑、依赖注入等问题上最后才通过仔细对比字符或者将代码粘贴到纯文本编辑器如Notepad开启显示所有字符中才发现了这些“伪装者”。4.2 解决方案过滤与预防找到原因后解决办法就多了。核心思路是在Gemini CLI的输出流入我的源码文件之前进行一道“净化”处理。方案一使用sed命令进行后处理这是最直接的方法。在将生成结果保存到文件前用sed命令替换掉全角引号gemini -m gemini-1.5-pro-latest -f my_prompt.txt | sed -e ‘s/“//g’ -e “s/”//g’ Output.java这条命令通过管道将Gemini的输出传递给sed-e ‘s/“//g’将左全角引号替换为半角引号-e “s/”//g’将右全角引号替换为半角引号。注意在shell中处理这些特殊引号需要小心转义。方案二在提示词中明确要求这是一种预防性措施。在提示词的开头或结尾用强硬的语气声明重要要求你输出的所有代码必须且只能使用英文半角符号包括双引号、单引号、括号()、逗号,和句号.。严禁使用中文全角符号。经过测试在提示词中如此强调后Gemini输出全角引号的概率大大降低但并非100%。作为一种“软约束”它有效但不能完全依赖。方案三封装成更健壮的脚本最稳妥的方法是将方案一和方案二结合并封装起来。我修改了我的gen_jeecg_code.sh脚本在调用gemini命令后自动执行字符替换过滤。同时在发送给Gemini的提示词模板里也加上了使用半角符号的强制要求。双管齐下基本杜绝了“波浪血案”的再次发生。这个坑踩得值。它提醒我在使用任何AI工具生成代码或配置时第一件事不是看逻辑而是检查最基本的语法符号特别是引号、括号、分号、逗号。最好能建立一个自动化的“安全过滤”步骤将这类低级错误扼杀在摇篮里。5. 能力边界评估Gemini CLI在Jeecg开发中的真实表现经过一系列实战和那个“血案”的洗礼我对Gemini CLI在Jeecg-Boot这类企业级Java Web开发中的能力边界有了更清晰的认识。它不是一个万能的黑盒而是一个在某些方面强大、在某些方面需要引导和约束的助手。5.1 游刃有余的领域结构化代码生成这是Gemini CLI的强项。无论是实体类、简单的Service/Dao层还是Controller的CRUD接口只要提示词描述清晰包括框架名、继承类、注解规范、方法签名期望它生成的代码骨架质量很高能节省大量模板代码的编写时间。对于Jeecg-Boot中常用的MyBatis-Plus注解、Lambda查询条件、分页对象等它都能正确使用。代码解释与注释将一段复杂的业务逻辑代码丢给它让它“解释这段代码做了什么”或者“为这段代码生成详细的JavaDoc注释”效果出众。它能很好地理解代码意图并用清晰的语言概括出来对于接手老项目或回顾自己很久以前写的代码非常有帮助。错误日志分析将项目运行中抛出的一段异常堆栈信息粘贴给它问“可能的原因是什么”。Gemini CLI能够快速定位到常见的空指针、类型转换、SQL语法错误等问题并给出初步的排查方向。虽然不能直接定位到项目中的具体行但它的分析能极大缩短盲目搜索的时间。简单的SQL编写根据描述生成基础的单表CRUD SQL、联表查询语句或者解释一个复杂SQL的执行逻辑都表现可靠。对于Jeecg开发中常见的数据库操作它足以应对。5.2 需要谨慎对待的领域复杂的业务逻辑实现对于涉及复杂状态机、多服务调用、分布式事务等核心业务逻辑直接让AI生成完整代码是危险的。它可能会生成一个“看起来合理”但存在并发漏洞、事务边界错误或业务规则遗漏的实现。正确的做法是让它生成伪代码或方法骨架然后由开发者填充关键的业务判断和流程控制。框架深度定制部分Jeecg-Boot有一些深度定化的功能比如特定的权限注解AutoLog、自定义的查询过滤器、与特定前端组件绑定的API格式等。Gemini对这些“独家”约定的了解可能不深生成代码时可能会遗漏或使用错误的方式。这时提示词中必须提供非常具体的示例或官方文档片段。依赖管理与配置让AI直接修改pom.xml或application.yml风险较高。它可能会引入版本冲突或者写出不符合项目特定配置风格的代码。更适合的做法是向它提问“我想在Spring Boot项目中集成Redis需要在pom.xml和application.yml中添加什么”然后手动将它的答案与项目现有配置进行比对和整合。代码重构建议它可以对一段代码提出“如何优化”的建议比如指出哪里可以用Stream API简化哪里存在重复代码。这些建议通常有参考价值但是否采纳、如何采纳必须由开发者基于完整的项目上下文和性能影响来决定。不能无条件接受所有“优化”。注意永远记住Gemini CLI或任何AI编码助手是一个“副驾驶”而不是“自动驾驶”。它的输出必须经过开发者的严格审查、测试和理解。尤其是在生成业务逻辑和修改项目核心配置时人的判断和经验是不可替代的。5.3 与Claude API的对比感受回到最初“平替”的目标上经过这段时间的使用我的感受是稳定性与速度Gemini CLI的API调用在我的网络环境下确实比Claude更稳定响应速度也更快、更一致。命令行工具的简洁性减少了HTTP客户端可能带来的额外开销和不确定性。代码生成质量在针对Jeecg-Boot这类有明确规约的框架时两者水平在伯仲之间。Claude有时在自然语言理解上更细腻一点但Gemini在遵循格式要求上更严格。工具链集成Gemini CLI作为命令行工具在集成到Shell脚本、CI/CD流水线、自动化任务方面天生具有优势。这是它相对于需要通过HTTP调用的Claude API的一个显著优点。“波浪血案”类问题两者都可能输出非半角符号这似乎是当前大语言模型在代码生成上的一个通病。关键在于使用者是否建立了有效的输出过滤机制。综合来看对于我的需求——一个能集成到自动化脚本中、稳定提供代码辅助的命令行工具——Gemini CLI成功地替代了Claude API。它没有带来质的飞跃但在稳定性和集成便利性上提供了更好的体验并且完全免费在免费额度内。那个“波浪血案”虽然是个小插曲但通过解决它我建立起了更健壮的使用流程这本身就是一次有价值的学习。