claudeers.
// Uncategorized / Others

destructive_command_guard

The Destructive Command Guard (dcg) is for blocking dangerous git and shell commands from being executed by agents.

// Uncategorized / Others[ cli ][ api ][ desktop ][ web ][ mobile ][ claude ]#claude#ai-agents#cli#developer-tools#git#rust#safety#uncategorizedNOASSERTION$open-sourceupdated 1 day ago

Install with your AI

Paste into Claude Code, Cursor, or any agent — it reads the repo and wires the tool into your project.

Install and set up destructive_command_guard (claude-skill project) into my current project.
Found on https://claudeers.com/destructivecommandguard
Repo: https://github.com/Dicklesworthstone/destructive_command_guard
Homepage/docs: —
Detected install method: claude-skill → # copy this skill into .claude/skills/destructive-command-guard/
Category: uncategorized. Platforms: cli, api, desktop, web, mobile.
Read the repo's README for exact setup and env vars, then install it and wire it into my project.

Claudeers Health Verdict:
unknown; community-verified: false. Confirm the source before running anything.
// or install directly (claude-skill)
# copy the skill dir into your project:
# .claude/skills/destructive-command-guard/   (or ~/.claude/skills/destructive-command-guard/ for all projects)
// or clone
git clone https://github.com/Dicklesworthstone/destructive_command_guard

dcg (Destructive Command Guard)

Destructive Command Guard - Protecting your code from accidental destruction

A high-performance hook for AI coding agents that blocks destructive commands before they execute, protecting your work from accidental deletion across Claude Code, Codex CLI, Gemini CLI, Copilot, Cursor, Hermes Agent, Grok (xAI), and related tools.

Supported: Claude Code, Codex CLI 0.125.0+, Gemini CLI, GitHub Copilot CLI, Cursor IDE, Hermes Agent, Grok (xAI) (native ~/.grok/hooks/ plus Claude compatibility layer), Antigravity CLI (agy) (native ~/.gemini/config/hooks.json via dcg install --agy), OpenCode (via community plugin), Pi (via extension recipe), Aider (limited—git hooks only), Continue (detection only)

Quick Install

curl -fsSL "https://raw.githubusercontent.com/Dicklesworthstone/destructive_command_guard/main/install.sh?$(date +%s)" | bash -s -- --easy-mode

Works on Linux, macOS, and Windows via WSL. Auto-detects your platform, downloads the right binary, and configures supported agent hooks including Claude Code, Codex CLI, Gemini CLI, GitHub Copilot CLI, Cursor IDE, Hermes Agent, and Grok (xAI) (via dcg install --grok for a native ~/.grok/hooks/dcg.json, or via the Claude compatibility layer automatically picked up by Grok). For native Windows, use the PowerShell installer below.

Windows (native, PowerShell)

& ([scriptblock]::Create((irm "https://raw.githubusercontent.com/Dicklesworthstone/destructive_command_guard/main/install.ps1"))) -EasyMode -Verify

Installs native dcg.exe, verifies the SHA256 checksum (and the Sigstore/cosign signature when cosign is present), adds it to your User PATH (-EasyMode), runs a self-test (-Verify), and configures detected agent hooks for Claude Code, Codex CLI, Gemini CLI, GitHub Copilot CLI, Cursor IDE, and Hermes Agent. Copilot hooks are repo-local, so run the installer from each protected repo or use -EasyMode/-Force intentionally. On Windows the windows.filesystem and windows.system packs are on by default, so del /s, rd /s, Remove-Item -Recurse -Force, format, and vssadmin delete shadows are blocked out of the box. Pin a version with -Version vX.Y.Z.


TL;DR

The Problem: AI coding agents (Claude, Codex, Gemini, Copilot, etc.) occasionally run catastrophic commands like git reset --hard, rm -rf ./src, or DROP TABLE users—destroying hours of uncommitted work in seconds.

The Solution: dcg is a high-performance hook that intercepts destructive commands before they execute, blocking them with clear explanations and safer alternatives.

Why Use dcg?

FeatureWhat It Does
Zero-Config ProtectionBlocks dangerous git/filesystem commands out of the box
50+ Security PacksDatabases, Kubernetes, Docker, AWS/GCP/Azure, Terraform, and more
Sub-Millisecond LatencySIMD-accelerated filtering—you won't notice it's there
Heredoc/Inline Script ScanningCatches python -c "os.remove(...)" and embedded shell scripts
Smart Context DetectionWon't block grep "rm -rf" (data) but will block rm -rf / (execution)
Rich Terminal OutputHuman-readable denial panels, rule context, and suggestions on stderr
Agent-Safe StreamsMachine-readable hook output stays on stdout while rich UI stays on stderr
Native Codex SupportCodex CLI 0.125.0+ uses the strict exit-code-2 + stderr denial path Codex expects
Graceful DegradationPlain output for CI, pipes, dumb terminals, and no-color environments
Scan Mode for CIPre-commit hooks and CI integration to catch dangerous commands in code review
Fail-Open DesignNever blocks your workflow due to timeouts or parse errors
Explain Modedcg explain "command" shows exactly why something is blocked

Quick Example

# AI agent tries to run:
$ git reset --hard HEAD~5

# dcg intercepts and blocks:
════════════════════════════════════════════════════════════════
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.
════════════════════════════════════════════════════════════════

Enable More Protection

# ~/.config/dcg/config.toml
[packs]
enabled = [
    "database.postgresql",    # Blocks DROP TABLE, TRUNCATE
    "kubernetes.kubectl",     # Blocks kubectl delete namespace
    "cloud.aws",              # Blocks aws ec2 terminate-instances
    "containers.docker",      # Blocks docker system prune
]

Agent-Specific Profiles

dcg automatically detects which AI coding agent is invoking it and can apply agent-specific configuration. The trust_level field is an advisory label recorded in JSON output and logs — it does not directly change rule evaluation. Behavioral differences come from the other profile fields:

