首页
/ gemini-cli 扩展发布指南:Git 仓库与 GitHub Releases 双通道的发布、更新与迁移实践

gemini-cli 扩展发布指南:Git 仓库与 GitHub Releases 双通道的发布、更新与迁移实践

2026-09-04 15:11:28作者:卓炯娓

本文基于 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 或邮件申请。要让你的扩展被自动发现并列出,需要同时满足三个条件:

  1. 使用公开仓库:扩展必须托管在一个公开的 GitHub 仓库中;
  2. 添加 GitHub topic:在仓库的 About 部分添加 gemini-cli-extension topic,官方爬虫依据该 topic 发现新扩展;
  3. 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 管理不同的发布通道,例如 stablepreviewdev。文档给出的推荐实践:

  • 默认分支作为 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。

更新判断本身也很直接:checkForExtensionUpdategithub-release 类型只比较 releaseData.tag_name 与本地元数据中记录的 releaseTag 是否一致,不一致即判定 UPDATE_AVAILABLE

自定义预构建归档(Custom Pre-built Archives)

你可以直接把自定义归档作为资产(asset)附加到 GitHub Release 上。当扩展需要构建步骤或包含平台相关二进制时,这是唯一途径。要求:

  • 归档必须完全自包含(fully self-contained);
  • 遵循下文"归档结构";
  • 若扩展平台无关,提供一个通用(generic)资产即可。

平台相关归档的命名约定

为了让 Gemini CLI 找到对应当前用户平台的资产,按以下优先级命名:

  1. 平台 + 架构{platform}.{arch}.{name}.{extension}
  2. 仅平台{platform}.{name}.{extension}
  3. 通用(generic):找不到特定匹配时,单个资产作为兜底。

占位符取值:

占位符 取值
{name} 扩展名
{platform} darwin(macOS)、linuxwin32(Windows)
{arch} x64arm64
{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.gz
  • win32.my-tool.zip

这个命名约定并非靠字符串解析约定俗成,而是有明确的源码实现:findReleaseAsset 依次用 os.platform()os.arch() 构造前缀(如 darwin.arm64.linux.),在资产名(转小写后)中做前缀匹配;若资产总数恰好为一个,且名称中不含任何平台字样(darwin/linux/win32),则作为 generic 资产兜底。

下载解压阶段由 downloadFromGitHubRelease 完成:优先使用自定义资产,否则回退到 GitHub 自动生成的 tarball_url/zipball_url;支持 .tar.gz.zip 两种格式(分别用 tarextract-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。操作步骤:

  1. 创建新仓库:把扩展在新位置搭建好;
  2. 更新旧仓库:修改 gemini-extension.json,加入指向新仓库 URL 的 migratedTo,并递增版本号:
{
  "name": "my-extension",
  "version": "1.1.0",
  "migratedTo": "https://github.com/new-owner/new-extension-repo"
}
  1. 发布更新:在旧仓库发布这个新版本。

之后,当用户检查更新时,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 类型重新加载源目录配置比较 versiongit 类型通过 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.tsupdate.ts 中的检测与回滚实现后,你就能针对每种通道设计出可验证、可回滚的扩展发布流水线。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
527
590
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
904
1.82 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
889
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.52 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
981
502
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384