Demo_CLI 实战教程:给 AI Agent 装上智能撤销,毁灭性操作一步还原
Claude Code 和 Cursor 在运行危险命令前会弹出确认框问你要不要继续,但它们不会提前快照。当 Agent 执行了 rm -rf 删错目录、DROP TABLE 丢了数据库、或者 git reset --hard 毁掉了未提交的工作,确认对话框上的 “Allow” 按钮就是你最后的心理防线——点下去,就没有回头路了。
Demo_CLI 的思路截然相反:恢复是默认行为,拦截是最后手段。在每个破坏性命令执行之前,它自动快照目标文件、目录或本地数据库,生成一份防篡改的收据(Receipt)。如果 Agent 搞砸了,一条 demo_cli undo 命令就能回到快照时刻。只有当操作确实无法恢复(如 terraform destroy、远程资源删除)时,它才升级为硬拦截。
安装与初始化
Demo_CLI 是一个 Python CLI 工具,通过 pipx 全局安装:
pipx install git+https://github.com/WePwn/demo_cli.git@beta demo_cli --version
安装完成后,进入你的项目目录,执行初始化:
cd /path/to/your/project demo_cli init # 生成 .demo_cli.toml 配置文件(默认 shadow 模式) demo_cli doctor # 验证安装:Python 版本、PATH、钩子注册状态
demo_cli doctor 是非常实用的诊断命令,它会检查 demo_cli 是否在 Claude Code 能够找到的 PATH 中。如果安装在虚拟环境内,需要保持该环境激活——否则 Claude Code 会静默跳过钩子,不做任何安全检查。
工作模式:从 Shadow 到 Enforce
Demo_CLI 有两种模式,建议按阶段切换:
Shadow 模式(默认):观察、快照、记录,但绝不拦截。这是推荐的上手方式。钩子会在 stderr 上输出捕获到的快照信息,让你看到价值而不影响 Agent 工作流。运行一周后查看收据日志,再决定是否启用强模式。
Enforce 模式:钩子主动拦截工具调用,根据操作类型做出不同响应:
| 判定结果 | 钩子响应 | 触发条件 |
|---|---|---|
ESCALATE | deny(拦截) | 不可恢复的破坏(基础设施销毁、强制推送等) |
CONTEXT_MISMATCH | ask(暂停) | 声明的环境与解析到的环境不匹配 |
REVERSIBLE / DRY_RUN | allow(放行) | 已快照且可恢复 |
ALLOW | allow(放行) | 非修改性操作,无需处理 |
切换模式只需修改配置文件或指定参数:
demo_cli check "rm -rf dist" --mode enforce
在 shadow 模式下运行一段时间积累信任后,再切换到 enforce。
与 Claude Code 集成
Demo_CLI 利用了 Claude Code 的 PreToolUse 钩子机制。每个工具调用之前,Claude Code 会运行一个外部命令,接收完整的工具输入 JSON,并返回权限决策。
注册钩子:
demo_cli install-hook # 写入 .claude/settings.json
钩子注册后,每次 Claude Code 执行 Bash、Edit、Write、MultiEdit 或 NotebookEdit 命令前,Demo_CLI 都会自动触发:
Claude Code 即将执行: Bash(rm -rf dist/)
↓
demo_cli hook(自动触发)
↓
分类 → 解析目标 → 快照 → 决策
↓
allow(放行,附带恢复点)
deny (拦截,原因返回给 Agent)
ask (暂停,等待人工决定)
这里有一个容易被忽略的关键点:PreToolUse 钩子返回 deny 时,即使会话使用了 --dangerously-skip-permissions 模式(跳过交互式确认),钩子仍然生效。也就是说,在完全自主运行的场景下,恢复保障层依然在工作。
与 Cursor 集成
Cursor 也支持钩子机制,Demo_CLI 为其提供了独立的适配命令:
demo_cli install-hook --cursor # 项目级(.cursor/hooks.json) demo_cli install-hook --cursor --scope global # 全局级(~/.cursor/hooks.json)
与 Claude Code 不同,Cursor 的钩子配置必须设置 failClosed: true——Cursor 默认是”失败开放”(钩子崩溃时放行命令),而 failClosed: true 将其反转:守护程序如果无法运行就阻止执行。
要注意的是,当前 Cursor 适配器仅拦截 Shell 命令(通过 beforeShellExecution 钩子),文件编辑操作的拦截在本次 Beta 中仅限 Claude Code。
日常操作命令
一旦 Demo_CLI 开始工作,你会积累一系列恢复点(Recovery Points)。管理和使用它们非常直观:
demo_cli status # 查看当前模式、钩子状态、收据完整性 demo_cli log # 列出所有恢复点:ID、时间、类型、大小、操作 demo_cli diff# 查看某个恢复点之后发生了哪些变化 demo_cli undo # 恢复到该操作之前的状态 demo_cli verify # 验证收据哈希链是否完整(防篡改检查)
手动测试某个命令的判定结果也很方便:
demo_cli check "rm -rf dist/" # 检查 rm -rf 的判定 demo_cli check "DELETE FROM users WHERE plan='free'" --db app.db demo_cli check "terraform destroy" --actual-env production --json
check 命令返回三种退出码:0 允许、1 上下文不匹配、2 需要升级拦截。
配置文件详解
demo_cli init 生成的 .demo_cli.toml 结构清晰:
mode = "shadow" [workspace] dir = ".demo_cli" # 收据和恢复点存储目录(已加入 gitignore) [approval] key_env = "DEMO_CLI_APPROVER_KEY" [[target]] match = "production" env = "production" recovery = "snapshot"
[[target]] 段用于声明环境匹配规则。如果 Agent 的目标是生产环境(通过 match: "production" 子串匹配),Demo_CLI 会使用该段定义的行为。环境优先级:显式 --actual-env 标志 > [[target]] 匹配 > 命令文本启发式判断。
什么能恢复,什么不能
Demo_CLI 的设计哲学是”诚实的恢复”——它只保证自己真正能恢复的操作。
快照目标:SQLite 文件、PostgreSQL(通过 pg_dump/pg_restore)、单个文件、目录(上限 256MB)。
诚实升级为拦截:terraform destroy、kubectl delete、git push --force、远程文件系统变更、对象存储删除、外部副作用(邮件、支付、Webhook)、凭据轮换——以及非本地连接字符串的数据库操作。Demo_CLI 不会虚报那些它无法提供的恢复能力。
全环境硬拦截:Remove-Item -Recurse -Force(PowerShell,包括 ri 别名和 -r/-fo 缩写)、rmdir /s、del /s|/f。这些命令递归删除整个目录树且不经过回收站,快照层无法捕获目标,因此即使在开发/暂存环境也会被拒绝。唯一合法的绕过方式是人工结构审批令牌(DEMO_CLI_APPROVER_KEY),Agent 无法伪造。
在 Python 代码中作为库使用
Demo_CLI 也提供了 Python API,可以集成到自己的工具链中:
from demo_cli import Guard
result = Guard(mode="enforce").evaluate("DELETE FROM users", explicit_db="app.db")
print(result.decision.decision) # REVERSIBLE
print(result.permission) # allow
为何不直接用 Git 或 Claude Code Checkpoints?
这是 README 里直接回答的问题,也是 Demo_CLI 的价值核心:Git 和 Claude Code 的后悔药无法恢复仓库之外的 rm -rf、丢失的数据库、或未跟踪文件的覆盖——它们在 Shell 命令执行之前不做快照。Demo_CLI 填补的正是这个精确的空白:在工具调用的前一刻捕获状态,而不是在事后找备份。
总结
Demo_CLI 带来的并不是又一个”拦截一切”的安全钩子,而是一种更务实的思路:大多数时候 Agent 的破坏是可逆的,给它们一个”撤销”比一个”拒绝”更有生产力。从 shadow 模式开始,零风险体验它的价值,再逐步切换到 enforce 模式——让你的 AI Agent 在不牺牲安全的前提下保持高效。
相关链接: