# How to Create Custom YAML Security Packs in dcg: A Complete Guide

> Learn to create custom YAML security packs in dcg from Dicklesworthstone/destructive_command_guard. Define command whitelists and blacklists to extend protective rules.

- Repository: [Jeff Emanuel/destructive_command_guard](https://github.com/Dicklesworthstone/destructive_command_guard)
- Tags: how-to-guide
- Published: 2026-07-14

---

**Custom YAML security packs in dcg let you define command whitelists and blacklists using simple YAML files that the Destructive Command Guard loads at runtime to extend its protective rules.**

The `Dicklesworthstone/destructive_command_guard` repository implements a flexible, file-driven rule system that allows you to version-control security policies and share them across teams. By authoring custom packs, you can tailor the guardrails to your specific toolchain—whether that means permitting benign Git operations or blocking catastrophic recursive deletions.

## Understanding the Pack Schema

Before writing rules, review the formal specification in **[`docs/pack.schema.yaml`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/docs/pack.schema.yaml)**. This schema defines the mandatory structure that dcg validates during load time. A valid pack must declare metadata fields and two distinct pattern arrays that drive the evaluation pipeline.

## Structuring Your Custom Pack

Create a new file ending in `.yaml` and populate it with the required top-level fields: `id`, `name`, `description`, and `enabled`. Beneath these, define `safe_patterns` (whitelist) and `destructive_patterns` (blacklist).

### Pack Metadata

The metadata block identifies your collection and controls its activation:

- **`id`**: A unique, dot-separated identifier (e.g., `custom.example`).
- **`name`**: Human-readable title shown in CLI listings.
- **`description`**: Brief explanation of the pack’s purpose.
- **`enabled`**: Boolean toggle; set to `true` to load by default.

### Safe Patterns

Safe patterns act as a **whitelist**. If a command matches any entry here, dcg permits it immediately without further checks. Each entry requires:

- **`rule_id`**: Stable unique identifier for the rule.
- **`regex`**: Fancy-Regex pattern to match against the normalized command string.
- **`description`** (optional): Context for why the command is considered safe.

### Destructive Patterns

Destructive patterns form the **blacklist**. Matching commands trigger a denial response containing remediation guidance. Each entry requires:

- **`rule_id`**: Unique identifier for tracking and auditing.
- **`regex`**: Fancy-Regex pattern to detect dangerous commands.
- **`reason`**: Human-readable explanation returned in the denial JSON.

Here is a complete example based on [`examples/packs/example.yaml`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/examples/packs/example.yaml):

```yaml
id: custom.example
name: Example Pack
description: Demonstrates a user-defined pack.
enabled: true

safe_patterns:
  - rule_id: custom.example:git-branch-create
    regex: ^git\s+checkout\s+-b\s+\S+$
    description: Allows creating a new Git branch.

destructive_patterns:
  - rule_id: custom.example:git-reset-hard
    regex: ^git\s+reset\s+--hard\b
    reason: "git reset --hard discards uncommitted changes and rewrites history."
  - rule_id: custom.example:rm-rf-home
    regex: ^rm\s+-rf\s+~/?$
    reason: "Recursive removal of the home directory is catastrophic."

```

## Installation and Configuration

Once your YAML file is written, dcg must be told where to find it. The loader logic in [`src/config.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/config.rs) resolves paths and registers packs with the evaluator.

### Locating the Packs Directory

You have two registration options:

1. **Automatic discovery**: Place your file in `~/.config/dcg/packs/`. The engine loads every `*.yaml` file in this directory automatically.
2. **Explicit listing**: Add the relative path to the `packs.enabled` array in `~/.config/dcg/config.toml`.

### Registering in config.toml

Open your configuration file and append the pack filename:

```toml
[packs]
enabled = [
    "custom.example.yaml",
    # existing built-in packs …

]

```

After saving, verify registration by running `dcg packs --verbose` (command implemented in [`src/cli.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/cli.rs)). The output should list `custom.example` among active packs.

## The Evaluation Pipeline

When dcg processes a command, patterns from your custom pack enter the evaluation pipeline defined in [`src/evaluator.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/evaluator.rs):

1. **Quick-reject filter** (`memchr`) discards obvious non-matches to improve performance.
2. **Normalization** strips paths and expands aliases, standardizing the input string.
3. **Safe-pattern whitelist** checks against your `safe_patterns`. If matched, the command bypasses all further checks.
4. **Destructive-pattern blacklist** checks against your `destructive_patterns`. If matched, dcg emits a JSON denial containing the `ruleId`, `reason`, and remediation suggestions.
5. **Default-allow** permits any command that survives the above stages.

This ordering ensures that explicit allowances override blanket prohibitions, giving you fine-grained control.

## Validation and Testing

Before deploying to production, validate your YAML against the official schema. While dcg performs runtime validation via `Pack::from_yaml()` (as seen in the loading sequence), catching syntax errors early prevents service interruptions.

Test your regex patterns against sample commands using the Fancy-Regex syntax. Remember that patterns are anchored implicitly against the normalized command string, so account for whitespace and argument ordering.

## Summary

- **Custom YAML security packs** extend dcg’s protection by defining project-specific whitelists and blacklists.
- **Schema compliance** is enforced via [`docs/pack.schema.yaml`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/docs/pack.schema.yaml); every pack needs metadata plus `safe_patterns` and `destructive_patterns` arrays.
- **Installation** requires either dropping the file into `~/.config/dcg/packs/` or listing it in [`config.toml`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/config.toml), then verifying with `dcg packs --verbose`.
- **Evaluation order** prioritizes safe patterns over destructive ones, with automatic fall-through for unmatched commands.

## Frequently Asked Questions

### What regex engine does dcg use for pattern matching?

dcg uses the **Fancy-Regex** engine, which supports Perl-compatible regular expressions with advanced features like look-aheads. Patterns are defined in the `regex` field of each rule entry and are evaluated against normalized command strings after path stripping and alias expansion.

### Can I disable a built-in pack while keeping my custom pack active?

Yes. Edit `~/.config/dcg/config.toml` and remove the built-in pack filename from the `packs.enabled` array, or set `enabled: false` inside the YAML file’s metadata block. The configuration loader in [`src/config.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/config.rs) only registers packs explicitly marked as enabled.

### How does dcg handle rule ID collisions?

Each `ruleId` must be unique across all loaded packs. If two packs define the same `rule_id`, the evaluator in [`src/evaluator.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/evaluator.rs) will encounter a collision during registration. Use dot-prefixed namespaces (e.g., `company.team.rule-name`) in your custom packs to avoid conflicts with built-in identifiers.

### Where should I place pack files for team-wide distribution?

While `~/.config/dcg/packs/` is the default user directory, you can reference absolute paths in [`config.toml`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/config.toml) to load packs from shared network mounts or version-controlled repositories. This allows teams to maintain a centralized rule set that updates independently of the dcg binary.