Gemini CLI 会话管理实战:会话自动保存、恢复、检查点与保留策略深度解析
Gemini CLI 的会话管理(Session Management)负责把你与模型的完整对话历史持久化到本地,让你可以随时从上次中断的地方继续工作。本文基于官方文档 session-management.md 并结合当前仓库源码,系统讲解会话的自动保存机制、通过命令行与交互式浏览器恢复会话的完整操作、Git worktree 并行会话方案,以及 sessionRetention 与 maxSessionTurns 的保留策略配置——读完之后,你可以独立完成会话的查看、恢复、删除与清理策略定制。
会话自动保存:保存什么、存在哪里
你与模型交互时,会话历史会被自动记录,无需任何手动操作。这一后台持久化过程即使在你中断会话(如 Ctrl+C、终端意外关闭)的情况下也能保证工作现场得以保留。
保存的内容包括完整的对话上下文:
- 你的提示词(prompts)和模型的回复;
- 所有工具执行记录(输入与输出);
- Token 用量统计(输入、输出、缓存等维度);
- 助理的思考与推理摘要(thoughts / reasoning summaries,在模型支持时可用)。
存储位置为 ~/.gemini/tmp/<project_hash>/chats/,其中 <project_hash> 是基于项目根目录生成的唯一标识。这带来一个关键特性:会话是按项目隔离的。切换到另一个目录(另一个项目)再启动 CLI,加载的就是那个项目自己的会话历史,互不干扰。
从源码结构看,这一隔离逻辑由核心包的 Storage 类统一管理:sessions.ts 中 listSessions 通过 config.storage 拿到项目级临时目录,再拼接 chats 子目录扫描会话文件。会话文件名遵循 session-<时间戳>-<ID前8位>.jsonl 格式——在 sessionUtils.ts 的注释中明确写道:
The filename format is
session-<TIMESTAMP>-<ID_SLICE(0,8)>.jsonl
文件名中只保留 UUID 的前 8 位作为短标识,完整 UUID 记录在文件内容的 sessionId 字段中。恢复或按短 ID 查找时,SessionSelector.sessionExists 会先按前 8 位过滤候选文件,再逐个解析确认完整 ID 是否匹配(见 sessionUtils.ts#L415-L440)。
另外,扫描时会主动过滤三类文件,它们不会出现在会话列表中:
- 子代理(subagent)会话:属于工具调用的内部实现细节,不对主代理历史开放;
- 无可恢复内容的会话:仅含启动信息、系统消息或内部上下文的会话被跳过(
hasResumableContent校验); - 损坏文件:解析失败的文件标记为 corrupted,列表接口自动剔除。
恢复会话:命令行三种方式
启动 Gemini CLI 时,使用 --resume(简写 -r)标志加载已有会话,支持三种寻址方式:
1. 恢复最近一次会话
gemini --resume
不带参数时立即加载最新会话。对应源码中 RESUME_LATEST 常量(sessionUtils.ts#L26):--resume 无值时被解析为 latest,SessionSelector.resolveSession 会按 startTime 升序排序后取最后一个。值得注意的是,当项目根本没有任何会话时,latest 不会报错退出,而是发出警告并回退创建一个新会话(见 gemini.tsx#L315-L319)。
2. 按索引恢复
先列出可用会话(见下文 列出会话),再用序号恢复:
gemini --resume 1
索引是 1 基的,按会话开始时间从旧到新编号——越新的会话编号越大。
3. 按 UUID 恢复
直接提供完整会话 ID:
gemini --resume a1b2c3d4-e5f6-7890-abcd-ef1234567890
从 SessionSelector.findSession 的实现可以确认解析优先级:先按完整 UUID 精确匹配,匹配失败才尝试解析为纯数字索引(且要求索引严格为数字字符串、大于 0 且不超过会话总数)。找不到时抛出带 INVALID_SESSION_IDENTIFIER 错误码的 SessionError,提示信息会引导你使用 --list-sessions 查看可用会话。
恢复会话:交互式 Session Browser
在 CLI 运行中,输入 /resume 斜杠命令即可打开 Session Browser:
/resume
从源码看,resumeCommand.ts 将其定义为 CommandKind.BUILT_IN 的内建命令,autoExecute: true——即无需带参数直接执行,其动作是返回 dialog: 'sessionBrowser' 交给 DialogManager 渲染。
在斜杠命令补全界面中,/resume(或 /chat)等命令会按标题分隔符分组展示:
-- auto --(会话浏览器组):其中的list可被选中,直接打开会话浏览器;-- checkpoints --(手动检查点命令组)。
唯一前缀如 /resum、/cha 也会解析到同一个分组菜单。
Session Browser 支持的交互操作如下(这些按键处理逻辑可在 SessionBrowser.tsx 的键盘事件分支中找到对应实现):
| 操作 | 按键 | 说明 |
|---|---|---|
| 浏览 | 上下方向键 / PageUp / PageDown | 滚动浏览历史会话列表 |
| 预览 | 选中项 | 显示会话日期、消息数、首条用户提示词等详情 |
| 搜索 | / |
进入搜索模式,按 ID 或会话内容过滤 |
| 恢复 | Enter | 恢复选中的会话 |
| 退出 | Esc | 关闭 Session Browser |
| 删除 | x 或 X |
删除选中的会话(源码中 key.sequence === 'x' || key.sequence === 'X' 分支触发删除流程) |
预览信息来自 SessionInfo 结构(sessionUtils.ts#L90-L121):包含 startTime、messageCount、lastUpdated、displayName(通常为 AI 摘要或首条用户消息)等字段。搜索模式下会按需加载会话全文(includeFullContent 选项)进行内容级匹配并展示带上下文的片段。
手动会话检查点
对于会话内部需要命名分支点(branch point)的场景,使用 chat checkpoints 保存和回跳:
/resume save decision-point
/resume list
/resume resume decision-point
兼容性别名:
/chat ...可以执行同样的命令;/resume checkpoints ...在迁移期内也保持可用。
使用 Git worktrees 并行多个会话
同时处理多个任务时,可以用 Git worktrees 为每个 Gemini 会话提供独立的代码库副本,避免一个会话的改动与另一个会话冲突。由于会话按项目根目录(<project_hash>)隔离,每个 worktree 目录天然对应独立的会话存储空间,这与 worktree 的隔离诉求正好契合。
管理会话:列出与删除
列出会话
gemini --list-sessions
输出当前项目所有可用会话的示例:
Available sessions for this project (3):
1. Fix bug in auth (2 days ago) [a1b2c3d4]
2. Refactor database schema (5 hours ago) [e5f67890]
3. Update documentation (Just now) [abcd1234]
实现位于 listSessions:会话按开始时间升序编号,每行显示序号、标题(超过 100 字符截断为 97 字符加省略号)、相对时间与 8 位短 ID;当前活动会话会额外标注 , current。此外,列表生成前会先调用 generateSummary 为最近一次会话生成 AI 摘要(未配置认证时优雅跳过),因此列表中的标题可能是摘要而非原始首条消息。
删除会话
命令行方式:--delete-session 后跟索引或 ID:
gemini --delete-session 2
deleteSession 的解析策略与 --resume 一致——先 UUID 后索引;同时有一条硬性保护:不允许删除当前活动会话(isCurrentSession 为真时直接提示 Cannot delete the current active session. 并返回)。
Session Browser 方式:
- 用
/resume打开浏览器; - 导航到要删除的会话;
- 按 x。
配置保留策略:sessionRetention
你可以在 settings.json 中控制会话历史的保留方式。默认情况下,Gemini CLI 会自动清理过期的会话数据,防止历史无限膨胀;某个会话被删除时,其所有关联数据(实现计划、任务跟踪器、工具输出、活动日志)会一并清除。默认策略是保留会话 30 天。
通过 /settings 命令或直接编辑 settings.json 自定义:
{
"general": {
"sessionRetention": {
"enabled": true,
"maxAge": "30d",
"maxCount": 50
}
}
}
enabled(boolean):会话清理总开关,默认true。maxAge(string):会话保留时长,例如"24h"、"7d"、"4w",超过该时长的会话将被删除,默认"30d"。maxCount(number):保留的会话数量上限,超出部分从最旧的开始删除。默认为未定义(不限制)。minRetention(string):最短保留期(安全下限),默认"1d",比该期限更新的会话永远不会被自动清理。
底层实现细节(见 sessionCleanup.ts):
- 时长字符串由
parseRetentionPeriod解析,支持的单位是h(小时)、d(天)、w(周)、m(月,按 30 天计),且数值必须大于 0——注意文档示例中的"4w"之外的单位(如s、y)不在支持范围; - 启动时执行的
validateRetentionConfig会做三项校验:maxAge不得小于minRetention;maxCount至少为 1;maxAge与maxCount必须至少指定其一。任何一项不满足,清理会被整体禁用并写警告日志(Session cleanup disabled: ...),而不是误删数据; - 清理入口
cleanupExpiredSessions在 CLI 启动时运行,删除判定基于lastUpdated时间戳,且当前活动会话永远被排除在删除范围之外; - 除了会话文件本身,还会级联调用
deleteSessionArtifactsAsync与deleteSubagentSessionDirAndArtifactsAsync清除该会话的工具输出目录、子代理会话等关联产物; - 同一份保留策略同样作用于
tool-outputs目录的清理(cleanupToolOutputFiles),即工具输出的年龄与数量上限与maxAge/maxCount联动; - 全局兜底原则是“清理失败不阻断启动”:任何异常都会被捕获并计入
failed统计,不会导致 CLI 无法启动。
配置单会话长度上限:maxSessionTurns
为防止单个会话的上下文窗口过大、成本过高,可以限制会话轮次:
{
"model": {
"maxSessionTurns": 100
}
}
maxSessionTurns(number):单次会话允许的最大轮数(用户与模型的交互往返数)。设为-1表示无限制(默认值)。
达到上限后的行为:
- 交互模式:CLI 显示一条提示信息并停止向模型发送请求,需要手动开启新会话;
- 非交互模式:CLI 直接以错误退出。
延伸阅读
- Memory 工具:把信息持久化并跨会话保留;
- Checkpoint:会话状态的检查点机制;
- CLI 参考:全部命令行标志;
- Git worktrees 指南:并行会话的目录隔离方案;
- 实现与测试:sessions.ts、sessionUtils.ts、sessionCleanup.ts、sessionCleanup.integration.test.ts、SessionBrowser 组件。
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