New:Introducing Socket Scanning for VS Code Marketplace Extensions.Learn more →
Get Started

dev-backup

Package Overview
Dependencies
Maintainers
1
Versions
3
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install
Package was removed
Sorry, it seems this package was removed from the registry

dev-backup

Cold backup for a dev workspace: git bundles, directory snapshots and config whitelists into any folder your cloud client already syncs. Zero dependencies, bash 3.2+, macOS and Linux (工作区冷备 CLI)

latest
Source
npmnpm
Version
1.0.2
Version published
Weekly downloads
0
Maintainers
1
Weekly downloads
 
Created
Source

English | 简体中文

dev-backup

npm 版本 许可证 CI

把「一个装着很多 git 仓库的工作区」冷备到一个目录里:产物直接落进你指定的同步目录 (OneDrive / iCloud / Dropbox / 坚果云…或一块外置磁盘),由你已经装好的同步客户端负责上传。

不依赖 rclone / restic,不加密,不做增量协议 —— 它做的是另一件事:把工作区变成一堆 不可变、可校验、可完整还原的文件。

npm i -g dev-backup      # 或者 ./install.sh(不需要 Node)
dev-backup --init        # 写一份配置文件模板
dev-backup --status      # 看一眼:备上了吗、上传了吗
dev-backup               # 跑一次备份

它解决什么问题

