Dicklesworthstone/destructive_command_guardPublic

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

AI summary: A high-performance safety hook that blocks AI agents from executing destructive commands.

Stars
5.7K
+85 today
Forks
221
Watchers
24
Open issues
5
Open PRs
0
Contributors
~3
Commits
1.9K
Branches
2

RustOtherCreated Jan 7, 2026Last push 1d agoLatest release v0.9.4+193 stars this week+214 this month

Star history

since Jan 4, 2026
02K4KJan 2026Mar 2026May 2026Aug 2026
5.7K stars as of Aug 6, 2026, tracked back to Jan 4, 2026. Historical curve reconstructed from public GitHub event archives, calibrated to the current total.

Contribution activity

commits per day, last 52 weeks
AugSepOctNovDecJanFebMarAprMayJunJulAugMonWedFri2025-08-09: 0 commits2025-08-10: 0 commits2025-08-11: 0 commits2025-08-12: 0 commits2025-08-13: 0 commits2025-08-14: 0 commits2025-08-15: 0 commits2025-08-16: 0 commits2025-08-17: 0 commits2025-08-18: 0 commits2025-08-19: 0 commits2025-08-20: 0 commits2025-08-21: 0 commits2025-08-22: 0 commits2025-08-23: 0 commits2025-08-24: 0 commits2025-08-25: 0 commits2025-08-26: 0 commits2025-08-27: 0 commits2025-08-28: 0 commits2025-08-29: 0 commits2025-08-30: 0 commits2025-08-31: 0 commits2025-09-01: 0 commits2025-09-02: 0 commits2025-09-03: 0 commits2025-09-04: 0 commits2025-09-05: 0 commits2025-09-06: 0 commits2025-09-07: 0 commits2025-09-08: 0 commits2025-09-09: 0 commits2025-09-10: 0 commits2025-09-11: 0 commits2025-09-12: 0 commits2025-09-13: 0 commits2025-09-14: 0 commits2025-09-15: 0 commits2025-09-16: 0 commits2025-09-17: 0 commits2025-09-18: 0 commits2025-09-19: 0 commits2025-09-20: 0 commits2025-09-21: 0 commits2025-09-22: 0 commits2025-09-23: 0 commits2025-09-24: 0 commits2025-09-25: 0 commits2025-09-26: 0 commits2025-09-27: 0 commits2025-09-28: 0 commits2025-09-29: 0 commits2025-09-30: 0 commits2025-10-01: 0 commits2025-10-02: 0 commits2025-10-03: 0 commits2025-10-04: 0 commits2025-10-05: 0 commits2025-10-06: 0 commits2025-10-07: 0 commits2025-10-08: 0 commits2025-10-09: 0 commits2025-10-10: 0 commits2025-10-11: 0 commits2025-10-12: 0 commits2025-10-13: 0 commits2025-10-14: 0 commits2025-10-15: 0 commits2025-10-16: 0 commits2025-10-17: 0 commits2025-10-18: 0 commits2025-10-19: 0 commits2025-10-20: 0 commits2025-10-21: 0 commits2025-10-22: 0 commits2025-10-23: 0 commits2025-10-24: 0 commits2025-10-25: 0 commits2025-10-26: 0 commits2025-10-27: 0 commits2025-10-28: 0 commits2025-10-29: 0 commits2025-10-30: 0 commits2025-10-31: 0 commits2025-11-01: 0 commits2025-11-02: 0 commits2025-11-03: 0 commits2025-11-04: 0 commits2025-11-05: 0 commits2025-11-06: 0 commits2025-11-07: 0 commits2025-11-09: 0 commits2025-11-10: 0 commits2025-11-11: 0 commits2025-11-12: 0 commits2025-11-13: 0 commits2025-11-14: 0 commits2025-11-15: 0 commits2025-11-16: 0 commits2025-11-17: 0 commits2025-11-18: 0 commits2025-11-19: 0 commits2025-11-20: 0 commits2025-11-21: 0 commits2025-11-22: 0 commits2025-11-23: 0 commits2025-11-24: 0 commits2025-11-25: 0 commits2025-11-26: 0 commits2025-11-27: 0 commits2025-11-28: 0 commits2025-11-29: 0 commits2025-11-30: 0 commits2025-12-01: 0 commits2025-12-02: 0 commits2025-12-03: 0 commits2025-12-04: 0 commits2025-12-05: 0 commits2025-12-06: 0 commits2025-12-07: 0 commits2025-12-08: 0 commits2025-12-09: 0 commits2025-12-10: 0 commits2025-12-11: 0 commits2025-12-12: 0 commits2025-12-13: 0 commits2025-12-14: 0 commits2025-12-15: 0 commits2025-12-16: 0 commits2025-12-17: 0 commits2025-12-18: 0 commits2025-12-19: 0 commits2025-12-20: 0 commits2025-12-21: 0 commits2025-12-22: 0 commits2025-12-23: 0 commits2025-12-24: 0 commits2025-12-25: 0 commits2025-12-26: 0 commits2025-12-27: 0 commits2025-12-28: 0 commits2025-12-29: 0 commits2025-12-30: 0 commits2025-12-31: 0 commits2026-01-01: 0 commits2026-01-02: 0 commits2026-01-03: 0 commits2026-01-04: 0 commits2026-01-05: 0 commits2026-01-06: 0 commits2026-01-07: 34 commits2026-01-08: 209 commits2026-01-09: 188 commits2026-01-10: 85 commits2026-01-11: 106 commits2026-01-12: 73 commits2026-01-13: 15 commits2026-01-14: 30 commits2026-01-15: 41 commits2026-01-16: 119 commits2026-01-17: 82 commits2026-01-18: 46 commits2026-01-19: 27 commits2026-01-20: 11 commits2026-01-21: 29 commits2026-01-22: 9 commits2026-01-23: 2 commits2026-01-24: 6 commits2026-01-25: 3 commits2026-01-26: 5 commits2026-01-27: 2 commits2026-01-28: 0 commits2026-01-29: 8 commits2026-01-30: 1 commit2026-01-31: 0 commits2026-02-01: 2 commits2026-02-02: 2 commits2026-02-03: 1 commit2026-02-04: 0 commits2026-02-05: 0 commits2026-02-06: 0 commits2026-02-07: 0 commits2026-02-08: 0 commits2026-02-09: 6 commits2026-02-10: 1 commit2026-02-11: 8 commits2026-02-12: 1 commit2026-02-13: 0 commits2026-02-14: 1 commit2026-02-15: 1 commit2026-02-16: 5 commits2026-02-17: 0 commits2026-02-18: 0 commits2026-02-19: 0 commits2026-02-20: 3 commits2026-02-21: 5 commits2026-02-22: 1 commit2026-02-23: 2 commits2026-02-24: 4 commits2026-02-25: 7 commits2026-02-26: 0 commits2026-02-27: 0 commits2026-02-28: 1 commit2026-03-01: 2 commits2026-03-02: 0 commits2026-03-03: 0 commits2026-03-04: 3 commits2026-03-05: 0 commits2026-03-06: 1 commit2026-03-07: 2 commits2026-03-08: 0 commits2026-03-09: 0 commits2026-03-10: 0 commits2026-03-11: 3 commits2026-03-12: 2 commits2026-03-13: 0 commits2026-03-14: 1 commit2026-03-15: 0 commits2026-03-16: 0 commits2026-03-17: 0 commits2026-03-18: 1 commit2026-03-19: 0 commits2026-03-20: 4 commits2026-03-21: 5 commits2026-03-22: 2 commits2026-03-23: 1 commit2026-03-24: 4 commits2026-03-25: 3 commits2026-03-26: 0 commits2026-03-27: 0 commits2026-03-28: 0 commits2026-03-29: 3 commits2026-03-30: 8 commits2026-03-31: 0 commits2026-04-01: 1 commit2026-04-02: 0 commits2026-04-03: 0 commits2026-04-04: 0 commits2026-04-05: 1 commit2026-04-06: 1 commit2026-04-07: 0 commits2026-04-08: 1 commit2026-04-09: 0 commits2026-04-10: 0 commits2026-04-11: 0 commits2026-04-12: 0 commits2026-04-13: 0 commits2026-04-14: 0 commits2026-04-15: 0 commits2026-04-16: 0 commits2026-04-17: 24 commits2026-04-18: 62 commits2026-04-19: 6 commits2026-04-20: 4 commits2026-04-21: 0 commits2026-04-22: 3 commits2026-04-23: 0 commits2026-04-24: 2 commits2026-04-25: 0 commits2026-04-26: 0 commits2026-04-27: 3 commits2026-04-28: 153 commits2026-04-29: 9 commits2026-04-30: 59 commits2026-05-01: 101 commits2026-05-02: 0 commits2026-05-03: 6 commits2026-05-04: 4 commits2026-05-05: 0 commits2026-05-06: 1 commit2026-05-07: 0 commits2026-05-08: 0 commits2026-05-09: 0 commits2026-05-10: 0 commits2026-05-11: 1 commit2026-05-12: 4 commits2026-05-13: 0 commits2026-05-14: 5 commits2026-05-15: 2 commits2026-05-16: 0 commits2026-05-17: 1 commit2026-05-18: 1 commit2026-05-19: 2 commits2026-05-20: 0 commits2026-05-21: 0 commits2026-05-22: 0 commits2026-05-23: 4 commits2026-05-24: 4 commits2026-05-25: 5 commits2026-05-26: 9 commits2026-05-27: 0 commits2026-05-28: 1 commit2026-05-29: 1 commit2026-05-30: 1 commit2026-05-31: 0 commits2026-06-01: 1 commit2026-06-02: 1 commit2026-06-03: 0 commits2026-06-04: 0 commits2026-06-05: 0 commits2026-06-06: 0 commits2026-06-07: 3 commits2026-06-08: 4 commits2026-06-09: 1 commit2026-06-10: 0 commits2026-06-11: 0 commits2026-06-12: 0 commits2026-06-13: 0 commits2026-06-14: 0 commits2026-06-15: 1 commit2026-06-16: 0 commits2026-06-17: 2 commits2026-06-18: 2 commits2026-06-19: 1 commit2026-06-20: 0 commits2026-06-21: 0 commits2026-06-22: 0 commits2026-06-23: 3 commits2026-06-24: 2 commits2026-06-25: 2 commits2026-06-26: 8 commits2026-06-27: 2 commits2026-06-28: 0 commits2026-06-29: 2 commits2026-06-30: 0 commits2026-07-01: 1 commit2026-07-02: 3 commits2026-07-03: 1 commit2026-07-04: 1 commit2026-07-05: 1 commit2026-07-06: 1 commit2026-07-07: 0 commits2026-07-08: 1 commit2026-07-09: 0 commits2026-07-10: 0 commits2026-07-11: 7 commits2026-07-12: 0 commits2026-07-13: 5 commits2026-07-14: 1 commit2026-07-15: 4 commits2026-07-16: 0 commits2026-07-17: 0 commits2026-07-18: 3 commits2026-07-19: 0 commits2026-07-20: 0 commits2026-07-21: 1 commit2026-07-22: 0 commits2026-07-23: 1 commit2026-07-24: 0 commits2026-07-25: 0 commits2026-07-26: 0 commits2026-07-27: 5 commits2026-07-28: 14 commits2026-07-29: 1 commit2026-07-30: 0 commits2026-07-31: 20 commits2026-08-01: 1 commit2026-08-02: 13 commits2026-08-03: 2 commits2026-08-04: 7 commits2026-08-05: 17 commits2026-08-06: 0 commits2026-08-07: 0 commits2026-08-08: 0 commits
1,855 commits in the last yearLessMore

