关于 dcg
dcg 是用 Rust 编写的命令安全钩子,在 AI 编码 Agent 执行命令前拦截已知的破坏性操作。它采用安全模式优先和默认放行策略,并可按类别启用规则包。
主要功能
- 01拦截危险 Git 与文件操作
- 02模块化数据库和云规则包
- 03安全模式优先匹配
- 04默认放行未识别命令
- 05解释拦截原因并给出建议
适用场景
- 01防止 Agent 清除未提交的 Git 更改
- 02避免误删文件或存储数据
- 03限制容器、Kubernetes 和云端破坏操作
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ dicklesworthstone/ destructive_command_guard --skill dcg安装后在 Claude Code 中输入/dcg确认已加载。
详细介绍
DCG — 破坏性命令防护
一款高性能的 Claude Code 钩子,可在破坏性命令执行前拦截并阻止它们。使用 Rust 编写,并通过 SIMD 加速过滤,实现亚毫秒级延迟。
存在的意义
AI 编码 Agent 功能强大,但并非万无一失。它们可能会意外运行破坏性命令:
- “我来清理一下构建产物” →
rm -rf ./src(拼写错误) - “我会重置到上次提交” →
git reset --hard(破坏未提交的更改) - “我来解决合并冲突” →
git checkout -- .(丢弃所有修改) - “我会清理未跟踪的文件” →
git clean -fd(永久删除未跟踪的文件)
DCG 会在危险命令执行前拦截它们,并提供明确说明,阻止命令执行,让你有机会先暂存更改。
关键设计原则
1. 白名单优先架构
先检查安全模式,再检查破坏性模式。这样可确保明确标记为安全的命令不会被误拦截:
git checkout -b feature → Matches SAFE "checkout-new-branch" → ALLOW
git checkout -- file.txt → No safe match, matches DESTRUCTIVE → DENY
2. 故障安全默认值(默认允许)
默认允许无法识别的命令。这可确保:
- 钩子不会破坏正常工作流
- 只阻止已知的危险模式
- 新的 git 命令在被明确归类前均可正常使用
3. 零漏报理念
模式集优先考虑绝不放行危险命令,而非避免误报。多几次需要手动确认的提示可以接受;丢失工作成果则不可接受。
会阻止的命令
会破坏未提交工作的 Git 命令
| 命令 | 原因 |
|---|---|
git reset --hard | 破坏未提交的更改 |
git reset --merge | 破坏未提交的更改 |
git checkout -- <file> | 丢弃文件修改 |
git restore <file>(不带 --staged) | 丢弃未提交的更改 |
git clean -f | 永久删除未跟踪的文件 |
会破坏远程历史记录的 Git 命令
| 命令 | 原因 |
|---|---|
git push --force / -f | 覆盖远程提交 |
git branch -d、--delete、-D、-f、-M、-C | 删除或强制覆盖用户拥有的分支引用 |
会破坏暂存工作内容的 Git 命令
| 命令 | 原因 |
|---|---|
git stash drop | 永久删除一个暂存项 |
git stash clear | 永久删除所有暂存项 |
文件系统命令
| 命令 | 原因 |
|---|---|
rm -rf(/tmp、/var/tmp、$TMPDIR 之外) | 递归删除很危险 |
会允许的命令
安全操作会静默通过:
始终安全的 Git 操作
git status、git log、git diff、git add、git commit、git push、git pull、git fetch、只读分支列表、git stash、git stash pop、git stash list
明确安全的模式
| 模式 | 安全原因 |
|---|---|
git checkout -b <branch> | 创建新分支 |
git checkout --orphan <branch> | 创建孤儿分支 |
git restore --staged <file> | 仅取消暂存,不会触及工作树 |
git restore -S <file> | --staged 的简写 |
git clean -n / --dry-run | 预览模式,不会实际删除 |
rm -rf /tmp/* | 临时目录具有临时性 |
rm -rf $TMPDIR/* | Shell 变量形式 |
安全替代方案:--force-with-lease
git push --force-with-lease # ALLOWED - refuses if remote has unseen commits
git push --force # BLOCKED - can overwrite others' work
模块化规则包系统
DCG 使用模块化的“规则包”系统,按类别组织模式:
核心规则包(始终启用)
| 规则包 | 说明 |
|---|---|
core.git | 破坏性 git 命令 |
core.filesystem | 临时目录之外的危险 rm -rf |
数据库规则包
| 规则包 | 说明 |
|---|---|
database.postgresql | PostgreSQL 中的 DROP/TRUNCATE |
database.mysql | MySQL/MariaDB 中的 DROP/TRUNCATE |
database.mongodb | dropDatabase、drop() |
database.redis | FLUSHALL/FLUSHDB |
database.sqlite | SQLite 中的 DROP |
容器工具包
| 工具包 | 描述 |
|---|---|
containers.docker | docker system prune、docker rm -f |
containers.compose | docker-compose down --volumes |
containers.podman | podman system prune |
Kubernetes 工具包
| 工具包 | 描述 |
|---|---|
kubernetes.kubectl | kubectl delete namespace |
kubernetes.helm | helm uninstall |
kubernetes.kustomize | kustomize 删除模式 |
云服务提供商工具包
| 工具包 | 描述 |
|---|---|
cloud.aws | 具有破坏性的 AWS CLI 命令 |
cloud.gcp | 具有破坏性的 gcloud 命令 |
cloud.azure | 具有破坏性的 az 命令 |
基础设施工具包
| 工具包 | 描述 |
|---|---|
infrastructure.terraform | terraform destroy |
infrastructure.ansible | 危险的 ansible 模式 |
infrastructure.pulumi | pulumi destroy |
系统工具包
| 工具包 | 描述 |
|---|---|
system.disk | dd、mkfs、fdisk 操作 |
system.permissions | 危险的 chmod/chown 模式 |
system.services | systemctl stop/disable 模式 |
其他工具包
| 工具包 | 描述 |
|---|---|
strict_git | 更严格的 git 保护措施 |
package_managers | npm unpublish、cargo yank |
配置工具包
# ~/.config/dcg/config.toml
[packs]
enabled = [
"database.postgresql",
"containers.docker",
"kubernetes", # Enables all kubernetes sub-packs
]
环境变量
| 变量 | 描述 |
|---|---|
DCG_PACKS="containers.docker,kubernetes" | 启用工具包(逗号分隔) |
DCG_DISABLE="kubernetes.helm" | 禁用工具包/子工具包 |
DCG_VERBOSE=1 | 详细输出 |
DCG_COLOR=auto|always|never | 颜色模式 |
DCG_BYPASS=1 | 完全绕过 DCG(紧急出口) |
安装
快速安装(推荐)
curl -fsSL "https://raw.githubusercontent.com/Dicklesworthstone/destructive_command_guard/main/install.sh?$(date +%s)" | bash
# Easy mode: auto-update PATH
curl -fsSL "https://raw.githubusercontent.com/Dicklesworthstone/destructive_command_guard/main/install.sh?$(date +%s)" | bash -s -- --easy-mode
# System-wide (requires sudo)
curl -fsSL "https://raw.githubusercontent.com/Dicklesworthstone/destructive_command_guard/main/install.sh?$(date +%s)" | sudo bash -s -- --system
从源码安装(需要 Rust Nightly)
cargo +nightly install --git https://github.com/Dicklesworthstone/destructive_command_guard
预编译二进制文件
适用于:Linux x86_64、Linux ARM64、macOS Intel、macOS Apple Silicon、Windows
Claude Code 配置
将以下内容添加到 ~/.claude/settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash|PowerShell|Monitor",
"hooks": [
{
"type": "command",
"command": "/absolute/path/to/dcg"
}
]
}
]
}
}
将 /absolute/path/to/dcg 替换为解析后的二进制文件绝对路径。不要只写
dcg:非交互式钩子 Shell 可能不会继承交互式
PATH。在原生 Windows 上,请使用 install.ps1,以便钩子获得
兼容 PowerShell 的绝对命令和明确的 Shell 选择。
重要: 添加钩子后,请重启 Claude Code。
工作原理
处理流程
┌─────────────────────────────────────────────────────────────────┐
│ Claude Code │
│ Agent executes `rm -rf ./build` │
└─────────────────────┬───────────────────────────────────────────┘
│
▼ PreToolUse hook (stdin: JSON)
┌─────────────────────────────────────────────────────────────────┐
│ dcg │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Parse │───▶│ Normalize │───▶│ Quick Reject │ │
│ │ JSON │ │ Command │ │ Filter │ │
│ └──────────────┘ └──────────────┘ └──────┬───────┘ │
│ │ │
│ ┌───────────────────────────┘ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Pattern Matching │ │
│ │ 1. Check SAFE_PATTERNS (whitelist) ──▶ Allow if match │ │
│ │ 2. Check DESTRUCTIVE_PATTERNS ──────▶ Deny if match │ │
│ │ 3. No match ────────────────────────▶ Allow (default) │ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────┬───────────────────────────────────────────┘
│
▼ stdout: JSON (deny) or empty (allow)
阶段 1:JSON 解析
- 从 stdin 读取钩子输入
- 验证 Claude Code 的
PreToolUse格式 - 立即允许非 Bash 工具
阶段 2:命令规范化
- 去除绝对路径:
/usr/bin/git status→git status - 保留参数路径
阶段 3:快速过滤
- 使用 SIMD 加速的子字符串搜索查找 "git" 或 "rm"
- 不包含这些内容的命令会完全跳过正则表达式(占所有命令的 99% 以上)
阶段 4:模式匹配
- 首先检查安全模式(匹配时短路 → 允许)
- 然后检查破坏性模式(匹配时 → 拒绝)
- 无匹配 → 默认允许
退出代码
| 代码 | 含义 |
|---|---|
0 | 命令安全,可以继续 |
2 | 命令已阻止,不要执行 |
CLI 用法
手动测试命令:
# Show version with build metadata
dcg --version
# Test a command
echo '{"tool_name":"Bash","tool_input":{"command":"git reset --hard"}}' | dcg
阻止消息示例
════════════════════════════════════════════════════════════════════════
BLOCKED dcg
────────────────────────────────────────────────────────────────────────
Reason: git reset --hard destroys uncommitted changes. Use 'git stash' first.
Command: git reset --hard HEAD~1
Tip: If you need to run this command, execute it manually in a terminal.
Consider using 'git stash' first to save your changes.
════════════════════════════════════════════════════════════════════════
上下文建议
| 命令类型 | 建议 |
|---|---|
git reset、git checkout -- | "建议先使用 'git stash'" |
git clean | "建议先使用 'git clean -n' 预览" |
git push --force | "建议使用 '--force-with-lease'" |
rm -rf | "手动运行前,请仔细确认路径" |
已处理的边缘情况
路径规范化
/usr/bin/git reset --hard # Blocked
/usr/local/bin/git checkout -- . # Blocked
/bin/rm -rf /home/user # Blocked
标志顺序变体
rm -rf /path # Combined flags
rm -fr /path # Reversed order
rm -r -f /path # Separate flags
rm --recursive --force /path # Long flags
所有变体均已处理。
Shell 变量展开
rm -rf $TMPDIR/build # Allowed (temp)
rm -rf ${TMPDIR}/build # Allowed
rm -rf "$TMPDIR/build" # Allowed
rm -rf "${TMPDIR:-/tmp}/build" # Allowed
暂存区与工作树还原
git restore --staged file.txt # Allowed (unstaging only)
git restore -S file.txt # Allowed (short flag)
git restore file.txt # BLOCKED (discards changes)
git restore --worktree file.txt # BLOCKED (explicit worktree)
git restore -S -W file.txt # BLOCKED (includes worktree)
性能优化
DCG 的设计目标是实现零感知延迟:
| 优化 | 技术 |
|---|---|
| 惰性静态变量 | 通过 LazyLock 编译一次正则表达式模式 |
| SIMD 快速拒绝 | 使用 memchr crate 执行 CPU 向量指令 |
| 提前退出 | 安全匹配后立即返回 |
| 零拷贝 JSON | serde_json 直接操作输入缓冲区 |
| 零分配 | 使用 Cow<str> 规范化路径 |
| 发布配置 | opt-level="z"、LTO、单个代码生成单元 |
**结果:**典型命令的执行时间低于 1 毫秒。
模式数量
| 类型 | 数量 |
|---|---|
| 安全模式(白名单) | 34 |
| 破坏性模式(黑名单) | 16 |
安全注意事项
DCG 防护的风险
- 因
git checkout --或git reset --hard导致意外数据丢失 - 因强制推送导致远程历史记录被破坏
- 因
git stash drop/clear导致暂存内容丢失 - 因在临时目录之外执行
rm -rf导致文件系统事故
DCG 无法防护的风险
- 恶意行为者(可以绕过钩子)
- 非 Bash 命令(Python/JavaScript 文件写入、API 调用)
- 已提交但尚未推送的工作
- 脚本内的命令(不会检查
./deploy.sh的内容)
威胁模型
DCG 假设 AI Agent 出于善意,但可能犯错。它能捕获无心之失,而非对抗性攻击。
故障排除
钩子未拦截命令
- 确认
~/.claude/settings.json中配置了钩子 - 重启 Claude Code
- 手动测试:
echo '{"tool_name":"Bash","tool_input":{"command":"git reset --hard"}}' | dcg
钩子拦截了安全命令
- 检查是否存在未覆盖的边缘情况
- 提交 GitHub issue
- 临时绕过:使用
DCG_BYPASS=1,或手动运行命令
常见问题
问:为什么同时拦截 git branch -d 和 git branch -D?
小写 -d 会检查合并状态,但仍会删除分支名称、上游跟踪配置和便捷的 reflog 引用。这些都属于用户拥有的状态,因此每种删除形式都需要明确批准。请先使用 git branch -vv、git branch --merged 和 git branch --no-merged 进行检查。会检查合并状态的形式有自己的规则 core.git:branch-delete,因此设置 [policy.rules] "core.git:branch-delete" = "ask" 会将其变为审批提示,而 -D(core.git:branch-force-delete)仍会被拒绝。
问:为什么允许 git push --force-with-lease?
Force-with-lease 会在远程仓库包含你尚未看到的提交时拒绝推送,从而防止意外覆盖。
问:为什么拦截临时目录之外的所有 rm -rf?
递归强制删除极其危险。拼写错误或变量错误都可能删除关键文件。临时目录专为短期使用而设计。
问:如果我确实需要运行被拦截的命令,该怎么办?
DCG 会指示 Agent 请求许可。经过审慎考虑后,请在单独的终端中手动运行该命令。
与 Flywheel 集成
| 工具 | 集成方式 |
|---|---|
| Claude Code | 原生 PreToolUse 钩子 |
| Agent Mail | Agent 可以向协调器报告被拦截的命令 |
| BV | 标记反复触发 DCG 的任务 |
| CASS | 跨会话搜索 DCG 拦截模式 |
| RU | DCG 可防止 agent-sweep 执行破坏性提交 |