工作区里通常是几十个 git 仓库:有的推了远端,有的没有;有的一堆本地分支、tag、 filter-branch 留下的 refs/original/*;还有一堆根本不是 git 的目录(草稿、素材、配置)。 「推远端」覆盖不了这些,而全量 tar 又快又大。

dev-backup 的做法:

目标做法为什么
git 仓库git bundle create --all + 存在时的 refs/stash一个文件装下全部 refs(含远端不带的 refs/original/*、refs/remotes/*),可 git clone --mirror 完整还原
非 git 顶层目录tar.gz 快照,内容指纹写进文件名内容没变就不新增文件(云盘里不会堆重复快照)
工具配置(可选)白名单 + 上云前密钥预检只收你显式列出的几个文件;命中疑似密钥就整份不收

三条贯穿始终的规则:

  • 幂等 —— 同一个提交不会打第二份包;同一份内容不会存第二个快照。
  • 不可变 —— 备份目录里只新增 / 删除文件,从不原地修改已有文件。这是给同步客户端 和后台任务准备的:launchd 起的进程常常改不动别的进程建的文件。
  • 「最新」按文件名判断,不看 mtime —— 云盘重新物化会改写 mtime,用它排序会让 --status 误报落后、让 --restore-drill 拿旧产物演练。

安装

npm(推荐)

npm i -g dev-backup

不用 Node

git clone https://github.com/haotian-lu-prog/dev-backup.git
cd dev-backup && ./install.sh          # 装到 ~/.local/bin

要求:bash(macOS 自带的 3.2 就行)、git、tar、gzip,以及 shasum 或 sha256sum。

快速开始

dev-backup --init                 # 1) 生成 ~/.config/dev-backup/config
$EDITOR ~/.config/dev-backup/config   # 2) 改 ROOT 与 DEST
dev-backup --status               # 3) 看状态(此时应该是「还没有备份」)
dev-backup                        # 4) 跑第一次备份
dev-backup schedule install       # 5) 装每日任务(macOS: launchd;其他: cron)

第一次跑完,DEST 里会出现 repos/、snapshots/、manifests/ 和一份写给人看的 README.md(还原步骤就在里面,离开这台机器也看得到)。

配置

优先级:命令行 > 环境变量 > 配置文件 > 内置默认。配置文件是 KEY=VALUE, 默认在 ~/.config/dev-backup/config(--config 或 DEV_BACKUP_CONFIG 可改)。

配置文件键环境变量默认说明
ROOTDEV_ROOT~/dev要备份的工作区根
DESTDEV_BACKUP_DEST无(必填)备份目标目录。必须在 ROOT 之外 —— 放在工作区里会让快照把备份自己逐轮打大,工具会直接拒绝
LOGDIRDEV_BACKUP_LOGDIRmacOS ~/Library/Logs/dev-backup;其他 ~/.local/state/dev-backup日志、锁、last-ok / last-failure
DEPTHDEV_BACKUP_DEPTH3从 ROOT 往下找 .git 的层数
KEEPDEV_BACKUP_KEEP10每个目标保留多少份产物,更旧的轮转删除
SNAPSHOTSDEV_BACKUP_SNAPSHOTS1是否给非 git 顶层目录打快照
INCLUDE_ENVDEV_BACKUP_INCLUDE_ENV0快照是否包含 .env / .env.*(默认排除,明文密钥不上云)
EXCLUDESDEV_BACKUP_EXCLUDES空额外的 tar 排除项,空格分隔
CONFIGSDEV_BACKUP_CONFIGSoff工具配置白名单(见下)
NOTIFY_TITLEDEV_BACKUP_NOTIFY_TITLEdev-backup(工作区冷备)桌面通知标题
NO_NOTIFYDEV_BACKUP_NO_NOTIFY0设 1 关掉桌面通知
UPLOAD_GRACEDEV_BACKUP_UPLOAD_GRACE600产物超过这么多秒还没上传就报「未上传」
DRILL_DIRDEV_BACKUP_DRILL_DIR日志目录下的 tmp/drill-*--restore-drill 的输出目录
WORKSPACE_IDDEV_BACKUP_WORKSPACE_ID主机名 + ROOT 路径的指纹归属标记(见「多台机器共用一个备份目录」)
FDA_APPDEV_BACKUP_FDA_APP自动探测macOS 上提示授权时指给用户看的 app

DEV_BACKUP_DISABLE=1 会让备份模式立刻退出 0(git 钩子用它做开关); DEV_BACKUP_DEEP_ALL=1 让 --verify 对所有历史产物都做真 clone(慢,默认只对最新那份做)。

工具配置白名单

默认 off —— 它不会去猜你的 home 长什么样。要收就在配置里显式写:

CONFIGS=claude-config|~/.claude|settings.json,CLAUDE.md;codex-config|~/.codex|config.toml,AGENTS.md

格式 <标签>|<家目录>|<相对路径,相对路径>,多条用 ; 分隔。上云前会对这些文件做一次 密钥预检(sk-…、AKIA…、ghp_…、私钥头、token = "…" 之类):命中就整份不收, 并让整轮以非零退出 —— 本工具不加密,拦住比事后补救便宜。

命令

命令做什么退出码
dev-backup [--trigger=名]跑一次备份(幂等)0 / 1
dev-backup --status新鲜度 + 上传状态,人读0 / 1
dev-backup --status --json同一判定的 JSON 出口(契约见下)0 / 1
dev-backup --verify [--fix]逐份校验全部产物;bundle 真 clone + fsck0 / 1(--fix 删了损坏产物仍返回 1)
dev-backup --daily补跑备份 + 逐份校验 + 状态检查0 / 1
dev-backup --prune-orphans [--apply]清理备份目录里已不对应任何目标的残留;默认只列不删0 / 1
dev-backup --restore-drill [目录]真还原演练:镜像 clone,比对提交数与 ref 指纹0 / 1
dev-backup schedule install|uninstall|status [--dry-run]装 / 卸 / 查定时任务0 / 1 / 2
dev-backup --init [--force]写配置文件模板0 / 2
dev-backup --version版本与当前配置文件0

--status 与 --version 是严格只读的:不建目录、不写文件、不动日志。

产物布局与还原

<DEST>/repos/<标签>/<标签>-<UTC时间戳>-<提交前12位>.bundle    ← + 同名 .sha256
<DEST>/snapshots/<标签>/<标签>-<UTC时间戳>-<内容指纹>.tar.gz
<DEST>/configs/<标签>/<标签>-<UTC时间戳>-<内容指纹>.tar.gz
<DEST>/manifests/<UTC时间戳>-<触发源>.tsv                     ← 每次运行一份不可变清单
<DEST>/README.md                                              ← 还原说明(写给人看)
<DEST>/repos/<标签>/.dev-backup-owner                         ← 归属标记(见下)

标签 = 仓库相对工作区根的路径(plugins/foo → plugins_foo)。

# 完整还原(推荐):refs/* 全量,含 refs/original/*、refs/remotes/*
git clone --mirror "<DEST>/repos/<标签>/<文件>.bundle" /tmp/restore.git

# 日常还原:普通工作副本
git clone "<DEST>/repos/<标签>/<文件>.bundle" /tmp/restore

# 非 git 目录
tar -xzf "<DEST>/snapshots/<标签>/<文件>.tar.gz" -C /tmp/restore

不在覆盖内(有意为之):仓库里未提交 / 未跟踪的改动、隐藏目录(.worktrees/ 之类)、 家目录里的凭据与会话历史、可重装的大体积内容(node_modules/、构建产物)。别把冷备当唯一 保险 —— 它是「推远端」之外的第二层,不是「未提交改动」的保险。

定时任务

dev-backup schedule install --at 12:00     # macOS: launchd 每天 12:00;Linux: cron
dev-backup schedule install --dry-run      # 只打印计划,不碰系统
dev-backup schedule status
dev-backup schedule uninstall

macOS 的坑:如果 DEST 在 ~/Library/CloudStorage/(OneDrive / Google Drive 之类)或 ~/Library/Mobile Documents/ 下,后台任务默认读不到那里已有的文件 —— 那是 TCC 保护, 写入通常没事、读改会被拒。两种解法:给运行它的程序「完全磁盘访问权限」,或者

dev-backup schedule install --program /path/to/已授权的可执行文件

把任务交给一个已经拿到授权的主体去跑。程序会被调用成 <program> --daily --trigger=launchd。 --status 会明确报告这种情况(fda-blocked),不会假装正常。

多台机器共用一个备份目录

每备份一个目标,工具会在目标目录里写一份 .dev-backup-owner(内容是「工作区 ID」, 默认 = 主机名 + 工作区根路径的指纹)。于是:

  • 归属是别的工作区/主机的目录:--status 只报告、--prune-orphans --apply 绝不删、 备份时拒绝写入并整轮以非零退出(宁可少备一个目标,也不去覆盖别人的产物)。
  • 没有归属标记的老目录按「大概是自己的」处理,行为与老版本一致。

同一个工作区在两台机器上跑、并且就是要共用一个 DEST 时,把两边的 WORKSPACE_ID 设成同一个值即可。

给下游消费者的契约

dev-backup.status/1 JSON 是稳定契约,dsh-dev-backup (DeepSeek Harness 里的备份看板插件)与自建 macOS 面板都消费它。字段、reason code、 上传状态 token、退出码语义见 docs/compatibility.md。

平台支持与实测边界

  • macOS:本机日常使用中,端到端自测全绿(含 bash 3.2)。
  • Linux:代码里所有 stat -f%z / date -j -f / shasum 都走了兼容层,CI 在 ubuntu-latest 上跑同一套自测。作者尚未在真实 Linux 机器上手工验证过 —— 别把 CI 绿当成「任何发行版都没问题」。
  • 上传状态探测(uploaded / uploading / stale)用的是 macOS 的 mdls;其他平台如实 报告「上传状态未知」,不会假装已上传。

测试

npm test            # = bash test/lint.sh && bash test/selftest.sh
npm run test:frozen # 冻结时钟压力测试:把产物时间戳钉成同一个值再跑一遍

自测全程只在 mktemp -d 造的临时工作区里操作,不碰真实备份目录。静态检查会拦 「bash 3.2 会把全角字符吃进变量名」这类本机踩过的坑、bash 4 专有语法、版本号不一致、 以及误入仓库的个人路径。

npm run test:frozen 是专门的并列压力测试:产物名里的 UTC 时间戳只有秒精度, 真实机器上「同一秒内为两个提交各备一次」是时序巧合(快的机器会撞上),冻结时钟把那巧合变成常态, 用来保证轮转不会删掉刚写出的产物、校验与还原演练也不会抓错那一份。

许可证

MIT,见 LICENSE。

Keywords

backup

FAQs

Package last updated on 02 Oct 2026

Related posts