青蛙小白
博客 / 2025/11

Gemini CLI 的时光机与沙箱隔离:Checkpointing 和 Sandbox

2025/11/21 · — 字 · 阅读约 — 分钟 ·
目录

使用 Gemini CLI 进行 AI 辅助编程时,一直有个担心:万一 AI 改错了代码怎么办?特别是在让 AI 进行大规模重构时,虽然想让它大胆尝试,但又怕一不小心把项目搞乱。

好在 Gemini CLI 提供了两个核心安全特性来解决这个问题:

  • Checkpointing:自动保存项目状态,实现"时光倒流"般的撤销能力
  • Sandbox:隔离 AI 操作,限制其影响范围

本文将详细介绍这两个功能的配置和实战应用。

配置方式变更:Gemini CLI 0.17.0 版本调整了这两个功能的配置方式,移除了 --checkpointing--sandbox-image 命令行标志(实际上 --checkpointing 早在 v0.11.0 就已移除),改为更灵活的配置文件和环境变量方式。如果你之前使用过这些标志,本文会介绍新的配置方法。

Checkpointing 功能解析

Checkpointing 是 Gemini CLI 的核心安全特性之一,它能让你在 AI 修改文件前自动保存项目状态,实现"时光倒流"般的撤销能力。

如何启用

Checkpointing 默认是禁用的,需要通过 settings.json 配置文件启用:

{
  "general": {
    "checkpointing": {
      "enabled": true
    }
  }
}

注意:旧版本的 --checkpointing 命令行标志已在 v0.11.0 被移除。配置文件方式更加持久和统一,配置一次即可在所有会话中生效,也更适合团队协作。

工作原理

当我们批准 AI 的文件修改工具时,Checkpointing 会自动捕获三个关键点:

  1. Git 快照:完整的项目状态,存储在 ~/.gemini/history/<project_hash> 的影子仓库中
  2. 对话历史:与 AI 的完整对话记录
  3. 工具调用:正在执行的具体操作

所有数据都保存在本地,不会上传到云端。

检查点的存储结构

检查点文件名遵循特定格式:

2025-06-22T10-00-00_000Z-my-file.txt-write_file

格式解析:

  • 2025-06-22T10-00-00_000Z: 时间戳(ISO 8601 格式)
  • my-file.txt: 被修改的文件名
  • write_file: 执行的工具名称

使用 /restore 命令

列出所有检查点

/restore

输出示例:

Available checkpoints for project 'blogv3':

1. 2025-11-21T15-30-45_123Z-gemini-cli.md-write_file
   Modified: content/library/ide/gemini-cli.md
   Tool: write_file
   Time: 2 hours ago

2. 2025-11-21T15-28-12_456Z-settings.json-edit_file
   Modified: .gemini/settings.json
   Tool: edit_file
   Time: 2 hours ago

3. 2025-11-21T14-20-03_789Z-utils.py-write_file
   Modified: scripts/utils.py
   Tool: write_file
   Time: 3 hours ago

这会显示当前项目的所有保存点,按时间倒序排列。

恢复到特定检查点

/restore 2025-06-21T10-00-00_000Z-my-file.txt-write_file

执行后会发生什么:

  • 项目文件恢复到该检查点时的状态
  • 对话历史回滚到那个时间点
  • 原始的工具提示会重新出现在对话中

实战示例

1:撤销错误的代码重构

最近在重构一个数据处理函数时,我让 AI 优化性能。AI 的新实现确实更快,但在测试中发现它对空值的处理有问题:

# AI 修改后,运行测试失败
npm test
# Error: TypeError: Cannot read property 'length' of null

此时我不想手动对比代码差异,也不想用 git 回滚(因为想保留对话上下文继续调试)。直接使用:

/restore

选择对应的检查点:

/restore 2025-11-21T14-30-00_123Z-process.js-edit_file

代码立即恢复,对话历史也回到了修改前。我在原来的对话中补充:

“注意处理空值情况,在访问 data.length 之前先检查 data 是否为 null”

这次 AI 生成的代码就考虑了边缘情况,测试通过。

2:探索性编程

在尝试多种实现方案时,Checkpointing 让你可以大胆实验。每次尝试都会自动创建检查点,失败了就回滚,成功了就继续前进。

我曾尝试三种不同的缓存策略:LRU、LFU 和 ARC。每次实现后都运行基准测试,不满意就 /restore 回去尝试下一种。最后发现 LRU 在我的场景下性能最好,直接采用了那个版本。

3:代码审查

在批准gemin cli的大规模修改前,你可以先让它执行,检查结果,如果不满意立即恢复。这比传统的 git stash 更轻量,因为它同时保存了对话上下文。

有一次gemini帮我重构了整个模块的导入结构,涉及 20+ 个文件。我批准后检查发现有些导入路径不对,直接 /restore 回去,然后告诉 AI:“保持相对导入路径,不要改成绝对路径”。第二次就完美了。

使用checkpointing的最佳实践

  1. 启用 Checkpointing 作为默认配置:即使在个人项目中也建议开启
  2. 定期清理旧检查点:检查点会占用磁盘空间,可以手动删除 ~/.gemini/history/ 下的旧快照
  3. 配合 Git 使用:Checkpointing 不能替代 Git,它是 Git 的补充,适合快速实验和撤销

