# How to Add Organization-Specific Command Patterns to dcg's Quick Rejection Filter

> Learn how to add custom organization-specific command patterns to dcg's quick rejection filter. Extend dcg by creating internal packs or loading external YAML packs to enhance your rejection rules.

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

---

**You can extend dcg's quick-rejection filter by creating a custom internal pack in `src/packs/` or by loading an external YAML pack via configuration, both of which merge their keywords into the SIMD-accelerated lookup used before regex evaluation.**

The Destructive Command Guard (dcg) repository by Dicklesworthstone uses a high-performance pre-filter to scan commands for dangerous keywords before invoking expensive regex engines. To add organization-specific command patterns, you must inject custom keywords into this fast-path filter, which aggregates enabled pack definitions and performs SIMD-accelerated substring searches to minimize latency.

## Understanding the Quick-Rejection Architecture

The quick-rejection filter serves as the first line of defense in [`src/evaluator.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/evaluator.rs), checking commands against a compiled set of keywords before any pattern matching occurs. This system relies on two core components:

- **`collect_enabled_keywords`** in [`src/packs/mod.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/packs/mod.rs) gathers keywords from all enabled packs (both core and external) into a unified lookup table.
- **`keyword_matches_span`** (lines 78-86) performs the actual SIMD-accelerated scan using `memmem::Finder` to detect substrings without regex overhead.

When you add organization-specific patterns, you are essentially expanding the keyword list that feeds into this pre-compiled filter.

## Method 1: Create a Custom Internal Pack

Internal packs ship with the binary and require recompilation, but offer the best performance and version control for organization-specific logic.

### Step 1: Create the Pack Module

Create a new file under [`src/packs/myorg/mod.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/packs/myorg/mod.rs) and define your pack metadata:

```rust
use crate::packs::Pack;

pub const PACK: Pack = Pack {
    id: "myorg",
    description: "Organization-specific destructive commands",
    // Keywords trigger the quick-reject filter
    keywords: &["myorg-delete", "myorg-reset"],
    patterns: &[
        pattern!("myorg-delete-resource", r"myorg-delete\s+--resource\s+\S+"),
        destructive!(r"myorg-reset\s+--force", "Critical reset of org resources"),
    ],
};

```

The `keywords` array feeds directly into the quick-reject pre-filter, ensuring any command containing these strings receives full evaluation.

### Step 2: Register the Pack

Expose your module in [`src/packs/mod.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/packs/mod.rs) by adding:

```rust
pub mod myorg;

```

### Step 3: Enable in Configuration

Add your pack to the enabled list in `~/.config/dcg/config.toml` or a project-local [`dcg.toml`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/dcg.toml):

```toml
[packs]
enabled = ["myorg", "core.git", "core.filesystem"]

```

### Step 4: Recompile

Build the binary to compile your keywords into the static filter:

```bash
cargo build --release

```

Your organization-specific keywords are now embedded in the SIMD-based quick-reject filter and will intercept matching commands before the regex engine runs.

## Method 2: Add an External YAML Pack

External packs allow runtime customization without recompiling the binary, ideal for rapidly evolving organization policies.

### Step 1: Define the YAML Pack

Create a file following the schema defined in [`src/packs/external.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/packs/external.rs):

```yaml
id: myorg
description: Organization-specific destructive commands
keywords:
  - myorg-delete
  - myorg-reset
patterns:
  - name: myorg-delete-resource
    regex: "myorg-delete\\s+--resource\\s+\\S+"
    type: destructive
    severity: high

```

### Step 2: Configure the Load Path

Point dcg to your external file in `~/.config/dcg/config.toml`:

```toml
[external_packs]
paths = ["/path/to/myorg_pack.yml"]

```

### Step 3: Runtime Loading

When dcg starts, `load_external_packs` in [`src/packs/mod.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/packs/mod.rs) reads the YAML, extracts the keywords, and merges them into the global quick-reject store using the same `memmem::Finder` fast-path as internal packs. No recompilation is required.

## Verifying Your Configuration

Confirm your patterns are active by testing a command:

```bash
dcg explain "myorg-delete --resource production-db"

```

If configured correctly, the output will show the command matched the quick-reject filter, proceeded to full pattern evaluation, and returned a denial JSON containing your `ruleId` (e.g., `myorg:myorg-delete-resource`) and defined severity.

## Summary

- **The quick-rejection filter** aggregates keywords from all enabled packs via `collect_enabled_keywords` in [`src/packs/mod.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/packs/mod.rs) and scans commands using SIMD-accelerated substring search before regex evaluation.
- **Internal packs** require creating a Rust module under `src/packs/`, registering it in [`src/packs/mod.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/packs/mod.rs), enabling it in [`config.toml`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/config.toml), and recompiling with `cargo build --release`.
- **External packs** use YAML files loaded at runtime via the `external_packs` configuration path, parsed by [`src/packs/external.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/packs/external.rs), requiring no recompilation.
- **Keywords** defined in either method feed into the same fast-path filter (`keyword_matches_span`), ensuring organization-specific commands are caught early with minimal performance overhead.

## Frequently Asked Questions

### Where does dcg store the compiled keywords for quick rejection?

The keywords are aggregated at runtime (or compile-time for internal packs) by the `collect_enabled_keywords` function in [`src/packs/mod.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/packs/mod.rs). This function merges keywords from all enabled packs into a lookup structure that [`src/evaluator.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/evaluator.rs) uses to perform SIMD-accelerated checks via `memmem::Finder` before invoking the regex engine.

### Do external YAML packs require recompiling dcg?

No. External packs are loaded at runtime by the `load_external_packs` function in [`src/packs/mod.rs`](https://github.com/Dicklesworthstone/destructive_command_guard/blob/main/src/packs/mod.rs), which parses the YAML definitions and extracts keywords dynamically. You only need to restart the dcg process after updating the `external_packs` paths in your configuration file.

### What is the performance impact of adding many organization-specific keywords?

The impact is minimal. The quick-rejection filter uses SIMD-accelerated substring search (via `memmem::Finder`) to check all keywords in parallel, ensuring that even extensive custom keyword lists add negligible latency compared to the regex evaluation phase.

### How can I test if my organization-specific patterns are active?

Use the `dcg explain` command followed by your test command string. If the quick-rejection filter contains your keywords, the output will indicate that the command matched the pre-filter and proceeded to pattern evaluation, displaying the specific `ruleId` and severity level defined in your custom pack.