Signals and awards

derived from tracked data
  • Very active

    1,855 commits in 52 weeks

  • Repeat trending

    3 trending appearances

What destructive_command_guard does

The Destructive Command Guard (dcg) acts as a critical safety layer for AI coding assistants by intercepting and blocking dangerous shell and git commands before they execute. Written in Rust for minimal overhead, it integrates directly with popular tools like Claude Code, Cursor, and Copilot CLI via their native hook systems. By analyzing commands for destructive intent—such as forced git pushes, mass deletions, or dangerous environment modifications—it protects developers from accidental code loss or system damage caused by hallucinating or overly aggressive autonomous agents.

Software engineers and DevOps professionals who heavily utilize autonomous AI coding agents and need a strict safety net.

  • Broad compatibility: integrates out-of-the-box with over a dozen popular AI coding tools and CLIs.
  • High performance: built in Rust to ensure the interception process adds virtually zero latency to the workflow.
  • Pattern matching: uses sophisticated rules to identify inherently dangerous commands like `rm -rf` or `git reset --hard`.
  • Customizable rulesets: allows developers to define their own safe and blocked commands based on project needs.
  • Failsafe design: operates locally without external dependencies, ensuring continuous protection even offline.

Where teams use it

Preventing Accidental Deletions

Developers run the guard to ensure an autonomous agent doesn't mistakenly execute a command that wipes their local directory.

