gemini-cli 扩展发布指南:Git 仓库与 GitHub Releases 双通道的发布、更新与迁移实践
本文基于 gemini-cli 官方文档 releasing.md 整理,系统讲解如何将自研扩展发布给终端用户:通过 Git 仓库或 GitHub Releases 两种分发通道交付扩展、让扩展被官方画廊自动收录、用分支/Tag 管理 stable/preview/dev 发布通道、利用 migratedTo 字段完成仓库迁移,并深入源码剖析每种安装方式背后的更新检测机制。读完后你将能够独立完成一个可扩展、可更新、可迁移的 gemini-cli 扩展发布流程。
两种发布方式:选型与取舍
Gemini CLI 扩展的官方分发路径有两条,文档给出的定位非常明确:
- Git 仓库发布:最简单、最灵活,天然支持用分支管理开发中的多个版本;
- GitHub Releases 发布:首次安装更高效(下载单个压缩包即可,无需完整
git clone),且是唯一能承载平台相关二进制文件(platform-specific binaries)的方式。
从源码结构看,这一"双通道"体现在安装元数据的类型划分上:inferInstallMetadata 会依据 source 参数前缀(http://、https://、git@、ssh://、github:、gitlab: 等)把安装源判定为 git 类型,本地路径则判定为 local 类型;而安装到 ~/.gemini/extensions/<name>/ 后,元数据文件 .gemini-extension-install.json 中记录的 type 字段还会出现第三种取值 github-release,即当 CLI 通过 GitHub Releases API 分发内容落盘时使用的类型。这三种类型正是后文更新检测机制分发的依据。
让扩展进入官方画廊(Extension Gallery)
Gemini CLI 的官方扩展画廊会自动索引公开扩展,无需提交 issue 或邮件申请。要让你的扩展被自动发现并列出,需要同时满足三个条件:
- 使用公开仓库:扩展必须托管在一个公开的 GitHub 仓库中;
- 添加 GitHub topic:在仓库的 About 部分添加
gemini-cli-extensiontopic,官方爬虫依据该 topic 发现新扩展; - manifest 位于仓库根目录:
gemini-extension.json文件必须位于仓库(或发布归档)的绝对根目录。
系统每天抓取(crawl)已打 Tag 的仓库。一旦仓库打 Tag,扩展在通过校验后就会出现在画廊中。
通过 Git 仓库发布
Git 发布是最灵活的方案:创建一个公开 Git 仓库,把 URL 交给用户即可。用户的安装命令为:
gemini extensions install <your-repo-uri>
安装命令的完整参数
从 install 命令定义 可以看到,install <source> [--auto-update] [--pre-release] 支持以下参数:
| 参数 | 类型 | 说明 |
|---|---|---|
source |
位置参数(必填) | 扩展的 GitHub URL 或本地路径 |
--ref |
string | 指定要安装的 git ref(分支、tag 或 commit) |
--auto-update |
boolean | 为该扩展启用自动更新 |
--pre-release |
boolean | 允许安装预发布版本(用于 GitHub Releases 通道) |
--consent |
boolean | 预先确认了解安装扩展的安全风险,跳过确认提示 |
--skip-settings |
boolean | 跳过安装过程中的配置项询问 |
用户也可以通过 --ref 依赖特定的分支、Tag 或 commit,例如固定安装 stable 分支:
gemini extensions install <your-repo-uri> --ref=stable
从源码看,cloneFromGit 的实现方式是:先以 --depth 1 浅克隆仓库,然后 git fetch 拉取 installMetadata.ref(缺省为 HEAD)并 checkout 到 FETCH_HEAD,形成 detached HEAD 状态。这解释了文档中的关键语义——HEAD(或指定 ref)对应的 commit 始终被视为最新版本:每当被引用分支上有新 commit 推送,CLI 就会提示用户更新安装。
用分支和 Tag 管理发布通道
你可以用分支或 tag 管理不同的发布通道,例如 stable、preview、dev。文档给出的推荐实践:
- 将默认分支作为 stable 通道——保证不带
--ref的默认安装命令总是得到最可靠的版本; - 用
dev分支承载活跃开发,待发布时再合并回默认分支。
通过 GitHub Releases 发布
将扩展通过 GitHub Releases 分发,可以跳过仓库克隆,显著加快安装速度。Gemini CLI 通过查询 GitHub 仓库的 Latest release 来检查更新;用户也可以用 --ref 参数配合 release tag 安装特定版本,并用 --pre-release 标志安装最新版本——即使该版本没有被标记为 Latest。
源码层面,fetchReleaseFromGithub 完整印证了这一逻辑:
- 指定了
ref时,查询https://api.github.com/repos/{owner}/{repo}/releases/tags/{ref}; - 未开启预发布时,直接取
releases/latest(GitHub 不允许 latest 为预发布版本,可以直接取用); - 若 latest 查询失败或开启了预发布,则回退到
releases?per_page=1取时间上最新的一条 release。
更新判断本身也很直接:checkForExtensionUpdate 对 github-release 类型只比较 releaseData.tag_name 与本地元数据中记录的 releaseTag 是否一致,不一致即判定 UPDATE_AVAILABLE。
自定义预构建归档(Custom Pre-built Archives)
你可以直接把自定义归档作为资产(asset)附加到 GitHub Release 上。当扩展需要构建步骤或包含平台相关二进制时,这是唯一途径。要求:
- 归档必须完全自包含(fully self-contained);
- 遵循下文"归档结构";
- 若扩展平台无关,提供一个通用(generic)资产即可。
平台相关归档的命名约定
为了让 Gemini CLI 找到对应当前用户平台的资产,按以下优先级命名:
- 平台 + 架构:
{platform}.{arch}.{name}.{extension} - 仅平台:
{platform}.{name}.{extension} - 通用(generic):找不到特定匹配时,单个资产作为兜底。
占位符取值:
| 占位符 | 取值 |
|---|---|
{name} |
扩展名 |
{platform} |
darwin(macOS)、linux、win32(Windows) |
{arch} |
x64 或 arm64 |
{extension} |
.tar.gz 或 .zip |
示例:
darwin.arm64.my-tool.tar.gz(Apple Silicon Mac 专属)darwin.my-tool.tar.gz(其他 Mac 的兜底,例如 Intel)linux.x64.my-tool.tar.gzwin32.my-tool.zip
这个命名约定并非靠字符串解析约定俗成,而是有明确的源码实现:findReleaseAsset 依次用 os.platform() 与 os.arch() 构造前缀(如 darwin.arm64.、linux.),在资产名(转小写后)中做前缀匹配;若资产总数恰好为一个,且名称中不含任何平台字样(darwin/linux/win32),则作为 generic 资产兜底。
下载解压阶段由 downloadFromGitHubRelease 完成:优先使用自定义资产,否则回退到 GitHub 自动生成的 tarball_url/zipball_url;支持 .tar.gz 与 .zip 两种格式(分别用 tar 与 extract-zip 解包);若解压后出现"顶层单一目录 + 归档文件"共 2 个条目的结构(典型 GitHub 源码归档形态),且该目录内含有 gemini-extension.json,会自动把目录内文件上移一层并移除该层目录,从而满足"gemini-extension.json 必须位于归档根部"的要求。
归档结构
归档必须是一个完整的、自包含的扩展:gemini-extension.json 必须位于归档根目录,其余布局遵循标准扩展结构即可。
GitHub Actions 发布工作流示例
文档提供了一个多平台构建与发布的完整示例:
name: Release Extension
on:
push:
tags:
- 'v*'
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Build extension
run: npm run build
- name: Create release assets
run: |
npm run package -- --platform=darwin --arch=arm64
npm run package -- --platform=linux --arch=x64
npm run package -- --platform=win32 --arch=x64
- name: Create GitHub Release
uses: softprops/action-gh-release@v1
with:
files: |
release/darwin.arm64.my-tool.tar.gz
release/linux.arm64.my-tool.tar.gz
release/win32.arm64.my-tool.zip
该工作流的要点:由 v* 前缀的 tag 推送触发;在 ubuntu-latest 上用 Node.js 20 执行依赖安装与构建;npm run package 按 --platform/--arch 组合产出符合上文命名约定的归档;最后用 softprops/action-gh-release 把资产挂到 GitHub Release 上。仓库中扩展模板工程(如 examples/mcp-server)展示了 gemini-extension.json + package.json 的标准组织方式,可作为构建脚本的参照。
迁移扩展仓库(migratedTo)
当你把扩展迁移到新仓库或重命名时,可以在旧仓库的 gemini-extension.json 中声明 migratedTo 字段,让用户无缝切换。该字段在扩展配置类型中的定义见 extension.ts。操作步骤:
- 创建新仓库:把扩展在新位置搭建好;
- 更新旧仓库:修改
gemini-extension.json,加入指向新仓库 URL 的migratedTo,并递增版本号:
{
"name": "my-extension",
"version": "1.1.0",
"migratedTo": "https://github.com/new-owner/new-extension-repo"
}
- 发布更新:在旧仓库发布这个新版本。
之后,当用户检查更新时,Gemini CLI 会检测 migratedTo 字段、校验新仓库、并把本地安装自动切换为跟踪新来源,所有配置自动迁移。
源码实现印证了"自动切换"的两个环节:
- 检测阶段:checkForExtensionUpdate 发现
extension.migratedTo后,会临时构造一个source指向新仓库的扩展对象进行递归检查;只要新来源返回"有更新"或"已是最新"(即新仓库是有效更新源),就整体判定为UPDATE_AVAILABLE; - 执行阶段:updateExtension 更新前若校验新来源有效,直接把
installMetadata.source改写为migratedTo再执行安装。此外 update.ts 还为更新过程提供了一致的保障:更新前做完整性校验(integrity check),失败或安装异常时回滚(rollback)到更新前的扩展副本。
重要提示:
migratedTo流程要求新仓库上至少已有一个 release,CLI 才会将其识别为有效更新源。
更新机制详解:CLI 如何知道"有新版本"
Gemini CLI 按安装方式采用不同策略检查扩展更新:
| 安装方式 | 检测手段 | 比较对象 |
|---|---|---|
| GitHub releases | 查询 GitHub API 获取最新 release tag | tag_name vs 本地记录的 releaseTag(忽略 manifest 中的 version 字段) |
| Git clones | 执行 git ls-remote |
远端 ref 的最新 commit hash vs 本地 HEAD |
| Local extensions | 读取源目录 manifest | 源目录的 version vs 已安装的 version |
这些策略在 checkForExtensionUpdate 中逐一分支实现:local 类型重新加载源目录配置比较 version;git 类型通过 git listRemote 取远端 hash 并与 git revparse HEAD 的本地 hash 比较;github-release 类型则走 GitHub API 的 tag 比较路径。
要确认某个扩展的安装类型,可以查看元数据文件 ~/.gemini/extensions/<name>/.gemini-extension-install.json 中的 type 字段。
保持 manifest 与 tag 同步
使用 GitHub releases 发布时,务必保证 gemini-extension.json 中的 version 与 GitHub release tag 一致。虽然 CLI 用 tag 做更新检测,但 UI 上显示的是 manifest version——两者不同步会造成用户困惑。
小结
gemini-cli 的扩展发布体系可以概括为:Git 仓库通道胜在灵活(分支即通道、--ref 即版本、ls-remote 即更新检测),GitHub Releases 通道胜在高效(单归档安装、tag 即版本、平台化资产命名);画廊收录靠公开仓库 + gemini-cli-extension topic + 根目录 manifest 三件套;仓库迁移靠 migratedTo 一键切换。理解了 github.ts 与 update.ts 中的检测与回滚实现后,你就能针对每种通道设计出可验证、可回滚的扩展发布流水线。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00