OptionEffect
disabled_packsRemoves rule packs from evaluation
extra_packsAdds rule packs to evaluation
additional_allowlistAdds command patterns that bypass deny rules
disabled_allowlistWhen true, ignores all allowlist entries
# Trust Claude Code more — wider allowlist, fewer packs
[agents.claude-code]
trust_level = "high"
additional_allowlist = ["npm run build", "cargo test"]
disabled_packs = ["kubernetes"]

# Restrict unknown agents — extra rules, no allowlist bypass
[agents.unknown]
trust_level = "low"
extra_packs = ["paranoid"]
disabled_allowlist = true

See docs/agents.md for full documentation on supported agents, trust levels, and configuration options.

Codex Support

dcg now treats Codex CLI as a first-class hook target, not just a Claude-shaped compatibility path. The installer configures Codex CLI 0.125.0+ automatically when it detects codex on PATH or an existing ~/.codex/ directory.

Codex behaviordcg handling
Hook configMerges a PreToolUse Bash hook into ~/.codex/hooks.json
Denied commandExits with code 2, writes the block reason to stderr, and writes no stdout JSON
Allowed commandExits 0 with empty stdout and stderr
Existing hooksPreserves coexisting hooks, keeps dcg first for Bash, and refuses to overwrite malformed JSON
ValidationCovered by subprocess protocol tests plus an opt-in real Codex E2E harness

Codex's hook input is intentionally close to Claude Code's, but Codex rejects unknown fields in hook output. dcg detects Codex payloads from the non-empty turn_id field and switches to Codex's documented stderr denial path so a blocked command is reported as blocked rather than as a failed hook. See docs/codex-integration.md for protocol details, manual probes, and troubleshooting.


Origins & Authors

This project began as a Python script by Jeffrey Emanuel, who recognized that AI coding agents, while incredibly useful, occasionally run catastrophic commands that destroy hours of uncommitted work. The original implementation was a simple but effective hook that intercepted dangerous git and filesystem commands before execution.

  • Jeffrey Emanuel - Original concept and Python implementation (source); substantially expanded the Rust version with the modular pack system (50+ security packs), heredoc/inline-script scanning, the three-tier architecture, context classification, allowlists, scan mode, and the dual regex engine
  • Darin Gordon - Initial Rust port with performance optimizations

The initial Rust port by Darin maintained pattern compatibility with the original Python implementation while adding sub-millisecond execution through SIMD-accelerated filtering and lazy-compiled regex patterns. Jeffrey subsequently expanded the Rust codebase dramatically to add the features described above.

Escape Hatch / Bypass

If dcg is blocking something you genuinely need to run:

MethodScopeHow
Env var bypassSingle commandDCG_BYPASS=1 <command>
Allow-once codeSingle commandCopy the short code from the block message, run dcg allow-once <code>
Permanent allowlistRule or commanddcg allowlist add core.git:reset-hard -r "reason"
Remove the hookAll commandsDelete or comment out the dcg entry in ~/.claude/settings.json (or equivalent for your agent)

DCG_BYPASS=1 disables all protection for that invocation. Use it sparingly and prefer allowlists for recurring needs.

Modular Pack System

dcg uses a modular "pack" system to organize destructive command patterns by category. Packs can be enabled or disabled in the configuration file.

  • Full pack ID index: docs/packs/README.md
  • Canonical descriptions + pattern counts: dcg packs --verbose

Enabled by default (no config file)

