1. 项目概述当命令行AI助手遇上即时通讯如果你和我一样是个喜欢在终端里敲命令、用脚本自动化一切的开发者那你肯定对gemini_cli不陌生。它就像一个坐在你命令行里的AI助手能帮你写代码、分析日志、甚至直接执行系统命令把自然语言指令变成实实在在的操作。但它的交互方式一直局限在终端里——你得坐在电脑前打开一个终端窗口才能和它对话。最近我在做一个需要频繁离开工位但又不想中断手头自动化流程的项目这个矛盾点让我开始琢磨能不能让gemini_cli的能力突破终端的限制让我在手机上、在开会间隙、在任何地方都能继续“指挥”它工作于是我把目光投向了几乎人人都在用的Telegram。这个gemini_cli_server项目就是我的解决方案一个架设在gemini_cli和Telegram之间的桥梁让你能像和朋友聊天一样通过Telegram机器人来驱动你本地的AI命令行助手。核心价值很简单把专业级的命令行AI自动化变成随时随地可用的对话式服务。你不再需要守着电脑终端通过Telegram发条消息gemini_cli就能在后台为你执行任务并把结果推送回你的手机。无论是检查服务器状态、触发一个部署脚本还是让AI帮你写一段代码并直接执行测试现在都能在聊天窗口中完成。这对于需要移动办公、或者喜欢将不同工具能力聚合到单一聊天界面的开发者来说实用性直接拉满。2. 核心架构与设计思路拆解这个项目的设计哲学是“桥接”而非“重造”。它没有尝试去修改gemini_cli本身而是通过两个轻量级的服务组件在Telegram的聊天协议和gemini_cli的命令行接口之间建立了一个双向通道。理解这个架构是后续部署和自定义扩展的关键。2.1 双核心组件各司其职的通信桥梁整个系统的运转依赖于两个独立运行的程序它们通过HTTP协议进行通信形成了一个清晰的责任链。第一个核心是listen.js 它扮演着“本地网关”和“指令翻译官”的角色。这是一个用Node.js写的HTTP服务器默认运行在你本地机器的8765端口。它的核心职责是接收来自外部的HTTP请求最初是来自Telegram Bot的转发解析出其中的自然语言指令然后以子进程的方式调用你本地的gemini_cli程序。这里有一个至关重要的设计选择默认启用YOLO模式。这意味着listen.js在调用gemini_cli时会默认加上--yolo参数。这个参数告诉gemini_cli“对于需要确认的操作自动批准并执行”。在Telegram这种异步聊天场景下等待用户二次确认是不现实的YOLO模式确保了交互的流畅性。当然这也意味着你需要完全信任你的gemini_cli配置和权限设置因为它获得授权后能执行的操作范围很广。第二个核心是main.go 它是“Telegram交互前台”。这是一个用Go语言编写的Telegram机器人应用。它利用Telegram Bot API长期轮询或通过Webhook接收用户发送给机器人的消息。当它收到一条消息时并不会自己处理而是将其封装成一个结构化的JSON事件通过HTTP POST请求发送给listen.js服务的/event端点。随后它等待listen.js返回gemini_cli的处理结果再将这个结果作为回复消息发送回Telegram聊天窗口。main.go本身不包含任何AI逻辑它的任务就是做好协议转换和消息路由。2.2 交互流程全景图一次完整的交互数据流会经历以下六个步骤形成一个闭环用户发起请求你在Telegram中向你的Bot发送一条消息比如“帮我列出当前目录下所有大于100MB的文件”。Bot接收并转发main.go程序从Telegram服务器获取到这条消息将其打包成{“source”: “telegram”, “message”: “…”}的JSON格式发送到GEMINI_ENDPOINT环境变量指定的地址即listen.js的/event端点。网关处理并调用CLIlisten.js收到请求提取出message字段的内容然后在你本地系统上启动一个gemini_cli进程并将该消息作为输入传递给CLI。CLI开始理解指令并准备执行。CLI执行并返回gemini_cli根据它的配置和能力包括已集成的任何MCP服务器来执行任务。它可能会运行shell命令、调用脚本或进行推理。执行完成后它会将文本结果输出到标准输出(stdout)。网关捕获结果listen.js捕获gemini_cli进程的stdout输出将其作为处理结果封装成HTTP响应返回给调用方即main.go。Bot回复用户main.go收到HTTP响应从中提取出结果文本并将其作为一条回复消息发送回最初的Telegram聊天这样你就在手机上看到了gemini_cli执行后的答案。这个架构的优势在于解耦清晰。listen.js只关心如何与本地CLI交互main.go只关心如何与Telegram API通信。你可以单独维护、升级甚至替换其中任何一个组件。2.3 关于MCP集成的深度解读项目描述中提到了一个强大的特性“如果Gemini CLI集成了MCP服务器它们可以通过Telegram Bot完全访问”。这是本项目价值倍增的关键。MCPModel Context Protocol是一种让AI模型安全、结构化地访问外部工具和数据的协议。你的gemini_cli可能已经通过MCP连接了数据库、Git仓库、云平台API或内部系统。这个集成意味着通过Telegram发送的指令能够间接驱动所有这些MCP工具。例如你可以对Bot说“查一下过去24小时生产数据库的慢查询日志”这条指令经过gemini_cli解析后可能会调用连接了数据库的MCP服务器来执行查询然后将结果返回给你。你实际上是为所有已连接的MCP工具创建了一个移动聊天界面。在设计架构时listen.js不需要对MCP做任何特殊处理它只是简单地调用gemini_cli。而gemini_cli在内部处理消息时会自然而然地考虑所有已注册的MCP工具就像在终端中操作时一样。这种透明性使得扩展性极佳每增加一个新的MCP工具你的Telegram Bot就自动获得了一项新能力。3. 从零开始的详细部署指南理论清晰了我们进入实战环节。部署这套系统需要按顺序完成几个步骤我会把每个环节的细节和容易踩坑的地方都讲清楚。3.1 环境准备与项目初始化首先确保你的基础环境就绪。你需要Node.js (v16)用于运行listen.js网关。Go (v1.19)用于编译和运行main.goTelegram机器人。Git用于克隆仓库。一个正常工作的gemini_cli安装这是整个系统的“大脑”必须事先在你的机器上配置好并能正常运行。接下来是获取代码。打开终端执行克隆命令git clone https://github.com/bravian1/gemini_cli_server.git cd gemini_cli_server这个仓库里主要包含两个部分telegram_bot/目录存放Go写的机器人代码根目录下的scripts/和commands/目录则是需要迁移到gemini_cli配置中的关键组件。一个至关重要的步骤迁移配置文件夹。项目要求你将commands和scripts两个文件夹复制到你的~/.gemini目录下。~/.gemini是gemini_cli默认的配置目录。你需要执行cp -r commands/ ~/.gemini/ cp -r scripts/ ~/.gemini/这么做的原因是gemini_cli在运行时会在其配置目录中寻找特定的脚本和命令定义。scripts/listen.js是核心网关commands/listen/下的.toml文件则定义了Telegram Bot中可用的命令菜单。将它们放在~/.gemini下能确保gemini_cli在通过本项目被调用时拥有完全一致的行为和扩展能力。注意如果你自定义过gemini_cli的配置路径请将文件夹复制到对应的目录中。复制前建议备份原有的~/.gemini/commands和~/.gemini/scripts目录如果存在以防冲突。3.2 配置Telegram机器人这是与外部世界连接的第一步。我们需要在Telegram上创建一个Bot并获取通信凭证。创建Bot在Telegram中搜索并联系BotFather。这是Telegram官方的机器人管理工具。发送指令向BotFather发送/newbot指令。设置名称根据提示为你的机器人设置一个显示名称例如My Gemini Assistant。设置用户名设置一个全局唯一的机器人用户名必须以bot结尾例如my_gemini_cli_bot。成功后BotFather会给你一段消息其中最关键的信息就是HTTP API访问令牌格式类似1234567890:ABCDEFGhijklmnOpqrstUvWxyz-abcdeF。务必妥善保存这个令牌它相当于你机器人的密码。3.3 配置并运行本地网关 (listen.js)网关是本地服务我们先让它跑起来。进入脚本目录并启动它cd ~/.gemini/scripts node listen.js如果一切正常终端会输出类似Listener started on port 8765的信息表示一个HTTP服务已经在你的127.0.0.1:8765地址上运行。你可以打开另一个终端用curl快速测试一下curl -X POST http://127.0.0.1:8765/health -H Content-Type: application/json -d {}应该会收到一个{status:ok}的响应。这意味着网关服务是健康的并且可以接受事件。关键配置点YOLO模式与安全性。如前所述listen.js默认以YOLO模式调用gemini_cli。你可以查看listen.js的源码通常在调用child_process.spawn的地方能看到--yolo参数。如果你希望在某些高风险操作前进行确认可以修改此脚本移除--yolo标志。但请注意这需要gemini_cli能与用户交互而在无头的服务器或后台运行场景下这可能造成进程挂起。一个折中的安全实践是在gemini_cli自身的配置中精细地控制哪些命令或操作范围允许在YOLO模式下执行而不是完全依赖或禁用这个网关层的标志。3.4 配置并运行Telegram机器人 (main.go)机器人程序需要知道两件事如何联系Telegram以及如何联系你的本地网关。配置环境变量进入telegram_bot目录复制环境变量示例文件并编辑cd /path/to/gemini_cli_server/telegram_bot cp .env.example .env # 使用你喜欢的编辑器如nano, vim编辑 .env 文件 nano .env填写关键配置.env文件内容如下你需要填入自己的信息TELEGRAM_BOT_TOKEN你的BotFather给的令牌 GEMINI_ENDPOINThttp://127.0.0.1:8765/event TARGET_CHAT_IDTELEGRAM_BOT_TOKEN填入上一步获取的令牌。GEMINI_ENDPOINT这是连接main.go和listen.js的桥梁。目前我们填的是本地地址这意味着main.go和listen.js必须在同一台机器上运行。如果你想将listen.js部署在另一台服务器或者需要从公网访问下一步会讲到就需要修改这个地址。TARGET_CHAT_ID一个重要的安全选项。如果留空任何知道你的机器人用户名的人都可以给它发消息并触发你的gemini_cli。强烈建议你填写这个ID将机器人锁定为只响应你或你所在群组的消息。如何获取Chat ID最简单的方法是先不填这个字段启动机器人后向它发送一条消息如/start然后立刻查看运行main.go的终端日志通常它会打印出收到消息的Chat ID。将这个ID填入.env文件然后重启机器人即可。安装依赖并运行在telegram_bot目录下运行以下命令go mod tidy # 下载Go模块依赖 go run main.go如果看到Authorized on account ...或Bot started...之类的日志说明你的机器人已经上线并开始轮询Telegram消息了。3.5 实现公网访问使用Ngrok穿透内网到目前为止你的机器人和网关都在本地网络运行。但Telegram的服务器在互联网上它无法直接访问你电脑localhost:8765的服务。为了让main.go无论它运行在哪里能访问到listen.js我们需要一个公网地址。Ngrok是一个极佳的内网穿透工具。安装并启动Ngrok前往 ngrok官网 注册并获取你的Authtoken。按照指引安装客户端然后运行ngrok config add-authtoken 你的token ngrok http 8765获取公网URL命令执行后Ngrok会分配一个随机的公网地址如https://a1b2c3d4.ngrok-free.app并转发所有到该地址的请求到你本地的8765端口。在终端输出中找到Forwarding这一行复制这个HTTPS URL。更新端点配置将telegram_bot/.env文件中的GEMINI_ENDPOINT修改为你的Ngrok地址/event。例如GEMINI_ENDPOINThttps://a1b2c3d4.ngrok-free.app/event重启服务重启你的main.go机器人程序让它读取新的端点配置。现在整个链路就通了Telegram消息 - Telegram服务器 - 你的main.go可能运行在VPS上 - Ngrok公网地址 - 你的本地listen.js-gemini_cli。实操心得Ngrok的免费版URL每次启动都会变化不适合生产环境。对于长期使用你有几个选择1) 升级Ngrok付费计划以获得固定域名2) 使用云服务器反向代理如Caddy, Nginx3) 将listen.js直接部署在具有公网IP的云服务器上并配置域名和SSL证书。这样GEMINI_ENDPOINT就可以指向一个固定的、安全的地址。4. 核心功能使用与命令解析部署完成后你的Telegram机器人就具备了基础通信能力。但如何管理这个“网关”服务本身呢项目通过一套巧妙的动态命令注册机制提供了丰富的管理功能。4.1 动态命令系统的工作原理main.go在启动时会扫描~/.gemini/commands/listen/目录下的所有.toml文件。每个.toml文件对应一个Telegram Bot命令。文件名决定了命令名文件内容中的description字段则作为该命令的描述会显示在Telegram的Bot命令菜单中。例如存在一个~/.gemini/commands/listen/status.toml文件内容为description 检查监听器的当前运行状态那么当你在Telegram中向Bot输入/时命令列表里就会出现/listen_status并且旁边会显示“检查监听器的当前运行状态”这个描述。这种设计将命令的定义与Bot的代码解耦添加新命令只需要新建一个.toml文件并重启Bot无需修改Go代码。4.2 内置管理命令详解项目预置了一系列管理命令它们是你运维这个集成服务的工具箱。所有命令均以/listen_为前缀。/listen_start启动listen.js网关服务。Bot会向配置的GEMINI_ENDPOINT发送一个特定指令触发网关在后台启动并监听8765端口。注意这要求运行Bot的机器能通过SSH或类似方式在目标机器上启动进程。对于简单的本地部署你可能更倾向于手动在终端启动node listen.js并保持其运行。/listen_status查询网关服务的当前状态是否正在运行。这是最常用的检查命令。/listen_stop停止正在运行的网关服务。用于安全关闭服务。/listen_logs获取网关服务的最新日志。这对于调试至关重要当Bot没有响应时首先查看日志可以知道是网关没收到请求还是gemini_cli执行出错了。/listen_health对网关服务进行一次健康检查。它会发送一个简单的请求到/health端点确认服务是否可访问且功能正常。/listen_help显示当前所有可用的/listen_命令及其描述相当于一个内置的使用手册。/listen_clear清除网关服务的日志缓冲区。在长时间运行后清理日志有助于聚焦新问题。/listen_live这是一个有趣的功能它尝试将网关的实时日志流推送到你运行gemini_cli的本地终端。这对于深度调试非常有用但实现上可能依赖于特定的进程间通信设置。如何使用这些命令非常简单。在Telegram中打开与你的Bot的聊天窗口输入/Telegram客户端会自动列出所有可用命令。选择例如/listen_status发送即可。Bot会调用对应的接口并将网关返回的状态信息回复给你。4.3 与AI助手进行自然对话除了管理命令机器人的核心功能是处理自由格式的自然语言消息。任何不是以/listen_开头的消息都会被Bot视为要转发给gemini_cli的指令。例如你可以直接发送“查看一下当前系统的内存使用情况。”“帮我写一个Python函数用来递归遍历目录并计算文件总数。”“连接到我的Postgres数据库查询用户表的前10条记录。”这需要你的gemini_cli已配置相应的MCP服务器“执行部署脚本deploy.sh。”Bot会将这些文本原样转发给listen.js进而交给gemini_cli处理并将最终的结果返回。你体验到的就像是在和一个全能的、能操作你整个开发环境的AI助手直接对话。5. 高级配置、安全加固与故障排查将本地命令行AI能力暴露到聊天工具中带来了极大的便利也引入了安全和稳定性的考量。下面是一些进阶的配置技巧和问题排查指南。5.1 安全加固最佳实践强制使用TARGET_CHAT_ID这是第一道也是最重要的防线。务必在.env文件中设置这个值将机器人变成你的私人助手避免被他人滥用。使用Ngrok的认证功能付费版免费的Ngrok隧道是公开的任何人拿到你的URL都可以发送请求。Ngrok付费版支持为隧道添加基本的HTTP认证用户名/密码或者设置IP白名单。在ngrok启动命令中配置这些选项可以防止未授权的请求到达你的listen.js。在listen.js中增加请求验证你可以修改listen.js的源码在接收到请求时检查HTTP头中是否包含一个你预设的密钥Secret Token。然后在main.go发送请求时将这个密钥添加到请求头中。这为通信增加了一层简单的API密钥认证。listen.js端检查req.headers[x-auth-token]是否等于你设定的值。main.go端在发送HTTP请求时设置Headerreq.Header.Set(X-Auth-Token, your-secret-token-here)。精细化控制gemini_cli的权限在~/.gemini的配置中利用gemini_cli的沙箱或权限控制功能限制它在YOLO模式下可以执行的命令范围。例如禁止执行rm -rf /或dd这类高危命令。将AI的操作范围锁定在必要的、安全的领域内。使用HTTPS确保你的公网端点无论是Ngrok付费域名还是自己的服务器启用HTTPS。这可以加密传输过程中的数据防止中间人攻击。Ngrok免费版默认提供HTTPS。5.2 性能优化与稳定运行将服务进程化在本地开发时用node listen.js和go run main.go没问题但对于长期运行你需要使用进程管理工具。对于listen.js(Node.js)推荐使用pm2。npm install -g pm2后用pm2 start listen.js --name gemini-gateway启动并设置开机自启pm2 startup pm2 save。对于main.go(Go)可以先编译成二进制go build -o telegram-bot main.go然后同样用pm2管理pm2 start ./telegram-bot --name telegram-bot。或者使用系统的systemd服务。处理gemini_cli超时有些AI任务可能耗时较长如分析大量代码。listen.js中调用gemini_cli的默认超时时间可能不够。你需要查看并修改listen.js源码中关于child_process执行的超时设置或者确保gemini_cli本身有流式输出能力避免因超时导致进程被杀死请求无响应。日志与监控除了使用/listen_logs命令建议将listen.js和main.go的日志输出到文件并配合logrotate进行管理。对于关键的生产使用可以增加简单的监控比如定时调用/listen_health接口失败时发送告警通知。5.3 常见问题与排查清单当你遇到机器人不响应的问题时可以按照以下清单自上而下进行排查问题现象可能原因排查步骤Bot对任何消息都无回复1.main.go程序未运行或已崩溃。2.TELEGRAM_BOT_TOKEN错误或失效。1. 检查运行main.go的终端或进程管理器如pm2查看是否有错误日志。2. 尝试在BotFather处使用/revoke命令撤销旧令牌生成新令牌并更新.env文件。Bot只对/listen_*命令有回复对普通消息无回复1.listen.js网关未运行。2.GEMINI_ENDPOINT配置错误或网络不通。3. Ngrok隧道断开如果使用了Ngrok。1. 执行/listen_status检查网关状态。2. 在运行main.go的机器上用curl手动测试GEMINI_ENDPOINT的/health接口。3. 检查Ngrok终端或控制台确认隧道状态为online。重启Ngrok。Bot回复“超时”或“网关错误”1.listen.js调用gemini_cli进程超时。2.gemini_cli本身执行出错或卡死。1. 使用/listen_logs查看网关详细错误信息。2. 检查gemini_cli是否能在本地终端正常运行。尝试在listen.js所在环境手动执行gemini_cli命令看是否有环境变量或路径问题。Ngrok地址频繁变更使用的是Ngrok免费计划。考虑升级Ngrok付费计划以获得固定域名或改用云服务器部署并配置动态DNS。执行涉及MCP服务器的命令失败1.gemini_cli未正确配置MCP服务器。2. MCP服务器本身未运行或认证失败。1. 在本地终端直接使用gemini_cli测试相同的指令确认MCP功能正常。2. 检查gemini_cli的配置文件确保MCP服务器连接信息正确。查看MCP服务器的日志。一个实用的调试技巧在main.go的源码中找到发送HTTP请求到GEMINI_ENDPOINT的代码段附近添加一行日志打印输出它发送的完整请求URL和体。同样在listen.js中记录它收到的请求和调用gemini_cli的具体命令。这些日志能帮你精准定位通信链路中哪一环出现了问题。6. 扩展与自定义打造你的专属工作流这个项目的动态命令机制和基于HTTP的架构为自定义扩展打开了大门。你可以让它不仅仅是gemini_cli的转发器更能融入你的个性化工作流。6.1 添加自定义Telegram Bot命令假设你想添加一个命令/listen_deploy用于触发一个特定的部署流程。创建命令定义文件# 在 ~/.gemini/commands/listen/ 目录下 nano ~/.gemini/commands/listen/deploy.toml编辑文件内容description 触发生产环境部署流程在listen.js中实现处理逻辑/listen_命令最终会被映射到listen.js中特定的处理函数。你需要编辑listen.js添加一个处理deploy命令的路由或条件判断。例如当收到command为deploy的请求时不直接调用gemini_cli而是执行一个你预先写好的部署脚本deploy.sh。// 在 listen.js 的请求处理部分添加 if (command deploy) { // 执行你的自定义脚本 const { exec } require(child_process); exec(/path/to/your/deploy.sh, (error, stdout, stderr) { // 将结果返回给 Telegram Bot }); return; }重启服务重启main.go机器人程序让它重新扫描命令目录。现在在Telegram中输入/你应该能看到新的/listen_deploy命令了。6.2 集成其他自动化工具listen.js作为一个HTTP网关理论上可以触发任何本地操作。你可以扩展它使其成为你智能家居、CI/CD管道、数据备份等任务的统一聊天界面触发点。例如你可以修改listen.js让它根据收到的特定关键词去调用Home Assistant的API来开关灯或者调用Jenkins API来触发一个构建任务。关键在于将Telegram消息中的指令映射到你想要执行的具体动作上。6.3 关于直接外部测试的说明项目文档最后提到如果你用Ngrok暴露了端口可以直接用curl测试监听器。这是一个非常有效的集成测试方法它绕过了Telegram Bot直接验证listen.js到gemini_cli的链路是否通畅。curl -X POST https://your-ngrok.ngrok-free.app/event \ -H Content-Type: application/json \ -d { source: curl_test, message: 请用一句简短的话证明你是Gemini CLI并附上一句给测试者的俳句。 }如果这个命令能收到gemini_cli风格的诗意回复那么整个后端链路就是健康的问题很可能出在main.go与Telegram的通信上。这种分层测试的思路在调试分布式系统时非常有用。这个项目巧妙地利用了两个轻量级服务将强大的本地AI命令行工具变成了一个可移动、可对话的智能伴侣。从安全配置到故障排查再到深度自定义整个过程就像在搭建一个属于你自己的数字神经系统。最让我满意的是它没有破坏原有工具 (gemini_cli) 的生态而是以一种“非侵入式”的方式扩展了它的边界。如果你也厌倦了在终端和聊天应用之间反复切换不妨花点时间部署一下这种“一句话搞定”的流畅感确实能显著提升那些碎片化时间里的工作效率。