首页
/ Gemini CLI 贡献指南:从 CLA 到 preflight 全流程,构建、测试与沙箱开发环境实战

Gemini CLI 贡献指南:从 CLA 到 preflight 全流程,构建、测试与沙箱开发环境实战

2026-09-06 16:34:54作者:翟江哲Frasier

本文以 Gemini CLI 仓库的 CONTRIBUTING.md 为主体,系统讲解向该项目贡献代码与文档的完整流程:签署 CLA、寻找可认领的 Issue、遵循 Pull Request 规范,并深入拆解开发环境的搭建方式——包括 npm run build 构建流程、npm run preflight 质量门禁背后的每一步检查、review.sh 自动评审工具、VS Code 调试与 React DevTools 调试,以及 macOS Seatbelt 与容器化沙箱两套隔离方案的配置细节。读完本文,你可以独立完成一次从克隆仓库到提交 PR 的完整贡献,并理解项目各条 npm 脚本命令的真实实现。

贡献前的两项准备

签署 Contributor License Agreement

任何贡献都必须附带 Google 的 CLA(Contributor License Agreement)。作者(或其雇主)保留对贡献的版权,CLA 只是授予项目使用和再分发贡献的许可。如果你或你当前的雇主已经签署过 Google CLA(哪怕是针对其他项目的),通常无需重复签署。你可以在 Google CLA 页面(cla.developers.google.com)查看当前协议状态或签署新的协议。

遵守社区行为准则

项目遵循 Google 开源社区行为准则(Google Open Source Community Guidelines),所有 issue 讨论、PR 评审都应在此框架内进行。

代码贡献流程

五步贡献流程

  1. 找一个 Issue:被标记为 🔒Maintainers only 的 Issue 仅保留给项目维护者,不会接受相关 PR。对于认为适合社区贡献的 Issue,可以在 Issue 下留言,由维护者评估后打上 help-wanted 标签(只有维护者可以添加该标签)。
  2. Fork 仓库并创建新分支
  3. packages/ 目录中完成修改:所有产品代码都位于 packages/ 下的多个工作区包中(clicoresdkdevtoolsa2a-servervscode-ide-companiontest-utils 等),这一点可以从 package.json 中的 "workspaces": ["packages/*"] 得到印证。
  4. 确保所有检查通过:运行 npm run preflight
  5. 提交 Pull Request

自动评审工具

项目提供了自动评审工具,帮助检测常见反模式、测试缺失等容易遗漏的问题。所有提交(包括项目成员自己)都必须经过 PR 评审,自动评审用于辅助而非替代人工评审。有两种运行方式:

方式一:使用辅助脚本(推荐)

./scripts/review.sh <PR_NUMBER> [model]

该脚本会自动完成:把 PR checkout 到独立 worktree、安装依赖、构建项目、启动评审工具。从 scripts/review.sh 的源码可以看到,脚本要求预先在 ~/git/review/gemini-cli 目录有一份仓库克隆,会先用 gh pr view 校验 PR 是否存在,然后打开 PR 页面供人工核对。脚本有两点重要提醒:

  • 警告:运行 review.sh 前,必须人工确认被评审 PR 的代码可以安全执行、不包含数据外泄攻击。
  • 强烈建议 PR 作者在自己 PR 创建后立即运行此脚本,在维护者完整评审前先本地发现并修复简单问题。

模型选择:脚本默认使用最新的 Pro 模型(gemini-3.1-pro-preview,这一点在 scripts/review.sh 中可见 model="${2:-gemini-3.1-pro-preview}")。如果 Pro 配额不足,可以用 Flash 模型运行:

./scripts/review.sh <PR_NUMBER> gemini-3-flash-preview

方式二:在 Gemini CLI 中手动运行

如果 PR 代码已经在本地 checkout 并构建完成,可以直接在 CLI 提示符中执行:

/review-frontend <PR_NUMBER>

Issue 的自我认领与取消认领

  • 在 Issue 下评论 /assign 即可认领;评论 /unassign 取消认领。评论内容必须只有这一行文字,不能包含其他内容。
  • 同时最多只能认领 3 个 Issue;只有打了 help wanted 标签的 Issue 才允许自我认领;Issue 必须处于未认领状态才能被认领。

Pull Request 六项规范

不满足这些标准的 PR 可能会被直接关闭。

1. 必须关联已有 Issue 所有 PR 都要关联 Issue 跟踪系统中的一个已有 Issue,确保每个变更在写代码前已被讨论并与项目目标对齐:Bug 修复关联对应的 bug 报告;新功能关联经维护者批准的提案 Issue。如果不存在对应 Issue,PR 会被自动关闭并附上提醒评论。正确的工作流是先开 Issue 等待反馈,再开始编码