With no config file present, dcg enables only the packs that guard against the most catastrophic, unrecoverable mistakes:

  • core.filesystem - Dangerous rm -rf outside temp directories (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, lvm removal, wipefs (on by default; opt out with disabled = ["system.disk"])

On Windows, two additional packs are on by default so a fresh install blocks the catastrophic native-Windows operations with no config:

  • windows.filesystem - cmd del /s, rd /s, format <drive>: and PowerShell Remove-Item -Recurse -Force (and aliases), Clear-Content, Clear-RecycleBin (default-on on Windows only; opt out with disabled = ["windows.filesystem"] or ["windows"])
  • windows.system - vssadmin delete shadows / wmic shadowcopy delete (Volume Shadow Copy destruction), diskpart, Format-Volume, Clear-Disk, Remove-Partition, cipher /w, bcdedit /delete (default-on on Windows only; opt out with disabled = ["windows.system"] or ["windows"])

The broader windows.misc (reg delete, net user /delete, wsl --unregister, robocopy /MIR) and windows.powershell (registry/provider deletes, Remove-LocalUser, Disable-ComputerRestore, Remove-VM) packs are opt-in on every platform. On Unix the windows.* packs are registered but off by default; enable them (e.g. to scan committed .ps1/.cmd scripts in CI) via [packs] enabled = ["windows"].

Every other pack — including database.postgresql and containers.docker — is opt-in and is not active until a config file enables it. Running dcg init writes a starter ~/.config/dcg/config.toml whose [packs] enabled list turns on database.postgresql and containers.docker as common examples, but that is a generated starter config, not the no-config default. Enable any pack below by adding it to [packs] enabled — see Enable More Protection.

Storage Packs

  • storage.s3 - Protects against destructive S3 operations like bucket removal, recursive deletes, and sync --delete.
  • storage.gcs - Protects against destructive GCS operations like bucket removal, object deletion, and recursive deletes.
  • storage.minio - Protects against destructive MinIO Client (mc) operations like bucket removal, object deletion, and admin operations.
  • storage.azure_blob - Protects against destructive Azure Blob Storage operations like container deletion, blob deletion, and azcopy remove.

Remote Packs

  • remote.rsync - Protects against destructive rsync operations like --delete and its variants.
  • remote.scp - Protects against destructive SCP operations like overwrites to system paths.
  • remote.ssh - Protects against destructive SSH operations like remote command execution and key management.

Database Packs

  • database.postgresql - Protects against destructive PostgreSQL operations like DROP DATABASE, TRUNCATE, and dropdb.
  • database.mysql - MySQL/MariaDB guard.
  • database.mongodb - Protects against destructive MongoDB operations like dropDatabase, dropCollection, and remove without criteria.
  • database.redis - Protects against destructive Redis operations like FLUSHALL, FLUSHDB, and mass key deletion.
  • database.sqlite - Protects against destructive SQLite operations like DROP TABLE, DELETE without WHERE, and accidental data loss.
  • database.supabase - Protects against destructive Supabase CLI operations including database resets, migration rollbacks, function/secret/storage deletion, project removal, and infrastructure changes.

Container Packs

  • containers.docker - Protects against destructive Docker operations like system prune, volume prune, and force removal.
  • containers.compose - Protects against destructive Docker Compose operations like down -v which removes volumes.
  • containers.podman - Protects against destructive Podman operations like system prune, volume prune, and force removal.

Kubernetes Packs

  • kubernetes.kubectl - Protects against destructive kubectl operations like delete namespace, drain, and mass deletion.
  • kubernetes.helm - Protects against destructive Helm operations like uninstall and rollback without dry-run.
  • kubernetes.kustomize - Protects against destructive Kustomize operations when combined with kubectl delete or applied without review.

Cloud Provider Packs

  • cloud.aws - Protects against destructive AWS CLI operations like terminate-instances, delete-db-instance, and s3 rm --recursive.
  • cloud.azure - Protects against destructive Azure CLI operations like vm delete, storage account delete, and resource group delete.
  • cloud.gcp - Protects against destructive gcloud operations like instances delete, sql instances delete, and gsutil rm -r.

CDN Packs

  • cdn.cloudflare_workers - Protects against destructive Cloudflare Workers, KV, R2, and D1 operations via the Wrangler CLI.
  • cdn.cloudfront - Protects against destructive AWS CloudFront operations like deleting distributions, cache policies, and functions.
  • cdn.fastly - Protects against destructive Fastly CLI operations like service, domain, backend, and VCL deletion.

API Gateway Packs

  • apigateway.apigee - Protects against destructive Google Apigee CLI and apigeecli operations.
  • apigateway.aws - Protects against destructive AWS API Gateway CLI operations for both REST APIs and HTTP APIs.
  • apigateway.kong - Protects against destructive Kong Gateway CLI, deck CLI, and Admin API operations.

Infrastructure Packs

  • infrastructure.ansible - Protects against destructive Ansible operations like dangerous shell commands and unchecked playbook runs.
  • infrastructure.atmos - Protects against destructive Atmos operations like terraform deploy (auto-approve), clean, destroy, state rm/taint, and helmfile destroy.
  • infrastructure.pulumi - Protects against destructive Pulumi operations like destroy and up with -y (auto-approve).
  • infrastructure.terraform - Protects against destructive Terraform operations like destroy, taint, and apply with -auto-approve.

System Packs

  • system.disk - Protects against destructive disk operations including dd to devices, mkfs, partition table modifications (fdisk/parted), RAID management (mdadm), btrfs filesystem operations, device-mapper (dmsetup), network block devices (nbd-client), and LVM commands (pvremove, vgremove, lvremove, lvreduce, pvmove).
  • system.permissions - Protects against dangerous permission changes like chmod 777, recursive chmod/chown on system directories.
  • system.services - Protects against dangerous service operations like stopping critical services and modifying init configuration.

CI/CD Packs

  • cicd.circleci - Protects against destructive CircleCI operations like deleting contexts, removing secrets, deleting orbs/namespaces, or removing pipelines.
  • cicd.github_actions - Protects against destructive GitHub Actions operations like deleting secrets/variables or using gh api DELETE against /actions endpoints.
  • cicd.gitlab_ci - Protects against destructive GitLab CI/CD operations like deleting variables, removing artifacts, and unregistering runners.
  • cicd.jenkins - Protects against destructive Jenkins CLI/API operations like deleting jobs, nodes, credentials, or build history.

Secrets Management Packs

  • secrets.aws_secrets - Protects against destructive AWS Secrets Manager and SSM Parameter Store operations like delete-secret and delete-parameter.
  • secrets.doppler - Protects against destructive Doppler CLI operations like deleting secrets, configs, environments, or projects.
  • secrets.onepassword - Protects against destructive 1Password CLI operations like deleting items, documents, users, groups, and vaults.
  • secrets.vault - Protects against destructive Vault CLI operations like deleting secrets, disabling auth/secret engines, revoking leases/tokens, and deleting policies.

Platform Packs

  • platform.github - Protects against destructive GitHub CLI operations like deleting repositories, gists, releases, or SSH keys.
  • platform.gitlab - Protects against destructive GitLab platform operations like deleting projects, releases, protected branches, and webhooks.
  • platform.kamal - Protects against destructive Kamal 2.x operations that tear down the stack (kamal remove), delete accessory data directories (kamal accessory remove), drop proxy routing, take the app offline, or prune the images that kamal rollback relies on.
  • platform.modal - Protects against destructive Modal serverless platform operations like recursive volume removal, app stops with --force, and secret deletion.
  • platform.railway - Protects against destructive Railway CLI and Public API operations that can delete projects, environments, services, functions, volumes, variables, or deployments.

DNS Packs

  • dns.cloudflare - Protects against destructive Cloudflare DNS operations like record deletion, zone deletion, and targeted Terraform destroy.
  • dns.generic - Protects against destructive or risky DNS tooling usage (nsupdate deletes, zone transfers).
  • dns.route53 - Protects against destructive AWS Route53 DNS operations like hosted zone deletion and record set DELETE changes.

Email Packs

  • email.mailgun - Protects against destructive Mailgun API operations like domain deletion, route deletion, and mailing list removal.
  • email.postmark - Protects against destructive Postmark API operations like server deletion, template deletion, and sender signature removal.
  • email.sendgrid - Protects against destructive SendGrid API operations like template deletion, API key deletion, and domain authentication removal.
  • email.ses - Protects against destructive AWS Simple Email Service operations like identity deletion, template deletion, and configuration set removal.

Feature Flag Packs

  • featureflags.flipt - Protects against destructive Flipt CLI and API operations.
  • featureflags.launchdarkly - Protects against destructive LaunchDarkly CLI and API operations.
  • featureflags.split - Protects against destructive Split.io CLI and API operations.
  • featureflags.unleash - Protects against destructive Unleash CLI and API operations.

Load Balancer Packs

  • loadbalancer.elb - Protects against destructive AWS Elastic Load Balancing (ELB/ALB/NLB) operations like deleting load balancers, target groups, or deregistering targets from live traffic.
  • loadbalancer.haproxy - Protects against destructive HAProxy load balancer operations like stopping the service or disabling backends via runtime API.
  • loadbalancer.nginx - Protects against destructive nginx load balancer operations like stopping the service or deleting config files.
  • loadbalancer.traefik - Protects against destructive Traefik load balancer operations like stopping containers, deleting config, or API deletions.

Messaging Packs

  • messaging.kafka - Protects against destructive Kafka CLI operations like deleting topics, removing consumer groups, resetting offsets, and deleting records.
  • messaging.nats - Protects against destructive NATS/JetStream operations like deleting streams, consumers, key-value entries, objects, and accounts.
  • messaging.rabbitmq - Protects against destructive RabbitMQ operations like deleting queues/exchanges, purging queues, deleting vhosts, and resetting cluster state.
  • messaging.sqs_sns - Protects against destructive AWS SQS and SNS operations like deleting queues, purging messages, deleting topics, and removing subscriptions.

Monitoring Packs

  • monitoring.datadog - Protects against destructive Datadog CLI/API operations like deleting monitors and dashboards.
  • monitoring.newrelic - Protects against destructive New Relic CLI/API operations like deleting entities or alerting resources.
  • monitoring.pagerduty - Protects against destructive PagerDuty CLI/API operations like deleting services and schedules (which can break incident routing).
  • monitoring.prometheus - Protects against destructive Prometheus/Grafana operations like deleting time series data or dashboards/datasources.
  • monitoring.splunk - Protects against destructive Splunk CLI/API operations like index removal and REST API DELETE calls.

Payment Packs

  • payment.braintree - Protects against destructive Braintree/PayPal payment operations like deleting customers or cancelling subscriptions via API/SDK calls.
  • payment.square - Protects against destructive Square CLI/API operations like deleting catalog objects or customers (which can break payment flows).
  • payment.stripe - Protects against destructive Stripe CLI/API operations like deleting webhook endpoints and customers, or rotating API keys without coordination.

Search Engine Packs

  • search.algolia - Protects against destructive Algolia operations like deleting indices, clearing objects, removing rules/synonyms, and deleting API keys.
  • search.elasticsearch - Protects against destructive Elasticsearch REST API operations like index deletion, delete-by-query, index close, and cluster setting changes.
  • search.meilisearch - Protects against destructive Meilisearch REST API operations like index deletion, document deletion, delete-batch, and API key removal.
  • search.opensearch - Protects against destructive OpenSearch REST API operations and AWS CLI domain deletions.

Backup Packs

  • backup.borg - Protects against destructive borg operations like delete, prune, compact, and recreate.
  • backup.rclone - Protects against destructive rclone operations like sync, delete, purge, dedupe, and move.
  • backup.restic - Protects against destructive restic operations like forgetting snapshots, pruning data, removing keys, and cache cleanup.
  • backup.velero - Protects against destructive velero operations like deleting backups, schedules, and locations.

Windows Packs

Native-Windows (cmd.exe + PowerShell) destructive-command protection. windows.filesystem and windows.system are default-on on Windows (off/opt-in on Unix); windows.misc and windows.powershell are opt-in everywhere. All patterns are case-insensitive.

  • windows.filesystem - Recursive/forced filesystem destruction: cmd del /s, rd /s/rmdir /s, format <drive>:; PowerShell Remove-Item -Recurse -Force (and aliases rm/del/rd/ri), Clear-Content, Clear-RecycleBin. Whitelists PowerShell -WhatIf previews only on cmdlets/aliases that honor it, plus temp-dir deletes.
  • windows.system - Catastrophic disk/system operations: vssadmin delete shadows and wmic shadowcopy delete (Volume Shadow Copy destruction — a ransomware hallmark), diskpart, Format-Volume, Clear-Disk, Remove-Partition, Initialize-Disk/Reset-PhysicalDisk, cipher /w, bcdedit /delete.
  • windows.misc - Registry/account/service/WSL/copy destruction: reg delete, net user|localgroup /delete, sc delete, schtasks /delete, wsl --unregister (destroys a WSL distro), robocopy /MIR (mirror-delete).
  • windows.powershell - Destructive PowerShell cmdlets: registry/provider deletes (Remove-Item HKLM:\, Remove-ItemProperty, Remove-PSDrive), Remove-LocalUser/Remove-LocalGroup, Unregister-ScheduledTask, Disable-ComputerRestore, forced Stop-Computer/Restart-Computer, Remove-VM/Remove-AppxPackage.

Other Packs

  • package_managers - Protects against dangerous package manager operations like publishing packages and removing critical system packages.
  • strict_git - Stricter git protections: blocks all force pushes, rebases, and history rewriting operations.

Enable packs in ~/.config/dcg/config.toml:

[packs]
enabled = [
    # Databases
    "database.postgresql",
    "database.redis",
    "database.supabase",

    # Containers and orchestration
    "containers.docker",
    "kubernetes",  # Enables all kubernetes sub-packs

    # Cloud providers
    "cloud.aws",
    "cloud.gcp",

    # Secrets management
    "secrets.aws_secrets",
    "secrets.vault",

    # CI/CD
    "cicd.jenkins",
    "cicd.gitlab_ci",

    # Messaging
    "messaging.kafka",
    "messaging.sqs_sns",

    # Search engines
    "search.elasticsearch",

    # Backup
    "backup.restic",

    # Platform
    "platform.github",
    "platform.railway",

    # Monitoring
    "monitoring.splunk",
]

Custom Packs

Create your own organization-specific security packs using YAML files. Custom packs let you define patterns for internal tools, deployment scripts, and proprietary systems without modifying dcg.

[packs]
custom_paths = [
    "~/.config/dcg/packs/*.yaml",      # User packs
    ".dcg/packs/*.yaml",               # Project-local packs
]

For detailed pack authoring guide, schema reference, and examples, see docs/custom-packs.md.

Validate your pack before deployment:

dcg pack validate mypack.yaml

Heredoc scanning configuration:

[heredoc]
# Enable scanning for heredocs and inline scripts (python -c, bash -c, etc.).
enabled = true

# Extraction timeout budget (milliseconds).
timeout_ms = 50

# Resource limits for extracted bodies.
max_body_bytes = 1048576
max_body_lines = 10000
max_heredocs = 10

# Optional language filter (scan only these languages). Omit for "all".
# languages = ["python", "bash", "javascript", "typescript", "ruby", "perl", "go"]

# Graceful degradation (hook defaults are fail-open).
fallback_on_parse_error = true
fallback_on_timeout = true

CLI overrides for heredoc scanning:

  • --heredoc-scan / --no-heredoc-scan
  • --heredoc-timeout <ms>
  • --heredoc-languages <lang1,lang2,...>

Heredoc documentation:

  • docs/adr-001-heredoc-scanning.md (architecture and rationale)
  • docs/patterns.md (pattern authoring + inventory)
  • docs/security.md (threat model and incident response)

Heredoc Three-Tier Architecture

Heredoc and inline script scanning uses a three-tier pipeline designed for performance and accuracy:

Command Input
     │
     ▼
┌─────────────────┐
│ Tier 1: Trigger │ ─── No match ──► ALLOW (fast path, <100μs)
│   (RegexSet)    │
└────────┬────────┘
         │ Match
         ▼
┌─────────────────┐
│ Tier 2: Extract │ ─── Error/Timeout ──► ALLOW + fallback check
│   (<1ms)        │
└────────┬────────┘
         │ Success
         ▼
┌─────────────────┐
│ Tier 3: AST     │ ─── No match ──► ALLOW
│   (<5ms)        │ ─── Match ──► BLOCK
└─────────────────┘

Tier 1: Trigger Detection (<100μs)

Ultra-fast regex screening to detect heredoc indicators. Uses a compiled RegexSet for O(n) matching against all trigger patterns simultaneously:

static HEREDOC_TRIGGERS: LazyLock<RegexSet> = LazyLock::new(|| {
    RegexSet::new([
        r"<<-?\s*(?:['\x22][^'\x22]*['\x22]|[\w.-]+)",  // Heredocs
        r"<<<",                                          // Here-strings
        r"\bpython[0-9.]*\b.*\s+-[A-Za-z]*[ce]",        // python -c/-e
        r"\bruby[0-9.]*\b.*\s+-[A-Za-z]*e",             // ruby -e
        r"\bnode(js)?[0-9.]*\b.*\s+-[A-Za-z]*[ep]",     // node -e/-p
        r"\b(sh|bash|zsh)\b.*\s+-[A-Za-z]*c",           // bash -c
        // ... more patterns
    ])
});

Commands without any trigger patterns skip directly to ALLOW—no further processing needed.

Tier 2: Content Extraction (<1ms)

For commands that trigger, extract the actual content to be evaluated:

  • Heredocs: cat <<EOF ... EOF → extracts body between delimiters
  • Here-strings: cat <<< "content" → extracts quoted content
  • Inline scripts: python -c "code" → extracts the code argument

Extraction is bounded by configurable limits:

  • Maximum body size (default: 1MB)
  • Maximum lines (default: 10,000)
  • Maximum heredocs per command (default: 10)
  • Timeout (default: 50ms)
pub struct ExtractionLimits {
    pub max_body_bytes: usize,
    pub max_body_lines: usize,
    pub max_heredocs: usize,
    pub timeout_ms: u64,
}

Tier 3: AST Pattern Matching (<5ms)

Extracted content is parsed using language-specific AST grammars (via tree-sitter/ast-grep) and matched against structural patterns:

// Example: detect subprocess.run with shell=True and rm -rf
let pattern = r#"
    call_expression {
        function: attribute { object: "subprocess" attr: "run" }
        arguments: argument_list {
            contains string { contains "rm -rf" }
            contains keyword_argument { keyword: "shell" value: "True" }
        }
    }
"#;

Recursive Shell Analysis:

When extracted content is itself a shell script (e.g., bash -c "git reset --hard"), Tier 3 recursively extracts inner commands and re-evaluates them through the full pipeline:

if content.language == ScriptLanguage::Bash {
    let inner_commands = extract_shell_commands(&content.content);
    for inner in inner_commands {
        // Re-evaluate inner command against all packs
        if let Some(result) = evaluate_command(&inner, ...) {
            if result.decision == Deny {
                return result; // Block the outer command
            }
        }
    }
}

If you encounter commands that should be blocked, please file an issue.

Environment Variables

Environment variables override config files (highest priority):

  • DCG_PACKS="containers.docker,kubernetes": enable packs (comma-separated)
  • DCG_DISABLE="kubernetes.helm": disable packs/sub-packs (comma-separated)
  • DCG_VERBOSE=0-3: verbosity level (0 = quiet, 3 = trace)
  • DCG_QUIET=1: suppress non-error output
  • DCG_COLOR=auto|always|never: color mode
  • DCG_NO_RICH=1: disable rich terminal formatting and use plain rendering
  • DCG_NO_COLOR=1: disable colored output (same as NO_COLOR)
  • DCG_LEGACY_OUTPUT=1: force plain output paths (same as --legacy-output)
  • DCG_ROBOT=1: enable robot mode for JSON stdout and quiet stderr
  • DCG_HIGH_CONTRAST=1: enable high-contrast output (ASCII borders + monochrome palette)
  • DCG_FORMAT=text|json|sarif: default output format (command-specific — see Output Formats for which values each subcommand actually accepts; real SARIF is dcg scan-only)
  • DCG_FAIL_CLOSED=1: block (deny) on hook input that cannot be parsed, instead of the default fail-open allow (opt-in; see Fail-Open Philosophy)
  • DCG_BYPASS=1: bypass dcg entirely (escape hatch; use sparingly)
  • DCG_CONFIG=/path/to/config.toml: use explicit config file
  • DCG_HEREDOC_ENABLED=true|false: enable/disable heredoc scanning
  • DCG_HEREDOC_TIMEOUT=50: heredoc extraction timeout (milliseconds)
  • DCG_HEREDOC_TIMEOUT_MS=50: heredoc extraction timeout (milliseconds)
  • DCG_HEREDOC_LANGUAGES=python,bash: filter heredoc languages
  • DCG_POLICY_DEFAULT_MODE=deny|warn|log: global default decision mode
  • DCG_HOOK_TIMEOUT_MS=200: hook evaluation timeout budget (milliseconds)

Output Formats and DCG_FORMAT

--format (and the DCG_FORMAT env var, which seeds the default) is command-specific: each subcommand accepts only its own set of values, and an unrecognized value is a usage error (exit 2). DCG_FORMAT applies wherever a command has a --format flag and is silently ignored by commands that don't.

CommandAccepted --format valuesNotes
dcg scanpretty, json, markdown, sarifOnly command that emits real SARIF 2.1.0
dcg testpretty (alias text), json (aliases sarif, structured), toon
dcg configpretty (alias text), json (alias sarif)
dcg packspretty (alias text), json (alias sarif)
dcg explainpretty, json (alias sarif)
dcg doctorpretty, json (alias sarif)
dcg simulatepretty, json (alias sarif)
dcg corpusjson, pretty (alias sarif)
dcg suggest-allowlisttext, json (alias sarif)

sarif is a JSON alias on every command except dcg scan. This is deliberate so that setting DCG_FORMAT=sarif globally degrades gracefully — dcg scan produces a real SARIF report while other commands fall back to their structured JSON rather than erroring. If you need machine-readable output from a non-scan command, prefer --format json (which is unambiguous); use dcg scan --format sarif for SARIF. --robot forces JSON regardless of --format.

Configuration Hierarchy

dcg supports layered configuration from multiple sources, with higher-priority sources overriding lower ones:

  1. Environment Variables (DCG_* prefix) [HIGHEST PRIORITY]
  2. Explicit Config File (DCG_CONFIG env var)
  3. Project Config (.dcg.toml in repo root)
  4. User Config (~/.config/dcg/config.toml)
  5. System Config (/etc/dcg/config.toml)
  6. Compiled Defaults [LOWEST PRIORITY]

Accessibility & Themes

dcg supports colorblind-safe palettes and high-contrast output. Colors are always paired with symbols/labels to avoid conveying meaning by color alone.

[output]
high_contrast = true       # ASCII borders + black/white palette

[theme]
palette = "colorblind"     # default | colorblind | high-contrast
use_unicode = true         # false for ASCII-only
use_color = true           # false for monochrome

Configuration File Locations:

LevelPathUse Case
System/etc/dcg/config.tomlOrganization-wide defaults
User~/.config/dcg/config.tomlPersonal preferences
Project.dcg.toml (repo root)Project-specific settings
ExplicitDCG_CONFIG=/path/to/fileTesting or override

Merging Behavior:

Configuration layers are merged additively, with higher-priority sources overriding specific fields:

// Only fields explicitly set in higher-priority configs override
// Missing fields retain values from lower-priority sources
fn merge_layer(&mut self, other: ConfigLayer) {
    if let Some(verbose) = other.general.verbose {
        self.general.verbose = verbose;  // Override if present
    }
    // Unset fields retain previous values
}

This means you can set organization defaults in /etc/dcg/config.toml, personal preferences in ~/.config/dcg/config.toml, and project-specific overrides in .dcg.toml—each layer only needs to specify the settings that differ from defaults.

Project-Specific Pack Configuration:

The [projects] section allows different pack configurations for different repositories:

[projects."/home/user/work/production-api"]
packs = { enabled = ["database.postgresql", "cloud.aws"], disabled = [] }

[projects."/home/user/personal/experiments"]
packs = { enabled = [], disabled = ["core.git"] }  # More permissive for experiments

Fail-Open Philosophy

dcg is designed with a fail-open philosophy: when the tool cannot safely analyze a command (due to timeouts, parse errors, or resource limits), it allows the command to proceed rather than blocking it and breaking the user's workflow.

Why Fail-Open?

  1. Workflow Continuity: A blocked legitimate command is more disruptive than a missed dangerous one
  2. Performance Guarantees: The hook must never become a bottleneck
  3. Graceful Degradation: Partial analysis is better than no analysis

Fail-Open Scenarios:

ScenarioBehaviorRationale
Parse error in heredocALLOW + warnMalformed input shouldn't block work
Extraction timeoutALLOW + warnSlow inputs shouldn't hang terminal
Size limit exceededALLOW + fallback checkLarge inputs get reduced analysis
Regex engine timeoutALLOW + warnPathological patterns shouldn't block
AST matching errorSkip that heredocContinue evaluating other content
Deadline exceededALLOW immediatelyHard cap prevents runaway processing

Configurable Strictness:

For high-security environments, fail-open can be disabled.

For heredoc/inline-script analysis specifically:

[heredoc]
fallback_on_parse_error = false  # Block on heredoc parse errors
fallback_on_timeout = false      # Block on heredoc timeouts

For the top-level hook input (the JSON dcg reads from stdin), enable fail-closed mode so that input which cannot be parsed at all is blocked instead of allowed:

[general]
fail_closed = true   # Deny when the hook input itself is unparseable

or at runtime:

DCG_FAIL_CLOSED=1   # env var overrides the config value

The default is fail-open (unparseable input is allowed) and is unchanged unless you opt in. With fail-closed enabled, a genuinely unparseable hook payload produces a deny (a permissionDecision: deny for Claude-style hooks; a "decision":"deny" line plus a non-zero exit for dcg hook --batch). Transient IO read errors still fail open even in this mode, since they are not attacker-controlled malformed payloads.

A leading UTF-8 BOM (EF BB BF) is stripped before parsing in all hook paths, so a BOM-prefixed but otherwise-valid command is correctly evaluated (and blocked if dangerous) rather than allowed through as "unparseable".

With strict mode enabled, dcg will block commands when analysis fails, providing detailed error messages explaining why.

Fallback Pattern Checking:

Even when full analysis is skipped, dcg performs a lightweight fallback check for critical destructive patterns:

static FALLBACK_PATTERNS: LazyLock<RegexSet> = LazyLock::new(|| {
    RegexSet::new([
        r"shutil\.rmtree",
        r"os\.remove",
        r"fs\.rmSync",
        r"\brm\s+-[a-zA-Z]*r[a-zA-Z]*f",
        r"\bgit\s+reset\s+--hard\b",
        // ... other critical patterns
    ])
});

This ensures that even oversized or malformed inputs are checked for the most dangerous operations before being allowed.

Absolute Timeout:

To prevent any single command from blocking indefinitely, dcg enforces an absolute maximum processing time of 200ms. Any command exceeding this threshold is immediately allowed with a warning logged.

Installation

The easiest way to install is using the install script, which downloads a prebuilt binary for your platform:

curl -fsSL "https://raw.githubusercontent.com/Dicklesworthstone/destructive_command_guard/main/install.sh?$(date +%s)" | bash -s -- --easy-mode

Easy mode auto-detects your platform, downloads the right binary, verifies SHA256 checksums, configures all supported AI agent hooks (Claude Code, Codex CLI, Gemini CLI, GitHub Copilot CLI, Cursor IDE, Hermes Agent, Aider), and updates your PATH. For Codex CLI 0.125.0+, the installer merges a PreToolUse Bash hook into ~/.codex/hooks.json; invalid JSON or malformed existing Codex hook shapes are left unchanged and reported instead of being overwritten.

Other options:

Interactive mode (prompts for each step):

curl -fsSL "https://raw.githubusercontent.com/Dicklesworthstone/destructive_command_guard/main/install.sh?$(date +%s)" | bash

Install specific version:

curl -fsSL "https://raw.githubusercontent.com/Dicklesworthstone/destructive_command_guard/main/install.sh?$(date +%s)" | bash -s -- --version v0.5.0

Install to /usr/local/bin (system-wide, requires sudo):

curl -fsSL "https://raw.githubusercontent.com/Dicklesworthstone/destructive_command_guard/main/install.sh?$(date +%s)" | sudo bash -s -- --system

Build from source instead of downloading binary:

curl -fsSL "https://raw.githubusercontent.com/Dicklesworthstone/destructive_command_guard/main/install.sh?$(date +%s)" | bash -s -- --from-source

Download/install only (skip agent hook configuration):

curl -fsSL "https://raw.githubusercontent.com/Dicklesworthstone/destructive_command_guard/main/install.sh?$(date +%s)" | bash -s -- --no-configure

Note: If you have gum installed, the installer will use it for fancy terminal formatting.

The installer also verifies Sigstore cosign bundles when available (falls back to checksum-only), falls back to building from source if no prebuilt is available, and removes the legacy Python predecessor (git_safety_guard.py) if present.

Agent-specific notes
  • Aider: No PreToolUse-style interception. The installer enables git-commit-verify: true in ~/.aider.conf.yml so git hooks run. For full protection, install dcg as a git pre-commit hook.
  • Continue: No shell command interception hooks. The installer detects Continue but cannot auto-configure protection. Use a git pre-commit hook instead.
  • Codex CLI: PreToolUse hooks via ~/.codex/hooks.json (stable in Codex 0.125.0+; the codex_hooks feature is on by default). Codex's hook input shape mirrors Claude Code's, but its JSON deny parser is strict (#[serde(deny_unknown_fields)]), so dcg detects Codex from the turn_id stdin field and switches to Codex's documented stderr deny path with exit code 2; the block message goes to stderr where Codex shows it to the model, without self-service allowlist or allow-once commands. The Unix installer and install.ps1 both merge dcg's hook into the existing hooks object, detect an already-current dcg hook exactly, leave invalid JSON or malformed hook shapes untouched, and surface the failure reason in the install summary. uninstall.sh and uninstall.ps1 remove only dcg-owned Codex hooks and preserve coexisting entries. See the Codex integration notes. Caveats: the model can still write scripts to disk to bypass hook-based blocking; and Codex's PreToolUse hooks do not yet intercept the unified_exec shell path (used by Codex Desktop / codex exec on Windows for command_execution events), so destructive commands routed that way are not blocked until Codex extends hook coverage upstream.
  • GitHub Copilot CLI: Hooks are repository-local (.github/hooks/*.json). Run the installer from each repository where you want protection. The generated hook covers both Unix bash and Windows powershell tool payloads.
  • Cursor IDE: Hooks are configured through ~/.cursor/hooks.json plus a generated bridge (dcg-pre-shell.ps1 on Windows). The installer inserts dcg first in beforeShellExecution, collapses duplicate dcg entries, and preserves coexisting Cursor hooks.
  • Hermes Agent: NousResearch's Hermes Agent declares shell hooks in ~/.hermes/config.yaml under hooks.pre_tool_call. The installer merges a single matcher: "terminal" entry that invokes dcg directly — no wrapper script — because Hermes' input JSON (hook_event_name: "pre_tool_call", tool_name: "terminal", tool_input.command) deserializes straight into dcg's existing HookInput. Hermes explicitly documents that "non-zero exit codes... never abort the agent loop", so dcg switches to Hermes' JSON block protocol on output: {"decision":"block","reason":...} (plus the alternate {"action":"block","message":...} form for cross-version compatibility). The installer also sets hooks_auto_accept: true if not already set; Hermes silently drops un-allowlisted hooks in non-TTY runs (gateway/cron) without it. unconfigure_hermes in uninstall.sh removes only the dcg-owned entry and leaves hooks_auto_accept alone (other Hermes hooks may rely on it).
  • Grok (xAI): Grok Build / Grok CLI auto-discovers every *.json under ~/.grok/hooks/. dcg install --grok writes a self-contained ~/.grok/hooks/dcg.json with a PreToolUse / matcher: "Bash" entry — Grok internally aliases Claude-style "Bash" to its own run_terminal_cmd tool, so a single rule covers every shell command. dcg detects Grok at runtime from the camelCase wire shape (hookEventName: "pre_tool_use", toolName: "run_terminal_cmd") or from the GROK_SESSION_ID / GROK_HOOK_EVENT / GROK_WORKSPACE_ROOT environment variables, and switches its output to Grok's JSON contract: {"decision":"deny","reason":...} (note "deny", not Hermes' "block"). Grok also picks up dcg automatically through its ~/.claude/settings.json compatibility layer, so existing Claude Code users get protection with no additional install step. Add --project to write <repo>/.grok/hooks/dcg.json for a per-repo install (Grok requires /hooks-trust the first time it opens a repo with hooks).
  • Antigravity CLI (agy): Google Antigravity's agy CLI ships a Claude-Code-compatible hooks system. dcg install --agy merges a PreToolUse / matcher: "Bash" entry into ~/.gemini/config/hooks.json (the canonical path; agy migrates the legacy ~/.gemini/antigravity-cli/hooks.json here and symlinks the old path to it). agy runs the hook before its run_command shell tool; dcg detects agy at runtime from the distinctive nested toolCall envelope ({"toolCall":{"name":"run_command","args":{"CommandLine":"…"}},"conversationId":…,"stepIdx":…}) — the shell command is read from toolCall.args.CommandLine — or from the ANTIGRAVITY_CONVERSATION_ID environment variable / agy parent-process name. dcg switches its output to agy's JSON contract: {"decision":"block","reason":…} with exit code 0 (verified: agy honors both "block" and "deny" and aborts the tool; a non-zero exit code is only logged and does NOT reliably block, so dcg always emits exit 0 + JSON). Add --project to write <repo>/.gemini/config/hooks.json for a per-repo install. Restart agy (start a new session) after installing.
  • OpenCode: Not auto-configured. Requires a Bun-based plugin with "tool.execute.before" hook key. A working community plugin: aspiers/ai-config/dcg-guard.js.
  • Pi: Not auto-configured. Pi intercepts shell commands through user-authored TypeScript extensions (pi.on("tool_call", …), auto-loaded from ~/.pi/agent/extensions/*.ts or <repo>/.pi/extensions/*.ts). A ready-to-use dcg-guard.ts extension that routes each bash command through dcg --robot test (exit 1 = deny) and blocks with the dcg reason is documented in docs/pi-integration.md.

Recommended: After installing, run dcg setup to add a shell startup check that warns you if the dcg hook is ever silently removed from ~/.claude/settings.json.

From source (requires Rust nightly)

view the full README on GitHub.

// compatibility

Platformscli, api, desktop, web, mobile
Operating systems
AI compatibilityclaude
LicenseNOASSERTION
Pricingopen-source
LanguageRust

// faq

What is destructive_command_guard?

The Destructive Command Guard (dcg) is for blocking dangerous git and shell commands from being executed by agents.. It is open-source on GitHub.

Is destructive_command_guard free to use?

destructive_command_guard is open-source under the NOASSERTION license, so it is free to use.

What category does destructive_command_guard belong to?

destructive_command_guard is listed under uncategorized in the Claudeers registry of Claude-compatible tools.

0 views
1,680 stars
unclaimed
updated 1 day ago

// embed badge

destructive_command_guard on Claudeers
[![Claudeers](https://claudeers.com/api/badge/destructivecommandguard.svg)](https://claudeers.com/destructivecommandguard)

// retro hit counter

destructive_command_guard hit counter
[![Hits](https://claudeers.com/api/counter/destructivecommandguard.svg)](https://claudeers.com/destructivecommandguard)

// reviews

// guestbook

0/500

// related in Uncategorized / Others

🔓

Fair-code workflow automation platform with native AI capabilities. Combine visual building with custom code, self-host or cloud, 400+ integrations.

// uncategorizedn8n-io/TypeScript195,721NOASSERTION[ claude ]
🔓

FULL Augment Code, Claude Code, Cluely, CodeBuddy, Comet, Cursor, Devin AI, Junie, Kiro, Leap.new, Lovable, Manus, NotionAI, Orchids.app, Perplexity, Poke, Q…

// uncategorizedx1xhlol/141,748GPL-3.0[ claude ]
🔓

The agent engineering platform.

// uncategorizedlangchain-ai/Python141,411MIT[ claude ]
🔓

100+ AI Agent & RAG apps you can actually run — clone, customize, ship.

// uncategorizedShubhamsaboo/Python116,798Apache-2.0[ claude ]

// built by

→ see how destructive_command_guard connects across the ecosystem