多端点备份(backup)
为什么做多端备份
AI 已经渗透到线上工作的方方面面,Agent 手里的权限越来越大——能读写文件、能操作云端账户、能执行删除。一旦误操作或凭证泄露,单点存储(只在本机、或只在一个云端)里的重要文件可能被彻底删除、无处找回。对策是把私有文件同时备份到多个互相独立的端点(飞书云盘、其它网盘、WebDAV、S3 等):攻击或误删要同时命中所有端点才能让信息真正消失,端点越多,彻底丢失的概率越低。
本 skill 就是这个对策的落地:统一的备份范围(目录制)+ 可插拔的备份端点(注册制)。做这个 skill 的完整动机与设计考量见 README.md。
备份范围:目录制(每个项目根一份 backup/)
- 项目
.gitignore必须含backup/一行(整目录忽略;只写目录名,绝不写成员文件名——.gitignore 是公开文件,文件名即信息)。 - 只收用户明确点名的文件:
backup/是用户的备份清单,不是 agent 的收纳箱——只有用户主动说「XX 要备份 / 把 XX 备份一下」的文件才放进去。agent 觉得某文件值得备份时先建议、经用户确认再放——点名之外的文件进备份目录 = 被上传云端,等于替用户决定了什么该上云。 - backup/ 里放副本,原文件留在原地:普通文件复制进
backup/,不移动。完整的多端模型是三份:本地原文件一份(tmp/、docs/ 等工作位置)+backup/内副本一份 + 云端一份——备份的价值全在冗余,若移动进来(原位置没了),backup/ 那份成了孤本、本地反而少一层,且文件离开工作位置会破坏日常使用。原文件日后有更新,重新复制覆盖backup/内副本再执行备份。 - 固定路径的配置文件(如
CLAUDE.local.md、.claude/settings.local.json这类有加载机制约定的):在backup/里放符号链接指向原文件——ln -s ../CLAUDE.local.md backup/CLAUDE.local.md。链接自动跟随原件更新、不像副本会过期,且原件始终在场、冗余天然成立。备份脚本tar -h会解引用链接、打包实际内容;恢复时解压出文件实体,移回原位即完成还原。 - 端点子目录(目录即端点归属):
backup/下的一级子目录若与某个已注册端点同名(如backup/feishu/),该目录内容只备份到该端点;根下散文件与其它名字的子目录(普通归档目录)备份到全部端点。「只备份到飞书」= 把文件放进backup/feishu/,无需任何额外标记。子目录里同样可放符号链接。
为什么不加密:风险模型是「本地丢失为真风险(高概率)、云端泄露为低概率低损失」——加密反而引入「本地密钥丢失则备份作废」的更大风险。明文备份即可。
端点体系:注册制
- 注册表:
endpoints/endpoints.json(本 skill 目录下),登记每个已授权端点的:name、display、type、credential(凭证位置 + 用法)、reference(详情文档)、authorized_at。做任何端点操作前先读它,确认端点已注册。 - 凭证纪律:注册表与文档只记「凭证在哪、怎么用」,凭证本体一律放工具自管的位置(如 lark-cli auth、rclone config),确需 skill 自存的放
endpoints/目录下独立文件——该目录是本机数据,整体不进开源镜像(CapabilityManagerAgent 仓库已 gitignore),绝不写进会被 git 跟踪的文件。 - 本机私有数据同纪律(「Skill 内容纯净性」全局规则):端点的其它私有值——云端 folder 标识、个人文件夹命名、机器网络细节(代理等)、个人配置当前值——同样只登记在
endpoints/(注册表字段或独立文件),功能文件(SKILL.md / references / scripts)只写通用机制并用占位符表达机器差异,保持可开源纯净。 - 默认全部端点:用户说「备份」未指定端点 = 执行全部已注册端点(多端冗余正是本 skill 的动机);说「备份到 XX」= 只执行该端点。共享内容(根下文件)进每个端的包、端点子目录内容只进对应端的包;逐端独立执行、独立汇报,单端失败不影响其它端(凭证失效的端点按其 reference 文档重新授权后重跑即可)。
- 端点类型两种:
builtin-*内置类型:专用工具对接(如 feishu 走 lark-cli),上传逻辑在scripts/backup.sh里有对应分支;rclone类型:rclone支持的任意远端(WebDAV / S3 / Google Drive / Dropbox / OneDrive 等),rclone config配好凭证即注册成功,脚本零改动。
- 备份模式与格式白名单:端点注册表每条可配
mode与file_formats:mode: "raw"= 原文件直传(不打包压缩),云端按backup/内相对路径建对应文件夹结构镜像存放;file_formats为格式白名单(glob 数组,大小写敏感),只有匹配的文件才上传,不匹配的逐条[SKIP]并汇总——飞书端点即此模式(白名单当前值见注册表file_formats)。端点可约定云端落位形态转换(如飞书:.md一律转飞书文档 docx 上传、不传原始 md 文件——转换命令与坑见references/feishu.md「MD 文件转为飞书文档」节);mode: "archive"(默认)= 打包 tar.gz 上传单文件,无白名单过滤。- 维护白名单:改
endpoints/endpoints.json对应端点的file_formats数组即可(增删格式即时生效),用户说「飞书白名单加 / 去掉 XX 格式」就改这里。
四个动作
① 放入备份目录(= 打标签)
用户说「XX 文件需要备份 / 把 XX 备份一下」→
- Read 该文件确认存在(不存在先问用户);
- 复制进项目根
backup/(原文件留原位置不动);固定路径配置文件 → 在backup/建符号链接;用户点名了端点(如「备份到飞书」)→ 放进backup/<端点名>/(端点名 = 注册表里的 name,目录不存在则新建,如backup/feishu/),不放根下——放根下 = 备份到全部端点; - 确认项目
.gitignore有backup/这一行,没有就补上(只此一行,别写文件名); - 放好不必立即备份(用户说备份时才备份)。用户说「取消 XX 的备份」→ 把
backup/里的副本(或链接)移出删除,原文件不受影响;说「XX 不用只备份到飞书了」→ 把文件从backup/feishu/移回backup/根下。
没被用户点名过的文件不进 backup/——agent 认为值得备份时先建议,用户点头再放入。
② 执行备份
~/.claude/skills/backup/scripts/backup.sh <项目目录> # 全部已注册端点
~/.claude/skills/backup/scripts/backup.sh <项目目录> --endpoint feishu # 只备份到指定端点
~/.claude/skills/backup/scripts/backup.sh <项目目录> --list # 只列备份范围,不上传
- 打包规则:每个目标端点独立执行。
raw端点逐文件直传(该端可见 = 共享文件 + 本端同名子目录,白名单过滤后原样上传,符号链接解引用为实际内容但保留链接名);archive端点独立打包(该端的包 = 根下共享文件 + 本端同名子目录,tar -h解引用,包内带backup/路径前缀,解压到项目根即还原)。某端无任何可传内容时自动跳过该端。 - 备份成功后逐端点、逐文件向用户汇报(
--list同款分组:共享 / 各端专属)。 - 脚本备份前强制检查
backup/已被 gitignore(项目是 git 仓库时),未忽略即终止并列出修复方法。
③ 查看与恢复
- 查看某端点云端备份列表 / 下载恢复 / 删除旧备份:命令因端点而异,读对应端点文档(飞书:
references/feishu.md)。 - 恢复的通用路径:从端点下载
<项目名>-backup-YYYY-MM-DD.tar.gz→tar -xzf解压到项目根(包内是backup/前缀的相对路径,解压即还原)。 - 删除云端旧备份是写操作,删除前向用户确认。
④ 注册新端点(首次授权)
用户说「备份到 XX」而注册表里没有 XX → 按 references/new-endpoint.md 走授权流程。核心四步:向用户拿凭证 → 验证可用(最小只读操作)→ 保存凭证(位置记进注册表、本体放安全位置)→ 写使用方法(references/<name>.md)并登记注册表。之后该端点与老端点一视同仁,直接凭证登录备份,无需再授权。
通用纪律
- 脚本必须纯 ASCII:脚本文件里不要写中文/全角字符(曾因混入不可见 Unicode 字符导致 bash
unbound variable报错)——注释与 echo 输出一律英文。 - backup/ 必须整目录 gitignore(硬规矩,脚本强制):目录下即私有文件。绝不要把成员文件名写进
.gitignore——.gitignore 是公开文件,文件名即信息(人名、账户、项目代号都算);只写backup/一行。项目不是 git 仓库时自动跳过检测。 - 备份不设自动周期:用户说「备份」时执行。放入目录与执行备份是两个独立动作,中间可隔任意久。
- 端点专属细节(认证命令、代理坑、路径坑、云端目录布局)在各端点 reference 文档里,做对应端点操作前先读。
- 放入前自检两问:往
backup/放任何文件前先自检——① 这是用户明确点名要备份的文件吗?② 它的本地原文件在原位置还在吗(backup/ 里放的是副本、不是孤本;发现文件只存在于 backup/ 一处,先把原位置补回一份再放)?有一问为「否」就先处理再放入。