{"skill":{"slug":"destructive-command-guard","displayName":"Destructive Command Guard","summary":"Destructive Command Guard - High-performance Rust hook for Claude Code that blocks dangerous commands before execution. SIMD-accelerated, modular pack system...","description":"---\nname: dcg\ndescription: \"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.\"\n---\n\n# DCG — Destructive Command Guard\n\nA 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.\n\n## Why This Exists\n\nAI coding agents are powerful but fallible. They can accidentally run destructive commands:\n\n- **\"Let me clean up the build artifacts\"** → `rm -rf ./src` (typo)\n- **\"I'll reset to the last commit\"** → `git reset --hard` (destroys uncommitted changes)\n- **\"Let me fix the merge conflict\"** → `git checkout -- .` (discards all modifications)\n- **\"I'll clean up untracked files\"** → `git clean -fd` (permanently deletes untracked files)\n\nDCG intercepts dangerous commands *before* execution and blocks them with a clear explanation, giving you a chance to stash your changes first.\n\n## Critical Design Principles\n\n### 1. Whitelist-First Architecture\n\nSafe patterns are checked *before* destructive patterns. This ensures explicitly safe commands are never accidentally blocked:\n\n```\ngit checkout -b feature    →  Matches SAFE \"checkout-new-branch\"  →  ALLOW\ngit checkout -- file.txt   →  No safe match, matches DESTRUCTIVE  →  DENY\n```\n\n### 2. Fail-Safe Defaults (Default-Allow)\n\nUnrecognized commands are **allowed by default**. This ensures:\n- The hook never breaks legitimate workflows\n- Only *known* dangerous patterns are blocked\n- New git commands work until explicitly categorized\n\n### 3. Zero False Negatives Philosophy\n\nThe pattern set prioritizes **never allowing dangerous commands** over avoiding false positives. A few extra prompts for manual confirmation are acceptable; lost work is not.\n\n## What It Blocks\n\n### Git Commands That Destroy Uncommitted Work\n\n| Command | Reason |\n|---------|--------|\n| `git reset --hard` | Destroys uncommitted changes |\n| `git reset --merge` | Destroys uncommitted changes |\n| `git checkout -- <file>` | Discards file modifications |\n| `git restore <file>` (without `--staged`) | Discards uncommitted changes |\n| `git clean -f` | Permanently deletes untracked files |\n\n### Git Commands That Destroy Remote History\n\n| Command | Reason |\n|---------|--------|\n| `git push --force` / `-f` | Overwrites remote commits |\n| `git branch -D` | Force-deletes without merge check |\n\n### Git Commands That Destroy Stashed Work\n\n| Command | Reason |\n|---------|--------|\n| `git stash drop` | Permanently deletes a stash |\n| `git stash clear` | Permanently deletes all stashes |\n\n### Filesystem Commands\n\n| Command | Reason |\n|---------|--------|\n| `rm -rf` (outside `/tmp`, `/var/tmp`, `$TMPDIR`) | Recursive deletion is dangerous |\n\n## What It ALLOWS\n\nSafe operations pass through silently:\n\n### Always Safe Git Operations\n\n`git status`, `git log`, `git diff`, `git add`, `git commit`, `git push`, `git pull`, `git fetch`, `git branch -d` (safe delete with merge check), `git stash`, `git stash pop`, `git stash list`\n\n### Explicitly Safe Patterns\n\n| Pattern | Why Safe |\n|---------|----------|\n| `git checkout -b <branch>` | Creating new branches |\n| `git checkout --orphan <branch>` | Creating orphan branches |\n| `git restore --staged <file>` | Unstaging only, doesn't touch working tree |\n| `git restore -S <file>` | Short flag for staged |\n| `git clean -n` / `--dry-run` | Preview mode, no actual deletion |\n| `rm -rf /tmp/*` | Temp directories are ephemeral |\n| `rm -rf $TMPDIR/*` | Shell variable forms |\n\n### Safe Alternative: `--force-with-lease`\n\n```bash\ngit push --force-with-lease   # ALLOWED - refuses if remote has unseen commits\ngit push --force              # BLOCKED - can overwrite others' work\n```\n\n## Modular Pack System\n\nDCG uses a modular \"pack\" system to organize patterns by category:\n\n### Core Packs (Always Enabled)\n\n| Pack | Description |\n|------|-------------|\n| `core.git` | Destructive git commands |\n| `core.filesystem` | Dangerous rm -rf outside temp |\n\n### Database Packs\n\n| Pack | Description |\n|------|-------------|\n| `database.postgresql` | DROP/TRUNCATE in PostgreSQL |\n| `database.mysql` | DROP/TRUNCATE in MySQL/MariaDB |\n| `database.mongodb` | dropDatabase, drop() |\n| `database.redis` | FLUSHALL/FLUSHDB |\n| `database.sqlite` | DROP in SQLite |\n\n### Container Packs\n\n| Pack | Description |\n|------|-------------|\n| `containers.docker` | docker system prune, docker rm -f |\n| `containers.compose` | docker-compose down --volumes |\n| `containers.podman` | podman system prune |\n\n### Kubernetes Packs\n\n| Pack | Description |\n|------|-------------|\n| `kubernetes.kubectl` | kubectl delete namespace |\n| `kubernetes.helm` | helm uninstall |\n| `kubernetes.kustomize` | kustomize delete patterns |\n\n### Cloud Provider Packs\n\n| Pack | Description |\n|------|-------------|\n| `cloud.aws` | Destructive AWS CLI commands |\n| `cloud.gcp` | Destructive gcloud commands |\n| `cloud.azure` | Destructive az commands |\n\n### Infrastructure Packs\n\n| Pack | Description |\n|------|-------------|\n| `infrastructure.terraform` | terraform destroy |\n| `infrastructure.ansible` | Dangerous ansible patterns |\n| `infrastructure.pulumi` | pulumi destroy |\n\n### System Packs\n\n| Pack | Description |\n|------|-------------|\n| `system.disk` | dd, mkfs, fdisk operations |\n| `system.permissions` | Dangerous chmod/chown patterns |\n| `system.services` | systemctl stop/disable patterns |\n\n### Other Packs\n\n| Pack | Description |\n|------|-------------|\n| `strict_git` | Extra paranoid git protections |\n| `package_managers` | npm unpublish, cargo yank |\n\n### Configuring Packs\n\n```toml\n# ~/.config/dcg/config.toml\n[packs]\nenabled = [\n    \"database.postgresql\",\n    \"containers.docker\",\n    \"kubernetes\",  # Enables all kubernetes sub-packs\n]\n```\n\n## Environment Variables\n\n| Variable | Description |\n|----------|-------------|\n| `DCG_PACKS=\"containers.docker,kubernetes\"` | Enable packs (comma-separated) |\n| `DCG_DISABLE=\"kubernetes.helm\"` | Disable packs/sub-packs |\n| `DCG_VERBOSE=1` | Verbose output |\n| `DCG_COLOR=auto\\|always\\|never` | Color mode |\n| `DCG_BYPASS=1` | Bypass DCG entirely (escape hatch) |\n\n## Installation\n\n### Quick Install (Recommended)\n\n```bash\ncurl -fsSL \"https://raw.githubusercontent.com/Dicklesworthstone/destructive_command_guard/master/install.sh?$(date +%s)\" | bash\n\n# Easy mode: auto-update PATH\ncurl -fsSL \"https://raw.githubusercontent.com/Dicklesworthstone/destructive_command_guard/master/install.sh?$(date +%s)\" | bash -s -- --easy-mode\n\n# System-wide (requires sudo)\ncurl -fsSL \"https://raw.githubusercontent.com/Dicklesworthstone/destructive_command_guard/master/install.sh?$(date +%s)\" | sudo bash -s -- --system\n```\n\n### From Source (Requires Rust Nightly)\n\n```bash\ncargo +nightly install --git https://github.com/Dicklesworthstone/destructive_command_guard\n```\n\n### Prebuilt Binaries\n\nAvailable for: Linux x86_64, Linux ARM64, macOS Intel, macOS Apple Silicon, Windows\n\n## Claude Code Configuration\n\nAdd to `~/.claude/settings.json`:\n\n```json\n{\n  \"hooks\": {\n    \"PreToolUse\": [\n      {\n        \"matcher\": \"Bash\",\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"dcg\"\n          }\n        ]\n      }\n    ]\n  }\n}\n```\n\n**Important:** Restart Claude Code after adding the hook.\n\n## How It Works\n\n### Processing Pipeline\n\n```\n┌─────────────────────────────────────────────────────────────────┐\n│                        Claude Code                               │\n│  Agent executes `rm -rf ./build`                                │\n└─────────────────────┬───────────────────────────────────────────┘\n                      │\n                      ▼ PreToolUse hook (stdin: JSON)\n┌─────────────────────────────────────────────────────────────────┐\n│                          dcg                                     │\n│  ┌──────────────┐    ┌──────────────┐    ┌──────────────┐       │\n│  │    Parse     │───▶│  Normalize   │───▶│ Quick Reject │       │\n│  │    JSON      │    │   Command    │    │   Filter     │       │\n│  └──────────────┘    └──────────────┘    └──────┬───────┘       │\n│                                                  │               │\n│                      ┌───────────────────────────┘               │\n│                      ▼                                           │\n│  ┌──────────────────────────────────────────────────────────┐   │\n│  │                   Pattern Matching                        │   │\n│  │   1. Check SAFE_PATTERNS (whitelist) ──▶ Allow if match  │   │\n│  │   2. Check DESTRUCTIVE_PATTERNS ──────▶ Deny if match    │   │\n│  │   3. No match ────────────────────────▶ Allow (default)  │   │\n│  └──────────────────────────────────────────────────────────┘   │\n└─────────────────────┬───────────────────────────────────────────┘\n                      │\n                      ▼ stdout: JSON (deny) or empty (allow)\n```\n\n### Stage 1: JSON Parsing\n- Reads hook input from stdin\n- Validates Claude Code's `PreToolUse` format\n- Non-Bash tools immediately allowed\n\n### Stage 2: Command Normalization\n- Strips absolute paths: `/usr/bin/git status` → `git status`\n- Preserves argument paths\n\n### Stage 3: Quick Rejection Filter\n- SIMD-accelerated substring search for \"git\" or \"rm\"\n- Commands without these bypass regex entirely (99%+ of commands)\n\n### Stage 4: Pattern Matching\n- Safe patterns checked first (short-circuit on match → allow)\n- Destructive patterns checked second (match → deny)\n- No match → default allow\n\n## Exit Codes\n\n| Code | Meaning |\n|------|---------|\n| `0` | Command is safe, proceed |\n| `2` | Command is blocked, do not execute |\n\n## CLI Usage\n\nTest commands manually:\n\n```bash\n# Show version with build metadata\ndcg --version\n\n# Test a command\necho '{\"tool_name\":\"Bash\",\"tool_input\":{\"command\":\"git reset --hard\"}}' | dcg\n```\n\n## Example Block Message\n\n```\n════════════════════════════════════════════════════════════════════════\nBLOCKED  dcg\n────────────────────────────────────────────────────────────────────────\nReason:  git reset --hard destroys uncommitted changes. Use 'git stash' first.\n\nCommand:  git reset --hard HEAD~1\n\nTip: If you need to run this command, execute it manually in a terminal.\n     Consider using 'git stash' first to save your changes.\n════════════════════════════════════════════════════════════════════════\n```\n\n### Contextual Suggestions\n\n| Command Type | Suggestion |\n|-------------|------------|\n| `git reset`, `git checkout --` | \"Consider using 'git stash' first\" |\n| `git clean` | \"Use 'git clean -n' first to preview\" |\n| `git push --force` | \"Consider using '--force-with-lease'\" |\n| `rm -rf` | \"Verify the path carefully before running manually\" |\n\n## Edge Cases Handled\n\n### Path Normalization\n\n```bash\n/usr/bin/git reset --hard          # Blocked\n/usr/local/bin/git checkout -- .   # Blocked\n/bin/rm -rf /home/user             # Blocked\n```\n\n### Flag Ordering Variants\n\n```bash\nrm -rf /path          # Combined flags\nrm -fr /path          # Reversed order\nrm -r -f /path        # Separate flags\nrm --recursive --force /path    # Long flags\n```\n\nAll variants are handled.\n\n### Shell Variable Expansion\n\n```bash\nrm -rf $TMPDIR/build           # Allowed (temp)\nrm -rf ${TMPDIR}/build         # Allowed\nrm -rf \"$TMPDIR/build\"         # Allowed\nrm -rf \"${TMPDIR:-/tmp}/build\" # Allowed\n```\n\n### Staged vs Worktree Restore\n\n```bash\ngit restore --staged file.txt    # Allowed (unstaging only)\ngit restore -S file.txt          # Allowed (short flag)\ngit restore file.txt             # BLOCKED (discards changes)\ngit restore --worktree file.txt  # BLOCKED (explicit worktree)\ngit restore -S -W file.txt       # BLOCKED (includes worktree)\n```\n\n## Performance Optimizations\n\nDCG is designed for zero perceived latency:\n\n| Optimization | Technique |\n|--------------|-----------|\n| **Lazy Static** | Regex patterns compiled once via `LazyLock` |\n| **SIMD Quick Reject** | `memchr` crate for CPU vector instructions |\n| **Early Exit** | Safe match returns immediately |\n| **Zero-Copy JSON** | `serde_json` operates on input buffer |\n| **Zero-Allocation** | `Cow<str>` for path normalization |\n| **Release Profile** | `opt-level=\"z\"`, LTO, single codegen unit |\n\n**Result:** Sub-millisecond execution for typical commands.\n\n## Pattern Counts\n\n| Type | Count |\n|------|-------|\n| Safe patterns (whitelist) | 34 |\n| Destructive patterns (blacklist) | 16 |\n\n## Security Considerations\n\n### What DCG Protects Against\n\n- Accidental data loss from `git checkout --` or `git reset --hard`\n- Remote history destruction from force pushes\n- Stash loss from `git stash drop/clear`\n- Filesystem accidents from `rm -rf` outside temp directories\n\n### What DCG Does NOT Protect Against\n\n- Malicious actors (can bypass the hook)\n- Non-Bash commands (Python/JavaScript file writes, API calls)\n- Committed but unpushed work\n- Commands inside scripts (`./deploy.sh` contents not inspected)\n\n### Threat Model\n\nDCG assumes the AI agent is **well-intentioned but fallible**. It catches honest mistakes, not adversarial attacks.\n\n## Troubleshooting\n\n### Hook not blocking commands\n\n1. Verify `~/.claude/settings.json` has hook configuration\n2. Restart Claude Code\n3. Test manually: `echo '{\"tool_name\":\"Bash\",\"tool_input\":{\"command\":\"git reset --hard\"}}' | dcg`\n\n### Hook blocking safe commands\n\n1. Check if there's an edge case not covered\n2. File a GitHub issue\n3. Temporary bypass: `DCG_BYPASS=1` or run command manually\n\n## FAQ\n\n**Q: Why block `git branch -D` but allow `git branch -d`?**\n\nLowercase `-d` only deletes branches fully merged. Uppercase `-D` force-deletes regardless of merge status, potentially losing commits.\n\n**Q: Why is `git push --force-with-lease` allowed?**\n\nForce-with-lease refuses to push if the remote has commits you haven't seen, preventing accidental overwrites.\n\n**Q: Why block all `rm -rf` outside temp directories?**\n\nRecursive forced deletion is extremely dangerous. A typo or wrong variable can delete critical files. Temp directories are designed to be ephemeral.\n\n**Q: What if I really need to run a blocked command?**\n\nDCG instructs the agent to ask for permission. Run the command manually in a separate terminal after making a conscious decision.\n\n## Integration with Flywheel\n\n| Tool | Integration |\n|------|-------------|\n| **Claude Code** | Native PreToolUse hook |\n| **Agent Mail** | Agents can report blocked commands to coordinator |\n| **BV** | Flag tasks that repeatedly trigger DCG |\n| **CASS** | Search DCG block patterns across sessions |\n| **RU** | DCG protects agent-sweep from destructive commits |\n","tags":{"latest":"1.0.0"},"stats":{"comments":0,"downloads":257,"installsAllTime":0,"installsCurrent":0,"stars":0,"versions":1},"createdAt":1771270971617,"updatedAt":1778491560329},"latestVersion":{"version":"1.0.0","createdAt":1771270971617,"changelog":"Destructive Command Guard v1.0.0\n\n- Initial release of a Rust-based high-performance command guard hook for Claude Code.\n- Blocks destructive git, filesystem, and system commands before execution, protecting against accidental data loss.\n- Features a whitelist-first architecture with safe commands always allowed and dangerous patterns blocked.\n- Modular \"pack\" system organizes protections by command category (git, database, cloud, etc.) and supports custom configuration.\n- Provides environment variable support for easy customization and bypass.\n- Offers clear explanations for blocked commands, sub-millisecond latency, and straightforward installation options.","license":null},"metadata":null,"owner":{"handle":"crypticalmass","userId":"s17axqwcpv84dhwtccxgqhjk1h885z3e","displayName":"Ali","image":"https://avatars.githubusercontent.com/u/144951615?v=4"},"moderation":null}