Securing CI/CD Pipelines

DevOps engineers install the tool in agentic CI environments to prevent unauthorized modifications to infrastructure state.

Safe Agent Experimentation

Researchers safely test new, unpredictable AI models on their local machines knowing destructive actions will be blocked.

Enforcing Git Best Practices

Teams use the guard to prevent agents from force-pushing to protected branches or rewriting shared history.

Getting started: cargo install dcg

README

main branch

dcg (Destructive Command Guard)

Destructive Command Guard - Protecting your code from accidental destruction

Coverage License: custom

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 CLI, VS Code Copilot Chat, Cursor, Hermes Agent, Grok (xAI), Posit Assistant, and related tools.

Supported: Claude Code, Codex CLI 0.125.0+, Gemini CLI, GitHub Copilot CLI, VS Code Copilot Chat, Cursor IDE, Hermes Agent, Posit Assistant (Positron/RStudio extension, standalone server, and pa terminal client), 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, VS Code Copilot Chat (through VS Code's Claude-hook compatibility), Cursor IDE, Hermes Agent, Posit Assistant, 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 mandatory SHA256 checksum, verifies the release's long-lived minisign signature when minisign is available, and verifies Sigstore/cosign provenance when both cosign and a trusted bundle are available. It adds dcg 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, Hermes Agent, and Posit Assistant. Copilot is configured at the user level under %COPILOT_HOME%\hooks (or %USERPROFILE%\.copilot\hooks) so every workspace is protected. On Windows the windows.filesystem and windows.system packs are on by default, so del /s, rd /s, Remove-Item -Recurse (with or without -Force), format, and vssadmin delete shadows are blocked out of the box. Pin a version with -Version vX.Y.Z; use -RequireMinisign to fail closed if the sidecar or verifier is unavailable.


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?

Feature What It Does
Zero-Config Protection Blocks dangerous git/filesystem commands out of the box
50+ Security Packs Databases, Kubernetes, Docker, AWS/GCP/Azure, Terraform, and more
Sub-Millisecond Latency SIMD-accelerated filtering—you won't notice it's there
Heredoc/Inline Script Scanning Catches python -c "os.remove(...)" and embedded shell scripts
Smart Context Detection Won't block grep "rm -rf" (data) but will block rm -rf / (execution)
Rich Terminal Output Human-readable denial panels, rule context, and suggestions on stderr
Agent-Safe Streams Machine-readable hook output stays on stdout while rich UI stays on stderr
Native Codex Support Codex CLI 0.125.0+ receives a minimal stdout JSON denial that current clients enforce reliably
Graceful Degradation Plain output for CI, pipes, dumb terminals, and no-color environments
Scan Mode for CI Pre-commit hooks and CI integration to catch dangerous commands in code review
Bounded Failure Policy Analysis timeouts become explicit review/block outcomes; malformed raw hook envelopes remain auditable and configurable
Explain Mode dcg 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:

Option Effect
disabled_packs Removes rule packs from evaluation
extra_packs Adds rule packs to evaluation
additional_allowlist Adds command patterns that bypass deny rules
disabled_allowlist When 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 = ["strict_git", "database"]  # real pack / category IDs (see `dcg packs`)
disabled_allowlist = true

extra_packs/disabled_packs take the same pack and category IDs as [packs] enabled/disabled — a category ID like "database" expands to every database.* sub-pack. Use IDs listed by dcg packs or in docs/packs/README.md; "paranoid" is a graduation mode, not a pack, so enable the real strict_git pack for stricter git rules.

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 behavior dcg handling
Hook config Merges a PreToolUse Bash hook into ~/.codex/hooks.json
Denied command Exits 0 with a minimal hookSpecificOutput denial on stdout; human warning stays on stderr
Allowed command Exits 0 with empty stdout and stderr
Existing hooks Preserves coexisting hooks, keeps dcg first for Bash, and refuses to overwrite malformed JSON
Validation Covered 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 emits only Codex's documented denial fields 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:

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 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.

Category IDs expand to their sub-packs. Listing a bare category in enabled turns on every pack under it: enabled = ["database"] activates database.postgresql, database.mysql, and the rest of that category. You can still drop a single sub-pack with disabled = ["database.redis"]. The same expansion applies to agent-profile extra_packs / disabled_packs. Always use real pack or category IDs from dcg packs / docs/packs/README.md — a name like "paranoid" is a graduation mode, not a pack.

  • 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 recursive rm operations and equivalent filesystem destruction outside 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, 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 (with or without -Force; aliases included), 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.snowflake - Protects modern snow sql inline queries, files, stdin, nested sources, destructive data operations, pipelines, warehouses, and account privileges.
  • 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 (with or without -Force; -Force only broadens coverage to hidden/read-only items; aliases rm/del/rd/ri included), 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.

Careful Company (Windows) Preset

Every other pack answers "will this command destroy something?". This preset also answers "is this command sending our data somewhere, or switching off the controls that watch it?" — the question that matters once an agent runs on a Windows workstation with tool-permission prompts disabled. The same policy is applied to statically inspectable commands submitted through either PowerShell or cmd.exe, including Cmd's caret escaping, control prefixes, nested cmd /c / call, and command chaining. It is opt-in on every platform, and one line enables the whole posture:

[packs]
enabled = ["careful_company_running_windows"]

With this exact preset ID enabled, the hook evaluation deadline defaults to 3000 ms instead of the ordinary 1000 ms unless config or DCG_HOOK_TIMEOUT_MS explicitly supplies another value. This changes only the time available to reach the same fail-closed decision. Inspect the effective value and source with dcg config --format json.

That turns on the six sub-packs below and the existing destruction coverage the same posture needs: the current windows.*, database.* (including Snowflake), storage.*, remote.*, backup.*, secrets.*, and cloud.* packs. Membership is an explicit pinned list rather than a prefix rule, so a future pack added to one of those reused categories does not silently join this security posture — it has to be added deliberately. (A future careful_company_running_windows.* sub-pack does join, through ordinary category expansion.) Any member can be dropped individually with disabled = ["remote.rsync"].

  • careful_company_running_windows.email - Sending mail from the workstation: Send-MailMessage, System.Net.Mail.SmtpClient, Outlook COM automation, Microsoft Graph sendMail, transactional mail-API send endpoints, aws ses send-email, SMTP CLI tools (blat, swaks, msmtp, git send-email, curl --mail-rcpt), and persistent forwarding rules (New-InboxRule -ForwardTo, Set-Mailbox -ForwardingSmtpAddress).
  • careful_company_running_windows.chat - Chat and webhook destinations: Slack incoming webhooks and Web API writes, Teams connectors and Power Automate triggers, Discord, Telegram, Google Chat, Twilio, Zapier/IFTTT, PagerDuty, and request catchers such as webhook.site and interact.sh.
  • careful_company_running_windows.upload - HTTP file-upload primitives (-InFile, -Form, curl -T, -F field=@file, --data-binary @file, --post-file, WebClient.UploadFile, GetRequestStream, MultipartFormDataContent, BITS uploads), file-drop/paste services, gh gist create, certreq -Post, and request bodies built from file or clipboard contents.
  • careful_company_running_windows.transfer - Outbound file transfer: scp/sftp/WinSCP to a remote destination, scripted FTP, tftp put, rsync and rclone to a remote, cloud-storage uploads (aws s3 cp local→s3://, az storage blob upload, azcopy, gsutil cpgs://, b2/s3cmd/mc/wrangler r2), peer-to-peer senders, WebDAV mounts, and copy LOLBins (esentutl /y, print /D:).
  • careful_company_running_windows.tunnel - Channels that expose the workstation or bypass inspection: ngrok, cloudflared, devtunnel/code tunnel, localtunnel, tailscale funnel, ssh -R/-D, chisel/frp, ncat/netcat/socat, PowerShell raw sockets, netsh interface portproxy, DNS tunnels, and out-of-band callback domains.
  • careful_company_running_windows.guardrails - Turning off the safety net: Defender (Set-MpPreference -Disable*/-ExclusionPath), the firewall, EDR and event-log services, BitLocker, Set-ExecutionPolicy Bypass, script-block logging, event-log clearing, dcg's own DCG_BYPASS, dcg uninstall, allowlist grants (dcg allowlist add, dcg allow-once), runtime config overrides (DCG_DISABLE/DCG_PACKS/DCG_CONFIG), and the agent's hook config, plus unreviewed remote code (iwr | iex, powershell -EncodedCommand, mshta/regsvr32 remote payloads). Diagnosis stays open: dcg explain, dcg allowlist list, and dcg allowlist validate are whitelisted.

False positives are the design constraint. Rules require positive evidence of egress — an attached file, a known egress host, a mutating method — so ordinary GETs, -OutFile/curl -o downloads, and every package-manager install pass through untouched (fetching from a known file-drop or paste host is the one exception, and it warns rather than blocks). Requests whose destinations are all internal (loopback, RFC1918, *.internal/*.corp/*.local, bare intranet hostnames) are whitelisted, with the cloud metadata endpoints (169.254.169.254, metadata.google.internal) deliberately excluded from that allowance. Searching for a token (Select-String "Send-MailMessage" *.ps1) and dcg explain "<command>" are never blocked. git push to a named remote is untouched, and SMB copies to a corporate share are out of scope.

Genuinely ambiguous cases warn instead of blocking (Medium severity: the command runs and the decision is recorded) — a POST with an inline body is a GraphQL query as often as an exfiltration. Promote them when your posture calls for it:

[policy.rules]
"careful_company_running_windows.upload:cli-http-mutating-request" = "deny"
"careful_company_running_windows.upload:ps-http-mutating-request" = "deny"

This preset carries one built-in trust boundary you should know about. While any careful_company_running_windows.* pack is enabled, a command whose executable is hfdt (optionally path-qualified) is allowed without evaluating any pack at all — not just this preset's. hfdt rm -rf /data is permitted with the preset on and denied with it off. The exemption is structural rather than textual: it requires hfdt to be the actual executable of the whole command and refuses chains, redirection, and process substitution, so hfdt …; Invoke-RestMethod … and hfdt $(…) are evaluated normally. If you do not run that tool, this never fires; if you do, treat it as an explicit decision to trust it completely. See docs/careful-company-windows.md.

Other first-party internal tooling gets no such exemption and should be allowlisted, which keeps the grant narrow and recorded:

dcg allowlist add-command "mytool publish --to https://artifacts.corp.internal" \
  -r "First-party internal publisher" --user

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"]

# Bounded heredoc fallback (strict mode can block instead).
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 ──► FALLBACK SCAN or BLOCK (strict)
│   (<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 Bounded Failure Policy)
  • 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|ask|warn|log: global default decision mode (ask requires native operator review and fails closed on unsupported clients)
  • DCG_HOOK_TIMEOUT_MS=<milliseconds>: explicit hook evaluation timeout (ordinary default: 1000; automatic careful_company_running_windows preset default: 3000)

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.

Command Accepted --format values Notes
dcg scan pretty, json, markdown, sarif Only command that emits real SARIF 2.1.0
dcg test pretty (alias text), json (aliases sarif, structured), toon
dcg config pretty (alias text), json (alias sarif)
dcg packs pretty (alias text), json (alias sarif)
dcg explain pretty, json (alias sarif)
dcg doctor pretty, json (alias sarif)
dcg simulate pretty, json (alias sarif)
dcg corpus json, pretty (alias sarif)
dcg suggest-allowlist text, 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 trusted sources, with higher-priority sources overriding lower ones:

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

An automatically discovered .dcg.toml is intentionally not a normal precedence layer. A repository is untrusted when it is first cloned, so its config may only add enforcement: enable built-in packs, add deny policy entries, opt into general.fail_closed, enable heredoc scanning, or turn off heredoc bounded fallbacks. Settings that grant trust or reduce coverage — including allow overrides, pack disables, custom pack paths, custom regex overrides (including block regexes), resource limits, language filters, agent profiles, and nested project overrides — are ignored during automatic discovery.

Automatic project discovery currently runs only where dcg can bind a direct regular file to the descriptor it actually reads (Unix, including macOS). Native Windows ignores an automatically discovered .dcg.toml until equivalent reparse-point and file-identity validation is available; this avoids turning a workspace path race into a privileged file read. A reviewed Windows project file can still be selected explicitly with DCG_CONFIG=.dcg.toml.

To deliberately trust the complete repository config for one invocation, select it explicitly: DCG_CONFIG=.dcg.toml dcg .... An explicit file has the same full authority as any other user-selected config.

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:

Level Path Use Case
System /etc/dcg/config.toml Organization-wide defaults
User ~/.config/dcg/config.toml Personal preferences
Project .dcg.toml (repo root) Automatically discovered enforcement-only policy
Explicit DCG_CONFIG=/path/to/file Testing or override

The machine-wide system-config layer is accepted on Unix only after the file and every directory in its direct path are root-owned and not group/world writable. Native Windows currently ignores that implicit layer until native ACL and reparse-point validation is implemented; use a user config or an explicit DCG_CONFIG file there.

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 repository-owned hardening in .dcg.toml without letting a newly cloned repository weaken the user's guard. Use DCG_CONFIG=.dcg.toml only after reviewing a project file that needs full override authority.

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

Bounded Failure Policy

dcg distinguishes an unreadable hook envelope from a command whose safety evaluation began but could not finish. It never treats elapsed analysis time or an oversized extracted command as proof that execution is safe.

Scenario Default behavior Strict/configured behavior
Malformed or oversized raw hook JSON Allow with an audit warning general.fail_closed = true denies
Transient hook stdin I/O error Allow with an audit warning Always fail-open because the payload was not attacker-controlled
Extracted command exceeds max_command_bytes Explicit indeterminate result Review-capable clients receive ask; other clients block
Absolute evaluation deadline expires Explicit indeterminate result Review-capable clients receive ask; other clients block
Heredoc extraction/parse/AST failure Run the bounded fallback scanner fallback_on_parse_error = false or fallback_on_timeout = false blocks

Configurable Strictness:

Raw hook-envelope fail-open behavior and embedded-code fallback behavior are configured independently.

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 blocks malformed attacker-controlled hook input and reports why. Separately, when heredoc parsing cannot complete and fallback is enabled, dcg runs a lightweight bounded check over the original command:

static FALLBACK_PATTERNS: LazyLock<RegexSet> = LazyLock::new(|| {
    RegexSet(README truncated)

View on GitHub

Recent activity

commits and pull requests

Releases and announcements

47 total
  1. v0.9.4v0.9.4Aug 6, 2026800 downloads

    A correctness and hardening release from a full issue-triage pass. It closes a class of fail-closed bypasses in the `#261` init-idiom warn path, restores four compose volume/force detections that global flags or combined short-flag clusters could slip past, and removes several false positives that were blocking ordinary safe workflows. No change to the evaluation hot path's asymptotics; a profiling campaign confirmed dcg already runs 35–90× inside its hook budget and produced a committed negative-evidence ledger rather than speculative tuning. ### Security - **`eval`/`source` init-idiom WARN can no longer be used to smuggle a destructive command (#261).** The curated init-idiom downgrade (which lets `eval "$(ssh-agent -s)"` and `source <(kubectl completion bash)` warn instead of hard-deny) was found across four adversarial fresh-eyes rounds to let a destructive command run with only a warning by attaching to, or hiding behind, a curated idiom. The warn is now locked to an allowlist-shaped box: it applies only at command-substitution depth 0 (a curated idiom reached through a nested substitution or heredoc recursion hard-denies at the consumption point), only when

  2. v0.9.3v0.9.3Aug 5, 2026284 downloads

    # dcg v0.9.3 ## Security fixes (false negatives) - **Force-clobber redirects no longer escape `redirect-truncate-root-home` (#263):** bash's noclobber-override redirect operator (`>|`) is strictly stronger than plain `>` but was not matched by the truncation guards; force-clobber writes to protected paths are now denied like other destructive redirections (7c05d96), with a follow-up hardening wave closing four more false negatives found while reviewing this area (70155a0). - **`mise exec -c/--command` inline shell payloads are recursively evaluated (#259):** payloads handed to a shell via mise's inline-command flags were not unwrapped before pattern evaluation, leaving destructive commands inside them unexamined. The argv/tokenizer blind spots are closed (7c05d96, 70155a0). Note: the redirect-only payload gap discovered afterwards is tracked separately in #271. ## Fixes and features - **Allow-once EOF honesty (#262):** `dcg allow-once <CODE>` without `--yes` no longer looks like it granted something it did not when stdin is at EOF; the outcome is reported truthfully. - **`--dialect` for `explain`/`test` (#269):** diagnostics can now evaluate a command under an explicitly select

  3. v0.9.2v0.9.2Aug 3, 20262.4K downloads

    ## v0.9.2 Second hardening patch from the continuing adversarial-review campaign over the v0.9.x line. Three independent reviewers probed the v0.9.1 fixes A/B against the released binaries on both evaluation routes; everything they surfaced is fixed here with regression coverage. ### Fixed - **Warn-mode batch masking**: a Warn-mode `toolCalls` entry ended the request before later entries were evaluated, silently allowing them. The hook now resolves every entry and publishes exactly one response by precedence (Deny > Indeterminate > Ask > Warn > Allow). - **Batch sibling decoys**: a `toolCalls` envelope carrying a destructive `tool_input`/`tool_args` command evaluated only the batch; siblings are now evaluated too. - **Protocol hijack by non-shell batches**: any non-empty `toolCalls` array forced the Claude wire shape, so Gemini/Hermes/Grok/Codex payloads carrying a `readFile`-style batch got a deny their parsers drop; the branch now requires a shell entry. - **mise modeled at its real grammar**: global flags before the subcommand (`mise -v exec -- …`) and post-subcommand flags outside the modeled set bypassed the wrapper model on the real hook path; both engines now share one op

  4. v0.9.1v0.9.1Aug 2, 2026617 downloads

    ## v0.9.1 Hardening patch: an adversarial review of the v0.9.0 changes (three independent reviewers probing the released binary A/B against v0.8.0) surfaced eight defects introduced by that release, all fixed here with regression coverage on both the all-dialect and real hook-path (Posix) evaluation routes. ### Fixed - **`mise exec` is now a fully modeled execution frontend.** The v0.9.0 wrapper support could strip the real command as prefix (`mise exec rm -rf / -- ok` evaluated only `ok`) or let an option value become an `echo` that masked the rest of the argv. The wrapped command now starts at the first bare word or after `--`, with modeled option arities (`-C/--cd`, `-E/--env`, `-j/--jobs`); destructive mise-wrapped commands deny on every dialect path. - **Batched `toolCalls` entries evaluate independently.** Joining a batch with newlines let an entry ending in an unterminated quote or trailing backslash swallow the next entry's destructive command. Each entry (and the singular `toolCall` when both are present) is evaluated on its own; the first non-allow decision answers the request. The `dcg hook` batch subcommand gained the same semantics. - **Malformed `toolCalls` shapes

  5. v0.9.0v0.9.0Aug 2, 2026361 downloads

    ## v0.9.0 Closes the entire post-v0.8.0 issue backlog: two new agent surfaces and six user-reported defects, all with regression coverage. ### Added - **Posit Assistant support** (idea from PR #254, independently reimplemented). Installer/uninstaller manage a Claude-compatible `PreToolUse` hook in `~/.posit/assistant/settings.json` with the lowercase exact matcher `"bash|powershell"` its matcher grammar requires; runtime detection via `PA_PROJECT_DIR` and the `pa` process name; a `powershell` tool inside a Posit hook now gets the Claude-compatible deny payload instead of Codex's minimal shape. - **VS Code Agent Host batched `toolCalls` envelope** (#252). The newer Copilot Agent Host envelope previously deserialized without a recognized command and failed open. Every shell entry in a batch is now extracted and evaluated; one destructive entry denies the whole batch. ### Fixed - **UTF-8 panic** in `dcg explain`/`dcg test` when an escape character preceded a multi-byte character (#255) — all 21 escape-scanner sites now advance by the escaped character's real width. - **Wrapper prefixes defeating data-flag masking** (#257): `mise exec --`, `nice`, `time`, `nohup`, `stdbuf`, `timeo

Commits per week

last 52 weeks
5160Week of 2025-08-09: 0 commitsWeek of 2025-08-16: 0 commitsWeek of 2025-08-23: 0 commitsWeek of 2025-08-30: 0 commitsWeek of 2025-09-06: 0 commitsWeek of 2025-09-13: 0 commitsWeek of 2025-09-20: 0 commitsWeek of 2025-09-27: 0 commitsWeek of 2025-10-04: 0 commitsWeek of 2025-10-11: 0 commitsWeek of 2025-10-18: 0 commitsWeek of 2025-10-25: 0 commitsWeek of 2025-11-01: 0 commitsWeek of 2025-11-09: 0 commitsWeek of 2025-11-16: 0 commitsWeek of 2025-11-23: 0 commitsWeek of 2025-11-30: 0 commitsWeek of 2025-12-07: 0 commitsWeek of 2025-12-14: 0 commitsWeek of 2025-12-21: 0 commitsWeek of 2025-12-28: 0 commitsWeek of 2026-01-04: 516 commitsWeek of 2026-01-11: 466 commitsWeek of 2026-01-18: 130 commitsWeek of 2026-01-25: 19 commitsWeek of 2026-02-01: 5 commitsWeek of 2026-02-08: 17 commitsWeek of 2026-02-15: 14 commitsWeek of 2026-02-22: 15 commitsWeek of 2026-03-01: 8 commitsWeek of 2026-03-08: 6 commitsWeek of 2026-03-15: 10 commitsWeek of 2026-03-22: 10 commitsWeek of 2026-03-29: 12 commitsWeek of 2026-04-05: 3 commitsWeek of 2026-04-12: 86 commitsWeek of 2026-04-19: 15 commitsWeek of 2026-04-26: 325 commitsWeek of 2026-05-03: 11 commitsWeek of 2026-05-10: 12 commitsWeek of 2026-05-17: 8 commitsWeek of 2026-05-24: 21 commitsWeek of 2026-05-31: 2 commitsWeek of 2026-06-07: 8 commitsWeek of 2026-06-14: 6 commitsWeek of 2026-06-21: 17 commitsWeek of 2026-06-28: 8 commitsWeek of 2026-07-05: 10 commitsWeek of 2026-07-12: 13 commitsWeek of 2026-07-19: 2 commitsWeek of 2026-07-26: 41 commitsWeek of 2026-08-02: 39 commitsAug 9, 2025Aug 2, 2026
1.9K commits in the last 52 weeks.

When work happens

weekday and hour
SunMonTueWedThuFriSat036912151821Sun 0:00 — 6 commitsSun 1:00 — 9 commitsSun 2:00 — 22 commitsSun 3:00 — 16 commitsSun 4:00 — 16 commitsSun 5:00 — 11 commitsSun 6:00 — 7 commitsSun 7:00 — 3 commitsSun 8:00 — 0 commitsSun 9:00 — 6 commitsSun 10:00 — 23 commitsSun 11:00 — 9 commitsSun 12:00 — 15 commitsSun 13:00 — 10 commitsSun 14:00 — 7 commitsSun 15:00 — 6 commitsSun 16:00 — 1 commitsSun 17:00 — 7 commitsSun 18:00 — 2 commitsSun 19:00 — 3 commitsSun 20:00 — 4 commitsSun 21:00 — 8 commitsSun 22:00 — 2 commitsSun 23:00 — 8 commitsMon 0:00 — 6 commitsMon 1:00 — 6 commitsMon 2:00 — 21 commitsMon 3:00 — 12 commitsMon 4:00 — 0 commitsMon 5:00 — 0 commitsMon 6:00 — 0 commitsMon 7:00 — 0 commitsMon 8:00 — 1 commitsMon 9:00 — 0 commitsMon 10:00 — 6 commitsMon 11:00 — 6 commitsMon 12:00 — 23 commitsMon 13:00 — 5 commitsMon 14:00 — 8 commitsMon 15:00 — 5 commitsMon 16:00 — 12 commitsMon 17:00 — 13 commitsMon 18:00 — 8 commitsMon 19:00 — 6 commitsMon 20:00 — 9 commitsMon 21:00 — 11 commitsMon 22:00 — 3 commitsMon 23:00 — 8 commitsTue 0:00 — 64 commitsTue 1:00 — 28 commitsTue 2:00 — 21 commitsTue 3:00 — 20 commitsTue 4:00 — 16 commitsTue 5:00 — 6 commitsTue 6:00 — 1 commitsTue 7:00 — 0 commitsTue 8:00 — 3 commitsTue 9:00 — 1 commitsTue 10:00 — 2 commitsTue 11:00 — 4 commitsTue 12:00 — 2 commitsTue 13:00 — 4 commitsTue 14:00 — 8 commitsTue 15:00 — 5 commitsTue 16:00 — 14 commitsTue 17:00 — 7 commitsTue 18:00 — 3 commitsTue 19:00 — 4 commitsTue 20:00 — 0 commitsTue 21:00 — 6 commitsTue 22:00 — 8 commitsTue 23:00 — 7 commitsWed 0:00 — 7 commitsWed 1:00 — 6 commitsWed 2:00 — 7 commitsWed 3:00 — 10 commitsWed 4:00 — 1 commitsWed 5:00 — 2 commitsWed 6:00 — 0 commitsWed 7:00 — 5 commitsWed 8:00 — 10 commitsWed 9:00 — 1 commitsWed 10:00 — 1 commitsWed 11:00 — 3 commitsWed 12:00 — 5 commitsWed 13:00 — 16 commitsWed 14:00 — 3 commitsWed 15:00 — 8 commitsWed 16:00 — 8 commitsWed 17:00 — 12 commitsWed 18:00 — 9 commitsWed 19:00 — 8 commitsWed 20:00 — 8 commitsWed 21:00 — 10 commitsWed 22:00 — 9 commitsWed 23:00 — 12 commitsThu 0:00 — 29 commitsThu 1:00 — 22 commitsThu 2:00 — 30 commitsThu 3:00 — 4 commitsThu 4:00 — 1 commitsThu 5:00 — 2 commitsThu 6:00 — 6 commitsThu 7:00 — 2 commitsThu 8:00 — 1 commitsThu 9:00 — 2 commitsThu 10:00 — 18 commitsThu 11:00 — 4 commitsThu 12:00 — 10 commitsThu 13:00 — 30 commitsThu 14:00 — 7 commitsThu 15:00 — 0 commitsThu 16:00 — 9 commitsThu 17:00 — 14 commitsThu 18:00 — 17 commitsThu 19:00 — 16 commitsThu 20:00 — 17 commitsThu 21:00 — 7 commitsThu 22:00 — 33 commitsThu 23:00 — 62 commitsFri 0:00 — 44 commitsFri 1:00 — 60 commitsFri 2:00 — 74 commitsFri 3:00 — 17 commitsFri 4:00 — 3 commitsFri 5:00 — 1 commitsFri 6:00 — 0 commitsFri 7:00 — 8 commitsFri 8:00 — 5 commitsFri 9:00 — 10 commitsFri 10:00 — 1 commitsFri 11:00 — 9 commitsFri 12:00 — 12 commitsFri 13:00 — 37 commitsFri 14:00 — 64 commitsFri 15:00 — 25 commitsFri 16:00 — 13 commitsFri 17:00 — 16 commitsFri 18:00 — 8 commitsFri 19:00 — 3 commitsFri 20:00 — 5 commitsFri 21:00 — 18 commitsFri 22:00 — 29 commitsFri 23:00 — 16 commitsSat 0:00 — 15 commitsSat 1:00 — 21 commitsSat 2:00 — 5 commitsSat 3:00 — 3 commitsSat 4:00 — 13 commitsSat 5:00 — 0 commitsSat 6:00 — 1 commitsSat 7:00 — 1 commitsSat 8:00 — 0 commitsSat 9:00 — 19 commitsSat 10:00 — 3 commitsSat 11:00 — 3 commitsSat 12:00 — 8 commitsSat 13:00 — 12 commitsSat 14:00 — 2 commitsSat 15:00 — 0 commitsSat 16:00 — 20 commitsSat 17:00 — 40 commitsSat 18:00 — 24 commitsSat 19:00 — 20 commitsSat 20:00 — 13 commitsSat 21:00 — 8 commitsSat 22:00 — 19 commitsSat 23:00 — 19 commits
Commit volume by weekday and hour (UTC). Larger dots mean more commits.

Who is committing

last 52 weeks
Maintainer commits1,846 (99%)
Community commits11 (1%)

1,857 commits in total over the last year.

DateListRankStars gained
Jul 15, 2026daily#18+6
Jul 14, 2026daily#19+4
Jul 12, 2026daily#5+4
  • affaan-m/ECC

    The agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.

    238.5K stars · JavaScript

  • affaan-m/ECC

    The agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.

    234.7K stars · JavaScript

  • NousResearch/hermes-agent

    The agent that grows with you

    227K stars · Python

  • ultraworkers/claw-code

    An agent-managed museum exhibit, built in Rust with Gajae-Code / LazyCodex — developed and maintained with no human intervention.

    195K stars · Rust

  • ultraworkers/claw-code

    An agent-managed museum exhibit, built in Rust with Gajae-Code / LazyCodex — developed and maintained with no human intervention.

    194.9K stars · Rust

  • ultraworkers/claw-code

    An agent-managed museum exhibit, built in Rust with Gajae-Code / LazyCodex — developed and maintained with no human intervention.

    194.9K stars · Rust