Skip to main content

dcg

Destructive Command Guard - High-performance Rust hook for Claude Code that blocks dangerous commands before execution. SIMD-accelerated, modular pack system, whitelist-first architecture. Essential safety layer for agent workflows.

Source facts

Repository
Dicklesworthstone/destructive_command_guard
Last source activity
October 25, 2026 at 11:58
Detected SKILL.md language
English
Stars
6,212
Forks
262

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
dcg
description
Destructive Command Guard - High-performance Rust hook for Claude Code that blocks dangerous commands before execution. SIMD-accelerated, modular pack system, whitelist-first architecture. Essential safety layer for agent workflows.
# DCG — Destructive Command Guard A high-performance Claude Code hook that intercepts and blocks destructive commands before they execute. Written in Rust with SIMD-accelerated filtering for sub-millisecond latency. ## Why This Exists AI coding agents are powerful but fallible. They can accidentally run destructive commands: - **"Let me clean up the build artifacts"** → `rm -rf ./src` (typo) - **"I'll reset to the last commit"** → `git reset --hard` (destroys uncommitted changes) - **"Let me fix the merge conflict"** → `git checkout -- .` (discards all modifications) - **"I'll clean up untracked files"** → `git clean -fd` (permanently deletes untracked files) DCG intercepts dangerous commands *before* execution and blocks them with a clear explanation, giving you a chance to stash your changes first. ## Critical Design Principles ### 1. Whitelist-First Architecture Safe patterns are checked *before* destructive patterns. This ensures explicitly safe commands are never accidentally blocked: ``` git checkout -b feature → Matches SAFE "checkout-new-branch" → ALLOW git checkout -- file.txt → No safe match, matches DESTRUCTIVE → DENY ``` ### 2. Fail-Safe Defaults (Default-Allow) Unrecognized commands are **allowed by default**. This ensures: - The hook never breaks legitimate workflows - Only *known* dangerous patterns are blocked - New git commands work until explicitly categorized ### 3. Zero False Negatives Philosophy The pattern set prioritizes **never allowing dangerous commands** over avoiding false positives. A few extra prompts for manual confirmation are acceptable; lost work is not. ## What It Blocks ### Git Commands That Destroy Uncommitted Work | Command | Reason | |---------|--------| | `git reset --hard` | Destroys uncommitted changes | | `git reset --merge` | Destroys uncommitted changes | | `git checkout -- <file>` | Discards file modifications | | `git restore <file>` (without `--staged`) | Discards uncommitted changes | | `git clean -f` | Permanently deletes untracked files | ### Git Commands That Destroy Remote History | Command | Reason | |---------|--------| | `git push --force` / `-f` | Overwrites remote commits | | `git branch -d`, `--delete`, `-D`, `-f`, `-M`, `-C` | Deletes or force-overwrites a user-owned branch ref | ### Git Commands That Destroy Stashed Work | Command | Reason | |---------|--------| | `git stash drop` | Permanently deletes a stash | | `git stash clear` | Permanently deletes all stashes | ### Filesystem Commands | Command | Reason | |---------|--------| | `rm -rf` (outside `/tmp`, `/var/tmp`, `$TMPDIR`) | Recursive deletion is dangerous | ## What It ALLOWS Safe operations pass through silently: ### Always Safe Git Operations `git status`, `git log`, `git diff`, `git add`, `git commit`, `git push`, `git pull`, `git fetch`, read-only branch listings, `git stash`, `git stash pop`, `git stash list` ### Explicitly Safe Patterns | Pattern | Why Safe | |---------|----------| | `git checkout -b <branch>` | Creating new branches | | `git checkout --orphan <branch>` | Creating orphan branches | | `git restore --staged <file>` | Unstaging only, doesn't touch working tree | | `git restore -S <file>` | Short flag for staged | | `git clean -n` / `--dry-run` | Preview mode, no actual deletion | | `rm -rf /tmp/*` | Temp directories are ephemeral | | `rm -rf $TMPDIR/*` | Shell variable forms | ### Safe Alternative: `--force-with-lease` ```bash git push --force-with-lease # ALLOWED - refuses if remote has unseen commits git push --force # BLOCKED - can overwrite others' work ``` ## Modular Pack System DCG uses a modular "pack" system to organize patterns by category: ### Core Packs (Always Enabled) | Pack | Description | |------|-------------| | `core.git` | Destructive git commands | | `core.filesystem` | Dangerous rm -rf outside temp | ### Database Packs | Pack | Description | |------|-------------| | `database.postgresql` | DROP/TRUNCATE in PostgreSQL | | `database.mysql` | DROP/TRUNCATE in MySQL/MariaDB | | `database.mongodb` | dropDatabase, drop() | | `database.redis` | FLUSHALL/FLUSHDB | | `database.sqlite` | DROP in SQLite | ### Container Packs | Pack | Description | |------|-------------| | `containers.docker` | docker system prune, docker rm -f | | `containers.compose` | docker-compose down --volumes | | `containers.podman` | podman system prune | ### Kubernetes Packs | Pack | Description | |------|-------------| | `kubernetes.kubectl` | kubectl delete namespace | | `kubernetes.helm` | helm uninstall | | `kubernetes.kustomize` | kustomize delete patterns | ### Cloud Provider Packs | Pack | Description | |------|-------------| | `cloud.aws` | Destructive AWS CLI commands | | `cloud.gcp` | Destructive gcloud commands | | `cloud.azure` | Destructive az commands | ### Infrastructure Packs | Pack | Description | |------|-------------| | `infrastructure.terraform` | terraform destroy | | `infrastructure.ansible` | Dangerous ansible patterns | | `infrastructure.pulumi` | pulumi destroy | ### System Packs | Pack | Description | |------|-------------| | `system.disk` | dd, mkfs, fdisk operations | | `system.permissions` | Dangerous chmod/chown patterns | | `system.services` | systemctl stop/disable patterns | ### Other Packs | Pack | Description | |------|-------------| | `strict_git` | Extra paranoid git protections | | `package_managers` | npm unpublish, cargo yank | ### Configuring Packs ```toml # ~/.config/dcg/config.toml [packs] enabled = [ "database.postgresql", "containers.docker", "kubernetes", # Enables all kubernetes sub-packs ] ``` ## Environment Variables | Variable | Description | |----------|-------------| | `DCG_PACKS="containers.docker,kubernetes"` | Enable packs (comma-separated) | | `DCG_DISABLE="kubernetes.helm"` | Disable packs/sub-packs | | `DCG_VERBOSE=1` | Verbose output | | `DCG_COLOR=auto\|always\|never` | Color mode | | `DCG_BYPASS=1` | Bypass DCG entirely (escape hatch) | ## Installation ### Quick Install (Recommended) ```bash 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 ``` ### From Source (Requires Rust Nightly) ```bash cargo +nightly install --git https://github.com/Dicklesworthstone/destructive_command_guard ``` ### Prebuilt Binaries Available for: Linux x86_64, Linux ARM64, macOS Intel, macOS Apple Silicon, Windows ## Claude Code Configuration Add to `~/.claude/settings.json`: ```json { "hooks": { "PreToolUse": [ { "matcher": "Bash|PowerShell|Monitor", "hooks": [ { "type": "command", "command": "/absolute/path/to/dcg" } ] } ] } } ``` Replace `/absolute/path/to/dcg` with the exact resolved binary path. Do not use bare `dcg`: non-interactive hook shells may not inherit the interactive `PATH`. On native Windows, use `install.ps1` so the hook receives the PowerShell-safe absolute command and explicit shell selection. **Important:** Restart Claude Code after adding the hook. ## How It Works ### Processing Pipeline ``` ┌─────────────────────────────────────────────────────────────────┐ │ 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) ``` ### Stage 1: JSON Parsing - Reads hook input from stdin - Validates Claude Code's `PreToolUse` format - Non-Bash tools immediately allowed ### Stage 2: Command Normalization - Strips absolute paths: `/usr/bin/git status` → `git status` - Preserves argument paths ### Stage 3: Quick Rejection Filter - SIMD-accelerated substring search for "git" or "rm" - Commands without these bypass regex entirely (99%+ of commands) ### Stage 4: Pattern Matching - Safe patterns checked first (short-circuit on match → allow) - Destructive patterns checked second (match → deny) - No match → default allow ## Exit Codes | Code | Meaning | |------|---------| | `0` | Command is safe, proceed | | `2` | Command is blocked, do not execute | ## CLI Usage Test commands manually: ```bash # Show version with build metadata dcg --version # Test a command echo '{"tool_name":"Bash","tool_input":{"command":"git reset --hard"}}' | dcg ``` ## Example Block Message ``` ════════════════════════════════════════════════════════════════════════ 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. ════════════════════════════════════════════════════════════════════════ ``` ### Contextual Suggestions | Command Type | Suggestion | |-------------|------------| | `git reset`, `git checkout --` | "Consider using 'git stash' first" | | `git clean` | "Use 'git clean -n' first to preview" | | `git push --force` | "Consider using '--force-with-lease'" | | `rm -rf` | "Verify the path carefully before running manually" | ## Edge Cases Handled ### Path Normalization ```bash /usr/bin/git reset --hard # Blocked /usr/local/bin/git checkout -- . # Blocked /bin/rm -rf /home/user # Blocked ``` ### Flag Ordering Variants ```bash rm -rf /path # Combined flags rm -fr /path # Reversed order rm -r -f /path # Separate flags rm --recursive --force /path # Long flags ``` All variants are handled. ### Shell Variable Expansion ```bash rm -rf $TMPDIR/build # Allowed (temp) rm -rf ${TMPDIR}/build # Allowed rm -rf "$TMPDIR/build" # Allowed rm -rf "${TMPDIR:-/tmp}/build" # Allowed ``` ### Staged vs Worktree Restore ```bash 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) ``` ## Performance Optimizations
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub