AI Agent Safety Hook - blocks dangerous commands before execution
Repo: https://github.com/Dicklesworthstone/destructive_command_guard Learned: 2026-01-18 16:01
Destructive Command Guard (dcg) is a high-performance safety hook that intercepts and blocks dangerous commands before AI coding agents can execute them. Born from real pain: AI agents like Claude Code, Gemini CLI, and Aider occasionally run catastrophic commands like git reset --hard, rm -rf ./src, or DROP TABLE users—destroying hours of uncommitted work in seconds.
Key Insight: Three-tier pipeline with SIMD-accelerated quick-reject means 95%+ of commands pass through in <10μs. Only commands containing dangerous keywords proceed to expensive regex matching.
| Item | Value |
|---|---|
| Install | curl -fsSL "https://raw.githubusercontent.com/.../install.sh" | bash -s -- --easy-mode |
| Entry point | src/main.rs (CLI), src/hook.rs (Claude Code integration) |
| Key files | evaluator.rs, context.rs, heredoc.rs, packs/ |
| Language | Rust |
| Supports | Claude Code, Gemini CLI, Aider, any MCP-compatible agent |
The tool acts as a pre-execution firewall. When an AI agent attempts to run a shell command, dcg inspects it in sub-millisecond time, determines if it matches any destructive patterns, and either allows it silently or blocks it with a clear explanation and safer alternatives.
It supports 49+ modular security packs covering:
- Databases: PostgreSQL, MySQL, MongoDB, Redis
- Cloud: AWS, GCP, Azure
- Containers: Docker, Kubernetes, Helm
- CI/CD: GitHub Actions, GitLab CI, Jenkins
- Core: git, rm, system commands
Also scans heredocs and inline scripts (e.g., python -c "os.remove(...)") using AST-based analysis.
Three-tier pipeline optimized for speed:
Command → Tier 1: Quick Reject (<10μs) → Tier 2: Context Classification → Tier 3: Full Regex
↓ no keywords ↓ data only ↓ safe pattern
ALLOW ALLOW ALLOW
- Quick Reject: SIMD-accelerated keyword matching. No keywords = pass through
- Context Classification: Mark spans as
Executed,Data,InlineCode,HeredocBody - Full Pattern Matching: Only on executable spans, against safe/destructive patterns
Fail-open philosophy: If analysis times out or fails to parse, command is allowed rather than blocking workflow.
| Component | Purpose |
|---|---|
hook.rs |
Claude Code/Gemini CLI hook protocol handler |
evaluator.rs |
Core decision engine—normalizes, matches, verdicts |
heredoc.rs |
Three-tier heredoc/inline-script detection |
ast_matcher.rs |
Tree-sitter AST matching for embedded code |
context.rs |
Span classification (Executed vs Data) |
packs/ |
49+ modular security packs |
scan.rs |
Repository scanning for CI/pre-commit |
config.rs |
Layered config (env > project > user > defaults) |
pending_exceptions.rs |
Allow-once system with short codes |
allowlist.rs |
Permanent exception management |
// Tier 1: Quick reject via keyword presence (<10μs)
pack_aware_quick_reject(command, &enabled_keywords)
// Tier 2: Context classification
let spans = classify_command(command); // Marks quoted strings as Data
// Tier 3: Full regex matching only on executable spansWhy clever: 95%+ of commands exit at tier 1 without memory allocation.
pub enum SpanKind {
Executed, // Must check patterns
Data, // Skip (quoted strings)
InlineCode, // bash -c "..." content - MUST check
HeredocBody, // Escalate to AST analysis
}Why clever: Eliminates false positives like git commit -m "Fix rm -rf detection" by recognizing quoted string is data.
Command → Tier 1: Trigger (<100μs) → Tier 2: Extract (<1ms) → Tier 3: AST (<5ms)
Why clever: Catches python -c "import os; os.system('rm -rf /')" that would bypass regex.
Pack {
id: "core.git",
keywords: &["git"], // Quick-reject gate
safe_patterns: vec![/* git checkout -b is safe */],
destructive_patterns: vec![/* git reset --hard is blocked */],
}Why clever: Packs are keyword-gated. Kubernetes pack only activates if kubectl appears.
| Package | Why |
|---|---|
fancy-regex + regex |
Pattern matching with lookbehind support |
aho-corasick + memchr |
SIMD multi-pattern string matching |
ast-grep-core |
Tree-sitter AST parsing for heredocs |
serde + serde_json |
Hook protocol serialization |
clap |
CLI parsing |
rusqlite |
Local telemetry database |
ratatui |
TUI output |
┌─────────────────┐ JSON Request ┌─────────────────┐
│ Claude Code │ ──────────────────────▶│ dcg │
│ │ {tool: "Bash", │ (hook.rs) │
│ wants to run: │ command: "git │ │
│ git reset │ reset --hard"} │ evaluates... │
│ --hard │ │ │
└─────────────────┘ └────────┬────────┘
│
◀──────────────────────────┘
JSON Response
// dcg returns nothing or empty - command proceeds{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "BLOCKED by dcg...",
"ruleId": "core.git:reset-hard",
"packId": "core.git",
"severity": "critical",
"allowOnceCode": "abc12",
"remediation": {
"safeAlternative": "git stash",
"explanation": "git reset --hard discards all uncommitted changes...",
"allowOnceCommand": "dcg allow-once abc12"
}
}
}BLOCKED by dcg
Reason: Destructive git command that discards uncommitted changes
Rule: core.git:reset-hard
Command: git reset --hard
Safe alternative: git stash
If this operation is truly needed, ask the user for explicit
permission and have them run the command manually.
To allow once: dcg allow-once abc12
| Aspect | How It Works |
|---|---|
| Hook protocol | Claude Code's PreToolUse hook - intercepts before execution |
| Decision | "allow" = silent pass, "deny" = blocked with reason |
| Allow-once | Short code (abc12) lets user bypass once if intentional |
| Remediation | Suggests safer alternatives (e.g., git stash instead of reset --hard) |
| AI-friendly | Returns ruleId, packId, severity so AI understands why |
# Install dcg
curl -fsSL "https://raw.githubusercontent.com/Dicklesworthstone/destructive_command_guard/master/install.sh" | bash -s -- --easy-mode
# dcg auto-registers as PreToolUse hook
# Every Bash command goes through dcg before execution
# Test manually:
echo '{"tool_name":"Bash","tool_input":{"command":"git reset --hard"}}' | dcg hookThe magic: Claude Code never executes the command if dcg returns "deny". It just shows the block message to the user.
- GitHub: https://github.com/Dicklesworthstone/destructive_command_guard
- Author: Dicklesworthstone
- License: MIT
This is exactly what we need for multi-agent safety! Could integrate with:
- MAW (Multi-Agent Workflow) as safety layer
- Oracle as pattern repository for custom rules
- Claude Code hooks in our workflow
Potential: Fork and add Oracle-aware patterns, sync with our philosophy of "Nothing is Deleted" (prevent destructive commands that violate this).