2. 保持小而聚焦 偏好小颗粒、原子的 PR,一个 PR 只解决一个 Issue 或添加一个自包含的功能。不要在一个 PR 里混入 Bug 修复、新功能和重构。大改动应拆成一系列可以独立评审、独立合并的小 PR。

3. 用 Draft PR 获取早期反馈 尚未完工的工作请使用 GitHub 的 Draft Pull Request 功能,向维护者表明 PR 还未进入正式评审、仅开放讨论。

4. 确保所有检查通过 提交前运行 npm run preflight,它会执行全部测试、lint 和其他风格检查(下节详解)。

5. 更新文档 如果 PR 引入了面向用户的变更(新命令、修改的 flag、行为变化),必须同步更新 /docs 目录下的相关文档。

6. 写清晰的 commit message 和 PR 描述 commit message 遵循 Conventional Commits 标准。示例:

  • 好的 PR 标题:feat(cli): Add --json flag to 'config get' command
  • 坏的 PR 标题:Made some changes

PR 描述中要解释变更的"为什么",并链接相关 Issue(如 Fixes #123)。

Fork 后的 CI 配置

Fork 仓库后可以运行 Build、Test 和 Integration test 工作流,但要让集成测试跑起来,需要在自己的 fork 中添加名为 GEMINI_API_KEY 的 GitHub Repository Secret,值设为一个有效的 API key。该密钥仅对你的仓库私有。此外,还需到仓库的 Actions 标签页手动启用工作流(页面中央的大蓝色按钮)。

开发环境搭建与工作流

前置条件

  1. Node.js
    • 开发环境请使用 Node.js ~20.19.0,因为上游开发依赖的兼容性问题需要锁定该版本(可用 nvm 管理);
    • 生产环境运行 CLI 则任意 >=20 的版本都可以。package.json 中声明的 "engines": { "node": ">=20.0.0" } 正对应这一生产要求。
  2. Git

克隆与构建

git clone https://github.com/google-gemini/gemini-cli.git # 或你的 fork 地址
cd gemini-cli

安装依赖(包括 package.json 中定义的工作区依赖与根依赖):

npm install

构建整个项目(所有包):

npm run build

该命令通常会把 TypeScript 编译为 JavaScript、打包资源并准备各包的可执行产物。在 package.json 中可以看到 "build": "node scripts/build.js",对应实现是 scripts/build.js,构建细节可参考它和 package.json 的 scripts 字段。

启用沙箱构建

CONTRIBUTING.md 强烈建议开发者启用沙箱(Sandbox),最低要求是在 ~/.env 中设置 GEMINI_SANDBOX=true 并确保有可用的沙箱提供方(macOS Seatbelt、docker 或 podman)。要同时构建 gemini CLI 和沙箱容器,在仓库根目录运行:

npm run build:all

如果想跳过沙箱容器的构建,用 npm run build 即可。从 package.json 可确认 build:all 的完整语义:

"build:all": "npm run build && npm run build:sandbox && npm run build:vscode",
"build:sandbox": "node scripts/build_sandbox.js",

即依次执行主构建、沙箱镜像构建(scripts/build_sandbox.js)以及 VS Code 伴侣扩展构建。

运行 CLI

构建后从源码启动 Gemini CLI:

npm start

对应实现为 cross-env NODE_ENV=development node scripts/start.js(见 scripts/start.js)。如果想在 gemini-cli 目录之外运行源码构建,可以:

npm link path/to/gemini-cli/packages/cli
# 或者
alias gemini="node path/to/gemini-cli/packages/cli"

运行测试

项目包含两类测试:单元测试与集成测试。

单元测试

npm run test

覆盖 packages/corepackages/cli 的测试套件。从 package.json 可以看到它实际上是 "test": "npm run test --workspaces --if-present && npm run test:sea-launch",即在所有工作区运行各自存在的测试,外加 sea/sea-launch.test.js;并且还有 "posttest": "npm run build" 钩子。提交任何变更前都应确保测试通过,更彻底的检查是 npm run preflight

集成测试

集成测试用于验证端到端功能,包含在默认的 npm run test 中:

npm run test:e2e

package.json 显示其定义为 cross-env VERBOSE=true KEEP_OUTPUT=true npm run test:integration:sandbox:none,即不带沙箱(GEMINI_SANDBOX=false)地运行 integration-tests/ 目录下的 vitest 套件。仓库还提供了 test:integration:sandbox:dockertest:integration:sandbox:podman 等变体。集成测试框架的详细说明见 docs/integration-tests.md——该文档指出,运行集成测试前需要先执行 npm run bundle 生成被测试的 release bundle,且每次修改 CLI 源码后都要重新 bundle。

Lint 与 preflight 检查

npm run preflight 是提交前的总闸门。对照 package.json 的定义:

"preflight": "npm run clean && npm ci && npm run format && npm run build && npm run lint:ci && npm run typecheck && npm run test:ci"

即依次执行:清理(scripts/clean.js)、npm ci 全新安装、Prettier 格式化、全量构建、CI 模式 lint(scripts/lint.jslint:all)、TypeScript 类型检查(各工作区 typecheck 加上 evals / integration-tests / memory-tests 的 tsc -b),以及 test:ci(各工作区 CI 测试 + 脚本测试 + SEA 启动测试)。

ProTip:克隆后创建 git pre-commit 钩子,保证每次提交都是干净的:

echo "
# Run npm build and check for errors
if ! npm run preflight; then
  echo \"npm build failed. Commit aborted.\"
  exit 1
fi
" > .git/hooks/pre-commit && chmod +x .git/hooks/pre-commit

也可以单独执行:

  • 格式化:npm run format(Prettier 按项目风格格式化全部文件,含 Markdown);
  • Lint:npm run lint(ESLint,--max-warnings 0 零警告策略);
  • 自动修复:npm run lint:fix

另外 package.json 还配置了 husky + lint-staged 的提交时检查:暂存的 *.{js,jsx,ts,tsx} 会被 Prettier 格式化并经 ESLint --fix 修正,*.{json,md} 会被 Prettier 格式化。

编码规范

  • 遵循现有代码库的风格、模式和约定;
  • 阅读 GEMINI.md(项目根目录),其中包含 AI 辅助开发的具体约定,包括 React、注释和 Git 使用规范;
  • 特别注意导入路径:项目用 ESLint 强制限制跨包的相对导入(eslint.config.js),应使用包名而非跨包相对路径。

调试

VS Code:在根目录运行

npm run debug

该命令是 cross-env DEBUG=1 node --inspect-brk scripts/start.js,会暂停执行直到调试器附着,此时可以用 Chrome 打开 chrome://inspect 连接调试器。也可以直接使用 .vscode/launch.json 中的 "Attach" 启动配置,或者 "Launch Program" 配置直接启动当前打开的文件,但一般推荐用 F5 对应的主配置("Build & Launch CLI" 会先执行 npm run build-and-start,并在 env 中默认关闭 GEMINI_SANDBOX 以便断点生效)。

要在沙箱容器内命中断点,运行:

DEBUG=1 gemini

注意:如果项目的 .env 文件里有 DEBUG=true,由于自动排除机制,它不会影响 gemini-cli;给 gemini-cli 专用的调试设置请写入 .gemini/.env

React DevTools:CLI 的界面基于 React(Ink)构建,可以用 React DevTools 调试:

  1. 以开发模式启动 CLI:

    DEV=true npm start
    
  2. 安装并运行与 CLI 的 react-devtools-core 版本(6.x,见 package.jsonreact-devtools-core: 6.1.2)匹配的 React DevTools 6:

    npm install -g react-devtools@6
    react-devtools
    # 或者
    npx react-devtools@6
    

    运行中的 CLI 会自动连接 React DevTools:

Gemini CLI 连接到 React DevTools 的界面

沙箱机制详解

macOS Seatbelt

在 macOS 上,gemini 使用 Seatbelt(sandbox-exec)加载 permissive-open 策略(packages/cli/src/utils/sandbox-macos-permissive-open.sb)。从该策略文件源码看,它以 (deny default) 拒绝默认操作,显式允许从宿主机任意位置读文件((allow file-read*))、进程 exec/fork(子进程继承策略从而保持被沙箱化)、向自身发信号(如写关闭管道时的 SIGPIPE)以及读取有限的 sysctl 信息,写入则被限制在项目文件夹内,同时默认放行广泛的文件读取与出站网络("open")。

可以通过设置 SEATBELT_PROFILE=strict-open(写入环境或 .env)切换到 strict-open 策略(packages/cli/src/utils/sandbox-macos-strict-open.sb),它把读取和写入都限制在工作目录内,但默认仍放行出站网络。内置的全部策略档位为 permissive-{open,proxied}restrictive-{open,proxied}strict-{open,proxied}(对应 packages/cli/src/utils/ 下的六个 .sb 文件)。也可以自定义策略:设置 SEATBELT_PROFILE=<profile> 并在项目设置目录 .gemini 下创建 .gemini/sandbox-macos-<profile>.sb

容器化沙箱(全平台)

在 macOS 或其他平台上想要更强的容器级隔离,可以在环境或 .env 中设置:

GEMINI_SANDBOX=true|docker|podman|<command>

指定的命令(true 时为 dockerpodman 之一)必须已安装在宿主机上。启用后,npm run build:all 会构建一个最小的沙箱容器镜像,npm start 会启动该镜像的一个全新实例;首次构建约需 20–30 秒(主要是拉取基础镜像),之后构建和启动的开销都很小。默认构建(npm run build)不会重建沙箱镜像。

容器沙箱会以读写方式挂载项目目录(以及系统临时目录),并随 Gemini CLI 的启动/停止自动启动/停止/移除。沙箱内创建的文件会自动映射到宿主机的用户/组。通过 SANDBOX_{MOUNTS,PORTS,ENV} 可以额外指定挂载、端口和环境变量。还可以为项目完全定制沙箱:在 .gemini 下创建 .gemini/sandbox.Dockerfile 和/或 .gemini/sandbox.bashrc,然后以 BUILD_SANDBOX=1 运行 gemini 触发定制沙箱的构建。

代理网络(Proxied networking)

所有沙箱方式(包括使用 *-proxied 策略的 macOS Seatbelt)都支持通过自定义代理服务器限制出站网络流量,用 GEMINI_SANDBOX_PROXY_COMMAND=<command> 指定。<command> 必须启动一个监听 :::8877 的代理服务器。仓库提供了最小示例:docs/examples/proxy-script.md 中的代理只放行到 example.com:443 的 HTTPS 连接(例如 curl https://example.com),拒绝所有其他请求。代理会随沙箱自动启动和停止。

手动发布

项目会为每个提交向内部 registry 发布产物。如果确实需要手动切一个本地构建:

npm run clean
npm install
npm run auth
npm run prerelease:dev
npm publish --workspaces

其中 npm run authpackage.json 中定义为 npm run auth:npm && npm run auth:docker,即依次执行 npx google-artifactregistry-authgcloud auth configure-docker us-west1-docker.pkg.dev,分别完成 Artifact Registry 与 Docker 的发布认证。

文档贡献流程

项目要求文档与代码贡献保持同步,追求清晰、准确、完整,并尽量提供实用示例。

文档贡献五步

  1. Fork 仓库并创建新分支;

  2. /docs 目录中完成修改;

  3. 本地预览 Markdown 渲染效果;

  4. Lint 并格式化改动——preflight 检查已包含对文档文件的检查:

    npm run preflight
    
  5. 提交 Pull Request。

文档组织结构

文档以 docs/sidebar.json 作为目录(table of contents)。从该文件源码可以看到,每个条目由 label(显示名)和 slug(对应文档路径,如 docs/get-started/installation)构成,并按 "Get started"、"Use Gemini CLI" 等分组嵌套。新增文档时:

  1. 把 Markdown 文件创建在 /docs 下的合适目录中;
  2. sidebar.json 的相应分组中添加条目;
  3. 确保所有内部链接使用相对路径且指向真实存在的文件。

写作风格

项目遵循 Google Developer Documentation Style Guide。关键要点:

  • 标题使用 sentence case(句首大写);
  • 用第二人称("you")称呼读者;
  • 使用现在时;
  • 段落短小、聚焦;
  • 代码块使用正确的语言标签以启用语法高亮;
  • 尽可能附上实用示例。

文档 Lint 与格式化

项目用 Prettier 保持文档风格一致,npm run preflight 会检查 lint 问题。也可以单独运行:

  • npm run lint —— 检查 lint 问题;
  • npm run format —— 自动格式化 Markdown 文件;
  • npm run lint:fix —— 尽可能自动修复 lint 问题。

提交文档 PR 前请确保没有 lint 错误。

提交前自查清单

  1. 运行 npm run preflight 确保所有检查通过;
  2. 复查改动的清晰度与准确性;
  3. 确认所有链接可正确访问;
  4. 确保代码示例经过测试、确实可用;
  5. 如果尚未签署,请签署 CLA。

如果文档贡献过程中遇到问题:可以查看现有文档找范例、在仓库 Issue 中先讨论拟议的改动、或直接联系维护者。项目欢迎每一份让文档变得更好的贡献。

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