
Destructive Command Guard
- 63 installs
- 14 repo stars
- Updated March 2, 2026
- oakoss/agent-skills
Helps with ai & agent building tasks during AI-assisted development.
About
destructive-command-guard is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- destructive-command-guard
- AI & Agent Building
- AI-coding skill
Destructive Command Guard by the numbers
- 63 all-time installs (skills.sh)
- +2 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #6,190 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/oakoss/agent-skills --skill destructive-command-guardAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 63 |
|---|---|
| repo stars | ★ 14 |
| Last updated | March 2, 2026 |
| Repository | oakoss/agent-skills ↗ |
What it does
Helps with ai & agent building tasks during AI-assisted development.
Files
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 via the memchr crate and Aho-Corasick multi-pattern matching for sub-millisecond latency. Assumes agents are well-intentioned but fallible.
Overview
DCG uses a whitelist-first architecture: safe patterns are checked before destructive patterns, and unrecognized commands are allowed by default (fail-safe). This ensures legitimate workflows are never broken while known dangerous patterns are always blocked. DCG runs as a PreToolUse hook in Claude Code, receiving JSON on stdin for each Bash tool invocation and returning exit code 0 (allow) or 2 (block). It only inspects direct Bash tool invocations, not contents of shell scripts.
The processing pipeline has four stages: JSON parsing, command normalization (strips absolute paths like /usr/bin/git), SIMD quick-reject filter (skips regex for commands without git or rm), and pattern matching. The memchr crate provides hardware-accelerated substring search (SSE2/AVX2 on x86_64, NEON on ARM), while Aho-Corasick handles multi-pattern matching in O(n) time regardless of pattern count.
DCG supports 49+ modular security packs organized by category (git, filesystem, databases, containers, Kubernetes, cloud providers, infrastructure tools). Core packs (core.git, core.filesystem) are always enabled; additional packs are configured via ~/.config/dcg/config.toml or the DCG_PACKS environment variable. The dcg scan subcommand can also audit files for destructive command contexts, suitable for CI integration.
DCG is not published on crates.io; it is installed from GitHub via cargo +nightly install or prebuilt binaries for Linux, macOS, and Windows WSL. The threat model assumes agents are well-intentioned but fallible; DCG catches honest mistakes, not adversarial attacks.
Quick Reference
| Category | Blocked Commands |
|---|---|
| Uncommitted work | git reset --hard, git checkout -- <file>, git restore <file>, git clean -f |
| Remote history | git push --force / -f, git branch -D |
| Stashed work | git stash drop, git stash clear |
| Filesystem | rm -rf (outside /tmp, /var/tmp, $TMPDIR) |
| Category | Allowed Commands |
|---|---|
| Safe git | git status, git log, git diff, git add, git commit, git push, git pull, git fetch, git branch -d, git stash, git stash pop |
| Safe patterns | git checkout -b, git restore --staged, git clean -n, git push --force-with-lease |
| Temp dirs | rm -rf /tmp/*, rm -rf $TMPDIR/* |
| Setting | Value |
|---|---|
| Exit code (safe) | 0 |
| Exit code (blocked) | 2 |
| Default behavior | Allow (fail-safe) |
| Pattern priority | Safe checked first, then destructive |
| Safe patterns | 34 |
| Destructive patterns | 16 |
| Pack Category | Examples |
|---|---|
| Core (default) | core.git, core.filesystem |
| Database | database.postgresql, database.mysql, database.mongodb |
| Containers | containers.docker, containers.compose, containers.podman |
| Kubernetes | kubernetes.kubectl, kubernetes.helm, kubernetes.kustomize |
| Cloud | cloud.aws, cloud.gcp, cloud.azure |
| Infrastructure | infrastructure.terraform, infrastructure.ansible |
| System | system.disk, system.permissions, system.services |
| Other | strict_git, package_managers |
| Environment Variable | Purpose |
|---|---|
DCG_PACKS | Enable packs (comma-separated) |
DCG_DISABLE | Disable specific packs |
DCG_VERBOSE | Verbose output |
DCG_BYPASS | Bypass DCG entirely (escape hatch) |
DCG_COLOR | Color mode (auto, always, never) |
| Installation Method | Command |
|---|---|
| Quick install | `curl -fsSL ".../install.sh" \ |
| From source | cargo +nightly install --git https://github.com/Dicklesworthstone/destructive_command_guard destructive_command_guard |
| Prebuilt binaries | Linux x86_64, Linux ARM64, macOS Intel, macOS Apple Silicon, Windows WSL |
| Processing Stage | Description |
|---|---|
| JSON parsing | Reads PreToolUse hook input, allows non-Bash tools |
| Normalization | Strips absolute paths (/usr/bin/git becomes git) |
| SIMD quick-reject | memchr substring search skips regex for irrelevant commands |
| Pattern matching | Safe patterns first, then destructive, default allow |
Common Mistakes
| Mistake | Correct Pattern |
|---|---|
| Forgetting to restart Claude Code after adding the hook | Always restart Claude Code after modifying ~/.claude/settings.json |
Using DCG_BYPASS=1 permanently in shell profile | Only set bypass temporarily for a single command, then remove it |
| Assuming DCG inspects commands inside scripts | DCG only inspects direct Bash tool invocations, not contents of ./deploy.sh |
Blocking git branch -d (lowercase) thinking it is destructive | Lowercase -d is safe (merge-checked); only uppercase -D force-deletes |
| Not enabling database or cloud packs for production environments | Configure relevant packs in ~/.config/dcg/config.toml for your stack |
| Expecting DCG to stop malicious actors | DCG catches honest mistakes; determined users can always bypass the hook |
Running cargo install without nightly toolchain | DCG requires Rust nightly (edition 2024); use cargo +nightly install |
Delegation
- Audit which destructive commands an agent session has attempted: Use
Exploreagent - Set up DCG with custom packs for a new project environment: Use
Taskagent - Plan a layered safety architecture combining DCG with other guardrails: Use
Planagent
References
- Command detection and processing pipeline
- Pack configuration and environment variables
- Installation and Claude Code setup
- Safety patterns and edge cases
- Troubleshooting and FAQ
Command Detection and Processing Pipeline
Why DCG Exists
AI coding agents are powerful but fallible. They can accidentally run destructive commands:
- "Let me clean up the build artifacts" results in
rm -rf ./src(typo) - "I'll reset to the last commit" results in
git reset --hard(destroys uncommitted changes) - "Let me fix the merge conflict" results in
git checkout -- .(discards all modifications) - "I'll clean up untracked files" results in
git clean -fd(permanently deletes untracked files)
DCG intercepts dangerous commands _before_ execution and blocks them with a clear explanation.
Processing Pipeline
+-------------------------------------------------------------+
| Claude Code |
| Agent executes `rm -rf ./build` |
+------------------------+------------------------------------+
|
v PreToolUse hook (stdin: JSON)
+-------------------------------------------------------------+
| dcg |
| +------------+ +-----------+ +---------------+ |
| | Parse |--->| Normalize |--->| Quick Reject | |
| | JSON | | Command | | Filter | |
| +------------+ +-----------+ +-------+-------+ |
| | |
| +------------------------+ |
| v |
| +------------------------------------------------------+ |
| | Pattern Matching | |
| | 1. Check SAFE_PATTERNS (whitelist) --> Allow | |
| | 2. Check DESTRUCTIVE_PATTERNS -------> Deny | |
| | 3. No match -------------------------> Allow | |
| +------------------------------------------------------+ |
+------------------------+------------------------------------+
|
v stdout: JSON (deny) or empty (allow)Stage 1: JSON Parsing
- Reads hook input from stdin
- Validates Claude Code's
PreToolUseformat - Non-Bash tools immediately allowed
Stage 2: Command Normalization
- Strips absolute paths:
/usr/bin/git statusbecomesgit 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 to allow)
- Destructive patterns checked second (match to deny)
- No match results in default allow
Critical Design Principles
Whitelist-First Architecture
Safe patterns are checked _before_ destructive patterns:
git checkout -b feature # Matches SAFE "checkout-new-branch" --> ALLOW
git checkout -- file.txt # No safe match, matches DESTRUCTIVE --> DENYFail-Safe Defaults (Default-Allow)
Unrecognized commands are allowed by default to ensure the hook never breaks legitimate workflows.
Zero False Negatives Philosophy
The pattern set prioritizes never allowing dangerous commands over avoiding false positives.
Performance Optimizations
| Optimization | Technique |
|---|---|
| Lazy Static | Regex patterns compiled once via LazyLock |
| SIMD Quick Reject | memchr crate for CPU vector instructions (SSE2/AVX2/NEON) |
| Aho-Corasick | Multi-pattern matching in O(n) regardless of keyword count |
| Early Exit | Safe match returns immediately |
| Zero-Copy JSON | serde_json operates on input buffer |
| Zero-Allocation | Cow<str> for path normalization |
| Release Profile | opt-level="z", LTO, single codegen unit, stripped symbols |
Result: Sub-millisecond execution for typical commands.
Pattern Counts
| Type | Count |
|---|---|
| Safe patterns (whitelist) | 34 |
| Destructive patterns (blacklist) | 16 |
Installation and Claude Code Setup
Quick Install (Recommended)
curl -fsSL "https://raw.githubusercontent.com/Dicklesworthstone/destructive_command_guard/master/install.sh?$(date +%s)" | bash
# Easy mode: auto-update PATH
curl -fsSL "https://raw.githubusercontent.com/Dicklesworthstone/destructive_command_guard/master/install.sh?$(date +%s)" | bash -s -- --easy-mode
# System-wide (requires sudo)
curl -fsSL "https://raw.githubusercontent.com/Dicklesworthstone/destructive_command_guard/master/install.sh?$(date +%s)" | sudo bash -s -- --systemFrom Source (Requires Rust Nightly)
Requires Rust nightly toolchain (minimum Rust 1.85, edition 2024). The repository includes a rust-toolchain.toml that automatically selects the correct toolchain.
cargo +nightly install --git https://github.com/Dicklesworthstone/destructive_command_guard destructive_command_guardPrebuilt Binaries
Available for: Linux x86_64, Linux ARM64, macOS Intel, macOS Apple Silicon, Windows
Claude Code Configuration
Add to ~/.claude/settings.json (global) or .claude/settings.json (project):
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "dcg"
}
]
}
]
}
}Important: Restart Claude Code after adding the hook. Alternatively, use the /hooks interactive menu to add hooks (takes effect immediately without restart).
Hook settings can be placed in three locations:
| Location | Scope | Committed |
|---|---|---|
~/.claude/settings.json | All projects | No |
.claude/settings.json | Single project | Yes |
.claude/settings.local.json | Single project | No |
Claude Code Hook API Context
DCG uses the PreToolUse hook event, which fires before any tool call. Claude Code supports additional hook events and types that may be relevant for layered safety:
| Hook Event | When It Fires | Relevant to DCG |
|---|---|---|
PreToolUse | Before tool execution (can block) | Primary DCG hook |
PostToolUse | After tool succeeds | Audit logging |
PostToolUseFailure | After tool fails | Error tracking |
PermissionRequest | When permission dialog appears | Alternative to PreToolUse |
Stop | When Claude finishes responding | Session summary |
SubagentStop | When subagent finishes | Subagent safety |
Hook types beyond "type": "command" (what DCG uses):
"type": "prompt"-- sends hook input to a Claude model for yes/no judgment"type": "agent"-- spawns a subagent that can read files and run tools to verify conditions
DCG uses "type": "command" for deterministic, sub-millisecond blocking. Prompt/agent hooks are useful for complementary checks requiring judgment.
Structured JSON Output
In addition to exit codes, PreToolUse hooks can return structured JSON on stdout for finer control:
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "git reset --hard destroys uncommitted changes. Use git stash first."
}
}DCG uses exit codes (simpler, faster) rather than JSON output, but the JSON format supports three decisions: "allow", "deny", and "ask" (escalate to user).
CLI Usage
Test commands manually:
# Show version with build metadata
dcg --version
# Test a command
echo '{"tool_name":"Bash","tool_input":{"command":"git reset --hard"}}' | dcgExit Codes
| Code | Meaning |
|---|---|
0 | Command is safe, proceed |
2 | Command is blocked, do not execute |
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" |
Pack Configuration and Environment Variables
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
# ~/.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\ |
DCG_BYPASS=1 | Bypass DCG entirely (escape hatch) |
Safety Patterns and Edge Cases
What DCG 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 | Force-deletes without merge check |
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 DCG Allows
Always Safe Git Operations
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
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, does not 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
git push --force-with-lease # ALLOWED - refuses if remote has unseen commits
git push --force # BLOCKED - can overwrite others' workEdge Cases Handled
Path Normalization
/usr/bin/git reset --hard # Blocked
/usr/local/bin/git checkout -- . # Blocked
/bin/rm -rf /home/user # BlockedFlag Ordering Variants
rm -rf /path # Combined flags
rm -fr /path # Reversed order
rm -r -f /path # Separate flags
rm --recursive --force /path # Long flagsAll variants are handled.
Shell Variable Expansion
rm -rf $TMPDIR/build # Allowed (temp)
rm -rf ${TMPDIR}/build # Allowed
rm -rf "$TMPDIR/build" # Allowed
rm -rf "${TMPDIR:-/tmp}/build" # AllowedStaged vs Worktree Restore
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)Security Considerations
What DCG Protects Against
- Accidental data loss from
git checkout --orgit reset --hard - Remote history destruction from force pushes
- Stash loss from
git stash drop/clear - Filesystem accidents from
rm -rfoutside temp directories
What DCG Does NOT Protect Against
- Malicious actors (can bypass the hook)
- Non-Bash commands (Python/JavaScript file writes, API calls)
- Committed but unpushed work
- Commands inside scripts (
./deploy.shcontents not inspected)
Threat Model
DCG assumes the AI agent is well-intentioned but fallible. It catches honest mistakes, not adversarial attacks.
Troubleshooting and FAQ
Troubleshooting
Hook Not Blocking Commands
1. Verify ~/.claude/settings.json has hook configuration 2. Restart Claude Code (or use /hooks menu to reload) 3. Check matcher is case-sensitive: "Bash" not "bash" 4. Test manually:
echo '{"tool_name":"Bash","tool_input":{"command":"git reset --hard"}}' | dcg
echo $? # Should print 25. Enable verbose mode in Claude Code with Ctrl+O to see hook output in transcript 6. Run claude --debug for full execution details including which hooks matched
Hook Blocking Safe Commands
1. Check if there is an edge case not covered 2. File a GitHub issue 3. Temporary bypass: DCG_BYPASS=1 or run command manually
Processing Timeout
DCG enforces a 200ms maximum processing time. If a command exceeds this threshold, it is immediately allowed with a warning logged. This prevents any single hook invocation from blocking the agent indefinitely.
FAQ
Q: Why block `git branch -D` but allow `git branch -d`?
Lowercase -d only deletes branches fully merged. Uppercase -D force-deletes regardless of merge status, potentially losing commits.
Q: Why is `git push --force-with-lease` allowed?
Force-with-lease refuses to push if the remote has commits you have not seen, preventing accidental overwrites.
Q: Why block all `rm -rf` outside temp directories?
Recursive forced deletion is extremely dangerous. A typo or wrong variable can delete critical files. Temp directories are designed to be ephemeral.
Q: What if I really need to run a blocked command?
DCG instructs the agent to ask for permission. Run the command manually in a separate terminal after making a conscious decision.
Integration with Claude Code
DCG integrates natively as a PreToolUse hook in Claude Code. The hook receives JSON on stdin containing tool_name and tool_input fields, and returns structured JSON output or uses exit codes to control execution:
- Exit code 0: Command is safe, proceed with execution
- Exit code 2: Command is blocked, Claude Code prevents execution and receives the reason
The hook configuration can be placed in any of the three Claude Code settings files:
~/.claude/settings.json(user-global).claude/settings.json(project-specific, committed).claude/settings.local.json(project-specific, not committed)
DCG also provides a dcg scan subcommand that extracts executable command contexts from files and evaluates them using the same pattern engine, suitable for CI integration and repository auditing.
Agent Compatibility
| Agent | Hook Support |
|---|---|
| Claude Code | Full PreToolUse hook support (primary target) |
| Aider | No PreToolUse interception; use git pre-commit hook instead |
| Codex CLI | Post-execution hooks only; no pre-execution command interception |
| Continue | No shell command interception hooks; use git pre-commit hook |
For agents without PreToolUse support, install DCG as a git pre-commit hook for partial protection (covers git operations only).