【免费下载链接】gentle-ai
Gentle-AI configures the AI coding agents you already use: Claude Code, Cursor, OpenCode, Codex, Pi, and more. Choose persistent memory, Organic-Driven Development, curated skills, MCP servers, personas, and optional bounded review. Open source, no agent lock-in.
Gentle-AI 会在每次install、sync、upgrade操作前自动为你的 AI 编码 Agent(Claude Code、Cursor、OpenCode、Codex、Pi 等)配置文件创建快照备份,并采用压缩、去重与自动修剪策略控制磁盘占用。本文围绕官方 备份与回滚指南 展开,结合仓库内internal/backup/包的源码实现,完整讲解备份触发流程、快照结构与清单字段、保留与去重算法、TUI 与 CLI 的恢复操作,以及验证失败后的标准处置路径,帮助你安全、可预期地管理配置文件回滚。
备份系统如何工作
备份系统在每次运行gentle-ai install、sync或upgrade时自动触发,核心流程分为四步,对应 snapshot.go 中Snapshotter.Create的实现:
- 计算校验和(checksum):对所有将要备份的文件计算复合 SHA-256 校验和;
- 去重跳过(dedup):如果结果与最近一次备份完全相同,则跳过本次备份,不产生新的快照;
- 创建压缩快照:将所有配置文件打包为
snapshot.tar.gz; - 修剪旧备份:仅保留最近 5 个未钉住(unpinned)的备份,删除其余部分。
触发点与元数据来源
- install/sync 路径在 run.go 的
prepareBackupStep中执行:先通过ComputeChecksum做去重判断,再调用snapshotter.Create创建快照,随后将source、description、created_by_version等元数据写入manifest.json,最后执行保留期修剪(backup.Prune)。 - upgrade 路径在 executor.go 中通过
snapshotCreator变量(默认为backup.NewSnapshotter().Create)在升级执行前创建快照;ExecuteOptions.SkipBackup对应 CLI 的--no-backup,可对单次运行显式跳过备份创建与修剪。 - 每次 install/sync 还会在临时目录创建一份"事务快照"(transaction snapshot),供安装过程中失败时即时回滚使用,成功后随清理步骤删除(见 run.go 的
cleanupRollbackSnapshot)。
校验和算法细节
retention.go 中ComputeChecksum的算法是:过滤出存在且为普通文件的路径 → 按字典序排序保证确定性 → 对每个文件内容计算 SHA-256 → 拼接所有path:hexhash\n对 → 对拼接结果再做一次 SHA-256 得到复合摘要。校验和包含绝对路径,因此去重是"每台机器"级别的,不同主机的相同文件会产生不同校验和——这是有意设计。当没有任何文件时,使用空字符串的 SHA-256 作为稳定哨兵值(emptyFilesChecksum),使连续两次零文件备份也能被正确识别为重复(snapshot.go)。
快照内容与目录结构
每个备份快照存放在~/.gentle-ai/backups/<id>/下(目录解析见 manifest.go),包含两个关键文件:
manifest.json—— 元数据清单:来源(source)、时间戳(created_at)、文件数(file_count)、校验和(checksum)、钉住状态(pinned)等;snapshot.tar.gz—— 所有被备份文件的压缩归档。
对于操作前不存在的路径,清单记录existed=false,以便回滚时正确"反向删除"安装过程中创建的文件。
manifest.json 字段说明
manifest.go 定义的Manifest结构主要字段如下:
| 字段 | JSON 键 | 含义 |
|---|---|---|
| ID | id | 备份目录名(基于时间戳生成) |
| CreatedAt | created_at | UTC 创建时间 |
| RootDir | root_dir | 备份目录绝对路径 |
| Source | source | 来源:install/sync/upgrade/uninstall(旧清单缺省显示unknown source) |
| Description | description | 人工可读的描述(TUI 中r键可编辑) |
| FileCount | file_count | 实际存在并被快照的文件数(existed=false的条目不计入) |
| CreatedByVersion | created_by_version | 创建该备份的 gentle-ai 版本 |
| Pinned | pinned | 是否被钉住(受保护不被修剪) |
| Compressed | compressed | 是否使用 tar.gz 压缩归档 |
| Checksum | checksum | 复合 SHA-256,用于去重 |
| Entries | entries | 每个备份目标的明细条目 |
DisplayLabel方法(manifest.go)组合来源、本地时间戳与文件数生成人类可读标签,钉住的备份会带[pinned]前缀——这正是 TUI 与gentle-ai restore --list列表里每行显示的内容。
备份范围(重要边界)
备份范围:升级前与同步前的快照只覆盖
state.InstalledAgents(~/.gentle-ai/state.json)中列出的 Agent。通过 gentle-ai 之外方式安装的 Agent 配置目录不会进入快照。
此外,upgrade 的备份遍历通过backupExcludeSubdirs白名单跳过运行态/缓存类目录(executor.go),例如:backups(绝不递归进备份自身)、cache、debug、downloads、plugins(MCP 插件二进制可达 60+ MB)、sessions、tasks、telemetry、node_modules,以及 Claude Code 的projects(单目录可超 1 GB)、Gemini/Antigravity 的browser_recordings(可达 3+ GB)等。这些目录不是配置、且体积巨大,跳过它们能避免升级过程被拖垮。
保留策略与去重
| 设置项 | 默认值 | 行为 |
|---|---|---|
| 保留数量(Keep count) | 5 | 保留最近 5 个未钉住的备份 |
| 钉住备份(Pinned) | 永不删除 | 无论数量多少都免于修剪 |
| 重复备份(Duplicates) | 跳过 | 配置未变化时不创建新备份 |
| 压缩(Compression) | 始终启用 | 新备份使用 tar.gz(体积约缩小 75%) |
默认保留数量5定义在 retention.go 的DefaultRetentionCount。修剪逻辑Prune(retention.go):
- 读取
backupDir下所有含可读manifest.json的子目录; - 按
CreatedAt从新到旧排序; - 划分出未钉住的部分,若数量超过保留上限,则删除最旧的超额备份;
- 单个目录删除失败仅记录日志、不中断其余备份的评估;
- 无
manifest.json的目录被静默跳过,不计入限额。
去重由DuplicateManifest(retention.go)实现:只有当最近一次备份的Checksum与本次相同且校验和不为空时才判定为重复。prepareBackupStep在判定重复时还会通过manifestTargetsMatch确认目标路径集合完全一致(run.go),双重保险后才真正跳过快照创建。
钉住备份(Pinning)
任何备份都可以在 TUI 中标记为"钉住"以保护其不被自动修剪:
- 运行
gentle-ai,进入Backups屏幕; - 使用
j/k选择备份; - 按
p切换钉住/取消钉住; - 钉住的备份显示
[pinned]标识。
钉住的备份永远不会被自动删除,即使超过保留数量上限也不例外。底层由TogglePin实现(manifest.go):翻转清单的Pinned字段并重写manifest.json;TUI 的按键处理在 model.go,Prune在分区时完全跳过Pinned == true的备份(retention.go)。
通过 TUI 管理备份
进入Backups屏幕后,可用快捷键如下(TUI 按键分发见 model.go):
| 按键 | 操作 |
|---|---|
j/k | 上下移动选择 |
Enter | 恢复选中的备份 |
p | 钉住/取消钉住(保护免于修剪) |
r | 重命名(添加描述) |
d | 删除 |
Esc | 返回 |
r键调用RenameBackup(manifest.go),只更新清单中的Description字段而不重命名目录;d键先进入删除确认屏幕,再调用DeleteBackup(manifest.go)删除整个备份目录。
通过 CLI 恢复备份
gentle-ai restore是独立的命令行恢复入口,完整实现见 restore.go:
gentle-ai restore [--list | latest | <id>] [--yes]| 参数 | 作用 |
|---|---|
--list | 列出所有可用备份而不执行恢复 |
latest | 恢复最新备份(列表中第一个) |
<id> | 按 ID 精确恢复指定备份 |
--yes/-y | 跳过确认提示(适合脚本/非交互场景) |
典型用法
# 查看可用备份 gentle-ai restore --list # 恢复最近一次备份 gentle-ai restore latest # 按 ID 恢复,并跳过确认 gentle-ai restore 20260928150405.000000000 --yes # 恢复过程中提示确认(默认交互) gentle-ai restore latest # Restore backup <id> (install — 2026-09-28 15:04)? # This will overwrite your current configuration. Type 'yes' to confirm:列表输出格式为[序号] ID 标签 [版本],例如[1] 20260928150405.000000000 install — 2026-09-28 15:04 (5 files) [v3.x]。确认逻辑只接受yes(忽略大小写),EOF 或非确认输入均视为拒绝并提示使用--yes(restore.go)。
恢复行为细节
existed=true:从快照将文件恢复到原始路径;existed=false:删除该文件(回滚安装期间创建的文件);- 按文件原子写入,不存在部分恢复状态;
- 同时兼容压缩(tar.gz)与旧版(plain file)备份。
原子写入与类型安全
restoreEntry(restore.go)通过filemerge.WriteFileAtomicMode写入文件并恢复原始权限位(mode)。恢复前会对清单中的每条OriginalPath做严格的路径围栏校验(isPathUnderRoot):路径必须是绝对路径、且位于允许的根目录(默认$HOME)之下;对于压缩备份的SnapshotPath还要求是相对路径(绝对路径会读取活文件系统而非解压目录,直接拒绝)。解压归档时,compression.go 会拒绝任何含..的条目、解析到目标目录本身的"."条目,以及非普通文件类型,防止路径穿越攻击。
PathKind 分类语义
清单条目的Kind字段(manifest.go)决定恢复策略:
regular:普通文件,进入归档并在恢复时写回;existed=false时显式删除;directory:空目录,不归档,恢复时确保目录存在、绝不删除预先存在的目录;symlink_directory:指向目录的相对符号链接,不归档,恢复时校验LinkTarget是安全相对路径(非绝对路径、解析后仍在根目录内,防..与..\穿越)后再重建;若磁盘上已存在同路径节点,则必须仍是符号链接且指向相同目标,否则 fail-closed 拒绝(restore.go);""(unknown,旧版清单):恢复时采用保守策略——existed=false的 unknown 条目只保留不删除,因为无法证明该路径是安装创建的,删除可能误伤用户自有文件(restore.go)。
旧版备份兼容
v1.16 之前的旧版备份使用files/目录存放普通文件副本,而非 tar.gz 归档(Compressed=false)。RestoreService.Restore会根据manifest.Compressed自动分流到restoreCompressed或restorePlain(restore.go),两种格式均可完整恢复。旧版清单没有Source、FileCount等字段时,显示层优雅降级为unknown source、不显示文件数。
验证失败后的标准处置
如果安装后的验证失败,按照文档给出的四步走:
- 审查验证报告中的失败检查项(报告格式由 report.go 渲染,逐项显示
[ok]/[!!]/[??]/[--]状态与失败原因,汇总行形如Verification checks: N passed, N failed, N warnings, N skipped); - 通过 TUI 或
gentle-ai restore latest从最新快照恢复; - 使用
--dry-run重新运行安装以验证计划(install、sync、upgrade均支持 dry-run,不产生任何文件变更); - 修复外部依赖后重新安装。
恢复操作全程有防误伤护栏:清单中的root_dir必须位于~/.gentle-ai/backups/之下才会执行删除(DeleteBackup的isRootDirUnderBackupRoot检查,manifest.go);回滚时rollbackRoots(run.go)以本次 install/sync 实际写入过的 home 目录、工作区目录为边界校验每个条目,防止被篡改的清单将文件写到任意位置。
rollback 不覆盖的内容
- 通过
brew install、apt-get install或pacman -S安装的软件包不会在回滚时被卸载——快照系统只处理配置文件; - 需要撤销包安装时,请直接使用平台包管理器,例如
brew uninstall、sudo apt-get remove、sudo pacman -R。
这也决定了备份系统的定位:它是配置层的安全网,负责把 Agent 配置文件恢复到操作前状态;系统级依赖属于包管理器职责范围,两者互补而不混淆。
总结
Gentle-AI 的备份与回滚机制在 internal/backup 包中形成了一条完整链路:Snapshotter.Create负责快照与元数据记录 →ComputeChecksum/DuplicateManifest实现内容去重 →Prune按保留策略修剪 →RestoreService按 PathKind 语义安全恢复。日常使用中,你只需记住三件事:所有install/sync/upgrade都会自动留后路;重要备份用 TUI 的p钉住;出问题时用gentle-ai restore latest一键回退,再用--dry-run验证计划后重装。
【免费下载链接】gentle-ai
Gentle-AI configures the AI coding agents you already use: Claude Code, Cursor, OpenCode, Codex, Pi, and more. Choose persistent memory, Organic-Driven Development, curated skills, MCP servers, personas, and optional bounded review. Open source, no agent lock-in.
相关推荐
Factorio Learning Environment备份策略:快照与灾难恢复
Factorio Learning Environment备份策略:快照与灾难恢复 在Factorio Learning Environment(FLE)中,实
人工智能大模型AI AgentAgent 评测模型评测Simplefolio备份策略:数据恢复与版本回滚的完整指南
Simplefolio备份策略:数据恢复与版本回滚的完整指南 作为一款简洁美观的开发者作品集模板,Simplefolio帮助开发者快速搭建个人在线作品展示平台。
前端Monad数据库快照:增量备份与恢复策略
Monad数据库快照:增量备份与恢复策略 引言:数据安全的痛点与解决方案 你是否曾因数据库故障导致数据丢失?是否在全量备份上耗费过多存储空间?Monad数据库的
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考