TL;DR
Destructive Command Guard (dcg) is a Rust-based PreToolUse hook that intercepts shell commands from AI coding agents and blocks the ones that would destroy your work — git reset --hard, rm -rf ./src, DROP TABLE users, kubectl delete namespace production, terraform destroy, docker system prune — before they execute. It’s currently trending on GitHub with 5,236 stars and 1,410 added this week, and it plugs into Claude Code, Codex CLI 0.125.0+, Gemini CLI, GitHub Copilot CLI, VS Code Copilot Chat, Cursor, Hermes, Grok, and Antigravity (agy) out of the box.
If you’ve spent any time letting an AI agent run shell commands autonomously, you already know the pitch. Everyone in the space has a story about a Claude Code session that decided the fastest way to “fix” a merge conflict was git reset --hard HEAD~5. dcg is the deterministic hook layer that makes that class of failure impossible instead of merely unlikely.
Key facts:
- 5,236 GitHub stars, 1,410 this week, currently trending on the Rust chart
- Sub-millisecond latency via SIMD-accelerated pattern matching (you won’t feel it)
- 50+ modular “packs” covering databases, Kubernetes, Docker, AWS/GCP/Azure, Terraform, storage, CDNs, CI/CD
- Heredoc + inline-script scanning — catches
python -c "os.remove(...)"and embedded bash inside heredocs - Context-aware — blocks
rm -rf /(execution) but ignoresgrep "rm -rf" audit.log(data) - Native Codex support — not just a Claude-shaped compat shim; speaks Codex’s
hookSpecificOutputdenial format - Bounded failure policy — analysis timeouts become explicit review-or-block outcomes, not silent passes
- Scan mode for CI — pre-commit hook to catch dangerous commands during code review
- Custom license, Linux / macOS / Windows (WSL and native PowerShell installer)
The problem is not hypothetical
If you’ve read any of the r/ClaudeAI, r/cursor or r/LocalLLaMA threads from the last six months, you’ve seen the same pattern: an agent, mid-task, decides the tidy way out of a broken state is to nuke it. git clean -fdx. rm -rf node_modules && rm -rf .git. git reset --hard origin/main on a branch with two hours of uncommitted work. DROP DATABASE dev. In one particularly cited case, an agent ran git reset --hard HEAD~10 inside a repo where the “recovery” branch was garbage.
The vendors’ answer to this has been “add hooks.” Claude Code shipped PreToolUse hooks first. Codex CLI 0.125.0+ picked up a very similar contract. Gemini CLI and Copilot CLI followed. Cursor has its own hooks.json. Grok added ~/.grok/hooks/. Antigravity (agy) reuses Gemini’s config. The mechanism exists everywhere — the problem is that writing a good hook is a whole subproject: parse the command, model the semantics, handle heredocs, avoid false positives on things like grep "rm -rf", and keep latency under a millisecond so the agent loop stays snappy.
That’s the gap dcg fills. It’s the hook you’d write if you had six months to write it — and its author (Jeffrey Emanuel, who has been publishing agent-tooling gists on and off through the year) plus the Rust port by Darin Gordon actually did.
Install in one command
The whole thing is a static Rust binary. The install script auto-detects your platform, downloads the binary, verifies checksums, and wires up every AI agent hook it can find on the box:
# One-line install (Linux / macOS / WSL)
curl -fsSL "https://raw.githubusercontent.com/Dicklesworthstone/destructive_command_guard/main/install.sh?$(date +%s)" \
| bash -s -- --easy-mode
On native Windows:
& ([scriptblock]::Create((irm "https://raw.githubusercontent.com/Dicklesworthstone/destructive_command_guard/main/install.ps1"))) `
-EasyMode -Verify
--easy-mode puts dcg on your PATH, runs a self-test, and configures the hooks it detects — Claude Code, Codex CLI, Gemini CLI, GitHub Copilot CLI (at the user level under %COPILOT_HOME%\hooks), Cursor, Hermes, and Grok. The Windows installer also verifies a mandatory SHA256, an optional minisign signature, and a Sigstore/cosign bundle when both are present. That’s a level of supply-chain hygiene that is genuinely rare for a Rust CLI at this stage.
What it blocks by default
Zero config, no config.toml, just installed:
core.filesystem— dangerous recursivermoutside literal temp subdirectories (always on, cannot be disabled)core.git— destructive git commands that lose uncommitted work, rewrite history, or destroy stashes (always on, cannot be disabled)system.disk—mkfs,dd-to-device,fdisk,parted,mdadm,wipefs, LVM removal (on by default)
On Windows, two more packs are default-on to catch native-Windows equivalents: windows.filesystem (del /s, rd /s, Remove-Item -Recurse, format) and windows.system (vssadmin delete shadows, diskpart, Format-Volume, bcdedit /delete).
Everything else — databases, containers, cloud CLIs, Kubernetes, Terraform — is opt-in. You turn packs on in ~/.config/dcg/config.toml:
[packs]
enabled = [
"database.postgresql", # DROP TABLE, TRUNCATE, dropdb
"database.mysql", # equivalent for MySQL/MariaDB
"database.redis", # FLUSHALL, FLUSHDB, mass delete
"kubernetes.kubectl", # delete namespace, drain
"kubernetes.helm", # uninstall, rollback --no-dry-run
"containers.docker", # system prune, volume prune, force rm
"containers.compose", # down -v (which nukes volumes)
"cloud.aws", # terminate-instances, delete-db-instance
"cloud.gcp", # gsutil rm -r, sql instances delete
"infrastructure.terraform", # destroy, taint, apply --auto-approve
"storage.s3", # bucket rm, sync --delete
]
That’s ~10 lines of TOML for the class of “one-line catastrophes” that dominate the post-mortems. Category IDs like "database" expand to every database.* sub-pack, so you can opt in broadly and then drop the sub-packs you don’t want with disabled = ["database.redis"].
What the block looks like
The agent tries to run something dangerous, and instead of executing, the hook returns a denial to the agent and prints a rich panel on stderr for the human watching:
════════════════════════════════════════════════════════════════
BLOCKED dcg
────────────────────────────────────────────────────────────────
Reason: git reset --hard destroys uncommitted changes
Command: git reset --hard HEAD~5
Tip: Consider using 'git stash' first to save your changes.
════════════════════════════════════════════════════════════════
The important detail: dcg puts the machine-readable denial on stdout (that’s what the agent parses to know it was blocked) and keeps the human-readable panel on stderr. That means the agent’s next-turn reasoning includes “the previous command was blocked because git reset --hard destroys uncommitted changes — try git stash first.” In practice this often produces a better follow-up plan than just erroring out.
If you want to know why something would be blocked before you run it:
$ dcg explain "kubectl delete namespace production"
It prints the matching rule, the pack, and the suggested alternative. dcg packs and dcg packs --verbose list every pack with descriptions and pattern counts. There’s a real man-page-quality reference here, not just a wall of regexes.
Agent-specific profiles
dcg detects which agent is invoking it and can apply per-agent configuration. This is where the real ergonomics live:
# Trust Claude Code more — wider allowlist, fewer packs
[agents.claude-code]
trust_level = "high"
additional_allowlist = ["npm run build", "cargo test", "pnpm test"]
disabled_packs = ["kubernetes"]
# Restrict unknown agents — extra rules, no allowlist bypass
[agents.unknown]
trust_level = "low"
extra_packs = ["strict_git", "database"]
disabled_allowlist = true
Note the honest documentation: trust_level is advisory (recorded in JSON output and logs, useful for audit) — the actual behavior comes from disabled_packs, extra_packs, additional_allowlist, and disabled_allowlist. That’s the kind of clarity you rarely see in agent-safety tooling, where “trust level” is usually a euphemism for “we didn’t decide what this does.”
The escape hatches (and how not to abuse them)
Every guardrail needs a bypass, or people will remove the guardrail. dcg gives you four, in increasing order of scope:
| Method | Scope | How |
|---|---|---|
| Env-var bypass | Single command | DCG_BYPASS=1 <command> |
| Allow-once code | Single command | Copy the short code from the block message, run dcg allow-once <code> |
| Permanent allowlist | Rule or command | dcg allowlist add core.git:reset-hard -r "reason" |
| Remove the hook | All commands | Delete the dcg entry from ~/.claude/settings.json (or equivalent) |
The allow-once code pattern is the interesting one: when a command is blocked, the block message includes a short one-time code, and running dcg allow-once <code> allows exactly that command exactly once. That’s the right ergonomic — it stays out of your way for legitimate one-offs without turning into a permanent hole in your safety net.
Scan mode for CI
The same engine also runs against static files, which turns dcg into a pre-commit / CI check. You can catch a terraform destroy in a proposed script during code review instead of during an outage:
# In a pre-commit hook or GitHub Action
dcg scan scripts/ deploy/
The pack system means your CI can run the same rules as your agent hook, which is a small thing but a real one — no two sources of truth to keep in sync.
Community reception
The reception has been unusually warm for a safety tool, because the pain is universal:
- GitHub trending Rust page: 1,410 stars added this week, sustained top-10 placement since launch
- The installer’s supply-chain hygiene (mandatory SHA256, optional minisign, optional Sigstore/cosign) has been called out repeatedly on X as “how every Rust CLI should ship”
- The Codex-first-class support landed with the Codex CLI 0.125.0 release notes and got picked up quickly by the Codex hooks doc
- The native Grok and Antigravity installers (
dcg install --grok,dcg install --agy) shipped days after those platforms added hook support — turnaround that suggests active maintenance, not a one-shot release
Skeptical reactions cluster around two points: “regex-based blocking will always have false positives” and “an agent that wants to destroy your work will find a way.” The first is mitigated by the context classifier and the allow-once codes. The second is honest — dcg is one deterministic layer, not a full sandbox. If you need process-level isolation, this is complementary to (not a replacement for) something like Bubblewrap, Firejail, or a full VM sandbox.
Honest limitations
- Aider integration is limited to git hooks (Aider doesn’t expose a
PreToolUsehook the way Claude Code does), and Continue support is currently detection-only. If those are your primary agents, you get a subset of the protection. - Regex-based rules can be evaded by a determined agent that constructs commands dynamically (
eval "$(base64 -d <<< ...)"). The heredoc/inline-script scanner catches a lot of this, but it’s not a proof. - The license is custom (not OSI-approved). Read it before you deploy at a company that cares — it’s permissive in practice, but “custom license” is worth a review.
- Config lives in one user file. If you want per-repo overrides, you get them via allowlists and per-agent profiles, not per-directory configs.
- Windows PowerShell requires the native
.exe. WSL works, but if your team is on native PowerShell you need theinstall.ps1path. - Not a sandbox. It cannot stop an agent that has already been compromised at a lower level. Treat it as one belt-and-suspenders layer, not the only one.
FAQ
Q: Does dcg slow down my agent loop?
Sub-millisecond in the common case. The three-tier pipeline uses SIMD-accelerated prefilter for the vast majority of commands (which contain no dangerous keywords at all) and reserves full regex evaluation for the small subset that might match. There are published benchmarks in the repo’s benches/ and perf/baselines/ directories, and the numbers are dominated by process-spawn overhead, not dcg itself.
Q: How does dcg compare to just setting --dangerously-skip-permissions=false in Claude Code?
Claude’s permission prompt is a human-in-the-loop control — it interrupts you and asks “run this?” dcg is a deterministic policy control — it blocks without asking, based on rules that don’t depend on your attention being on the terminal at the moment. They’re complementary. Use both: permission prompts for the ambiguous stuff, dcg for the class of commands that should never run regardless of who’s watching.
Q: What about sudo rm -rf /? Does it catch obfuscated variants?
Yes to both, and the context classifier is the interesting part. dcg distinguishes execution contexts (rm -rf /, sudo rm -rf /*, find / -delete) from data contexts (grep "rm -rf" audit.log, echo "rm -rf"). The heredoc scanner catches embedded scripts (bash <<'EOF' \n rm -rf / \n EOF) and -c inline strings (python -c "os.system('rm -rf /')", sh -c "rm -rf /"). Determined obfuscation via eval "$(base64 -d ...)" still gets through — no regex-based tool can fully solve that — but the common failure modes are covered.
Q: Can I use dcg without any AI agents, just as a general safety net?
Yes. The install script wires up hooks for detected agents, but the binary itself is a general-purpose command-filtering shell wrapper. Some users report running it as a shell function that wraps every interactive command, catching human git reset --hard typos as well as agent ones.
Q: Which agent gets the best integration today?
Claude Code and Codex CLI 0.125.0+ are first-class — both get proper PreToolUse output formats and both correctly propagate the denial back into the agent’s context. Gemini CLI, Copilot CLI, Cursor, Hermes, Grok, and Antigravity are all supported with native config paths. OpenCode and Pi have community-maintained integrations. Aider and Continue are the partial ones (see limitations above).
Should you use it?
If you’re already running Claude Code, Codex CLI, Gemini CLI, Copilot CLI, or Cursor with any level of auto-approval — yes. The install is one command, the default rules block the destructive commands you actually care about, and the false-positive rate on the defaults is genuinely low. The allow-once mechanism means the ergonomic cost of a false positive is a single line, not a broken session.
If you’re still doing every action through explicit human approval — you already have your safety net, and dcg is a redundant belt. Even then, the CI scan mode is a small, high-value add: it catches the terraform destroy in a proposed migration script during code review, which is exactly the moment before the blast radius gets large.
The larger pattern here is worth noticing. The first year of AI coding agents was “how do we make them powerful enough to be useful?” The second year is “how do we make them safe enough to run unattended?” Deterministic pre-tool hooks — the mechanism dcg uses — are the answer that’s converging across every major agent platform. dcg is the reference implementation of that pattern for shell commands, and it’s the one you should reach for before writing your own.
Links
- GitHub: Dicklesworthstone/destructive_command_guard
- Docs: Agent integration reference
- Codex integration: docs/codex-integration.md
- Pack index: docs/packs/README.md
- Original Python prototype: Jeffrey Emanuel’s gist