关于磁盘空间占用:检查点存储在 ~/.gemini/history/<project_hash> 目录下。我的一个中型项目(约 500 个文件)在使用一周后占用了约 500MB 空间。由于使用 Git 存储,增量保存效率较高,但建议定期清理旧检查点。

Sandbox 功能解析

沙箱是保护系统安全的最后一道防线。当我们允许 AI 执行 shell 命令或修改文件时,沙箱可以隔离这些操作,防止意外的系统损坏或数据泄露。

如何启用

Gemini CLI 提供了多层级的沙箱配置系统,优先级从高到低:

1. 命令行标志(最高优先级):

gemini -s docker      # 使用 Docker
gemini -s podman      # 使用 Podman
gemini -s sandbox-exec  # 使用 macOS Seatbelt
gemini -s true        # 自动选择可用的沙箱引擎

2. 环境变量

export GEMINI_SANDBOX=docker
# 可选值: true | docker | podman | sandbox-exec

3. 配置文件 (settings.json)(最低优先级):

{
  "tools": {
    "sandbox": true
  }
}

注意:旧版本的 --sandbox-image 标志已在 0.17.0 被移除。新的配置方式支持跨平台的沙箱引擎选择,更加灵活。这种分层设计允许团队在配置文件中设置默认值,同时允许开发者根据需要临时覆盖。

沙箱的核心价值

根据官方文档,沙箱提供以下保护:

  • 安全性:防止意外的系统损坏或数据丢失
  • 隔离性:将 AI 操作限制在受控环境中
  • 一致性:提供可重现的执行环境
  • 实验安全性:可以安全地测试未知代码

重要提示:官方文档明确指出:“Sandboxing reduces but doesn’t eliminate all risks”(沙箱可以降低但不能完全消除所有风险)。沙箱不是银弹,仍需谨慎审核 AI 的操作。

支持的沙箱引擎

1. macOS Seatbelt (sandbox-exec)

macOS 原生的沙箱机制,基于 TrustedBSD MAC Framework。

特点

  • 零依赖,系统内置
  • 使用沙箱配置文件(profile)控制权限
  • 默认使用 permissive-open profile,限制写入操作到项目目录外

可用的 Seatbelt Profile

通过 SEATBELT_PROFILE 环境变量选择:

export SEATBELT_PROFILE=restrictive-open

可选值:

  • permissive-open(默认):允许读取系统,限制写入
  • permissive-closed:更严格的读取限制
  • permissive-proxied:通过代理控制网络访问
  • restrictive-open:高度限制,仅允许必要操作
  • restrictive-closed:最严格的限制

选择建议

官方推荐"select the most restrictive profile suitable for your workflow"(选择最严格但仍能满足工作流程的 profile)。

  • 日常开发:permissive-open
  • 处理敏感数据:restrictive-openrestrictive-closed
  • 需要网络隔离:permissive-proxied

2. 容器化沙箱 (Docker/Podman)

跨平台的隔离方案,提供更强的隔离性。

要求

  • 本地构建的容器镜像
  • 活组织内部镜像仓库中的镜像

使用示例

# 使用 Docker
gemini -s docker -p "分析项目结构"

# 使用 Podman(适合无 root 环境)
gemini -s podman -p "运行测试"

高级配置

通过环境变量自定义容器行为:

# 传递自定义标志给 Docker/Podman
export SANDBOX_FLAGS="--cpus=2 --memory=4g"

# Linux 下覆盖用户权限
export SANDBOX_SET_UID_GID=1000:1000

# 启用调试输出
export DEBUG=1

gemini -s docker -p "执行任务"

沙箱配置示例

在容器中运行 AI,限制资源使用

# 设置环境变量
export GEMINI_SANDBOX=docker
export SANDBOX_FLAGS="--cpus=2 --memory=2g --network=none"

# 运行任务
gemini -p "分析代码并生成报告"

这个配置会:

  • 使用 Docker 沙箱
  • 限制最多使用 2 个 CPU 核心
  • 限制内存使用为 2GB
  • 禁用网络访问(--network=none

场景:macOS 上使用严格的沙箱 profile

export GEMINI_SANDBOX=sandbox-exec
export SEATBELT_PROFILE=restrictive-open

gemini -p "重构代码"

调试沙箱问题

当沙箱执行失败时,启用调试模式获取详细信息:

DEBUG=1 gemini -s docker -p "测试命令"

这会输出:

  • 沙箱引擎的选择过程
  • 传递给容器的完整命令
  • 权限和环境变量设置
  • 错误的详细堆栈

总结

Gemini CLI 的 Checkpointing 和 Sandbox 功能共同构成了 AI 辅助编程的安全防护体系:

Checkpointing 提供"时间维度"的安全:通过自动保存 Git 快照和对话历史,它让你可以大胆地让 AI 尝试各种方案,因为任何时候都可以回退到之前的状态。这种"时光倒流"的能力极大地降低了实验成本,让探索性编程变得更加自由。

Sandbox 提供"空间维度"的安全:通过隔离 AI 的操作环境,它限制了潜在风险的影响范围。无论是 macOS 的 Seatbelt 还是容器化方案,沙箱都能在不影响工作效率的前提下,为系统提供一层关键的保护。

参考资料

评论