Gemini CLI 会话管理实战:会话自动保存、恢复、检查点与保留策略深度解析
【免费下载链接】gemini-cliAn open-source AI agent that brings the power of Gemini directly into your terminal.项目地址: https://gitcode.com/GitHub_Trending/gemi/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 2deleteSession 的解析策略与--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 组件。
【免费下载链接】gemini-cliAn open-source AI agent that brings the power of Gemini directly into your terminal.项目地址: https://gitcode.com/GitHub_Trending/gemi/gemini-cli
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考