Skip to content

Authoring custom packs

Pullminder rule packs are portable YAML files that define detection patterns or policy checks. You can create custom packs for your organization’s specific needs, test them locally, and publish them to the community registry or host them in a private registry.

  • Pullminder CLI installed (Installation guide)
  • Familiarity with regular expressions
  • A GitHub account (for publishing to the community registry)

A registry is a directory that holds one or more rule packs. Start by scaffolding a new registry:

Terminal window
pullminder registry init my-rules

This creates the following structure:

my-rules/
registry.yaml # Registry metadata
packs/ # Pack definitions go here
README.md # Registry documentation

The registry.yaml file identifies the registry and contains metadata used when syncing packs:

name: my-rules
description: Custom rule packs for my organization
author: your-github-handle
url: https://github.com/your-org/my-rules

Use the CLI to scaffold a new pack inside the registry:

Terminal window
pullminder registry pack add \
--slug my-check \
--kind detection \
--name "My Check"

This creates packs/my-check/pack.yaml with a minimal template.

Open packs/my-check/pack.yaml and configure every field. Here is the full anatomy of a pack file:

slug: my-check
name: My Check
kind: detection
action: flag
version: 1
max_weight: 10
scoring:
- min_findings: 1
score: 5
- min_findings: 3
score: 10
patterns:
- name: Hardcoded database password
rule_id: MC-001
regex: "(?i)db_password\\s*=\\s*[\"'][^\"']+[\"']"
language: "*"
severity: error
category: security
description: Database password is hardcoded in source code.
- name: Console log in production code
rule_id: MC-002
regex: "console\\.log\\("
language: javascript
severity: low
category: code-quality
description: Console.log statements should be removed before merging.
overrides:
ignore_paths:
- "**/testdata/**"
- "**/fixtures/**"
ignore_authors:
- "dependabot[bot]"
FieldRequiredDescription
slugYesUnique identifier for the pack. Lowercase, hyphens only.
nameYesHuman-readable display name.
kindYesEither detection (pattern matching) or policy (workflow rules).
actionYesDefault action when findings are produced: flag, warn, or block.
versionYesInteger version of the pack (e.g., 3). Increment each time you modify patterns or configuration.
schema_versionNoSchema version. Omit if not needed. The registry infers schema version from the pack structure.
authorNoGitHub handle of the pack author. Required when publishing to the community registry.
max_weightNoMaximum weight a single finding from this pack can contribute to the risk score. Defaults to 10.
scoringNoTiered scoring configuration. Each tier defines the minimum number of findings required to reach that score. The pack’s contribution to the risk score is the highest tier whose min_findings threshold is met. See Pack schema reference for details.
patternsYesArray of pattern objects. At least one pattern is required for detection packs.
overridesNoPath and author exclusions.

Each pattern in the patterns array defines a single detection rule. Patterns are matched against the added and modified lines in the PR diff.

Patterns use Go-compatible regular expressions (RE2 syntax). A few tips:

  • Use (?i) at the start for case-insensitive matching.
  • Escape special characters: \\., \\(, \\{.
  • Use [^\"']+ to match non-empty strings inside quotes.
  • Use \\b for word boundaries to avoid false positives.

The language field filters which files the pattern runs against:

ValueMatches
*All files
go.go files
python.py files
javascript.js, .jsx, .mjs files
typescript.ts, .tsx files
rust.rs files
ruby.rb, .erb files
php.php files
java.java files
yaml.yaml, .yml files
dockerfileDockerfile, *.dockerfile files
terraform.tf files
SeverityWeightMeaning
critical10Immediate security risk. Typically warrants blocking the PR.
error8Serious error that should be fixed before merging.
high7Serious issue that should be addressed before merging.
medium5Notable concern worth reviewing.
low3Minor issue or style violation.
info1Informational finding. Does not significantly affect the risk score.

Run the pack against a local repository or diff to verify it works:

Terminal window
pullminder rules test --pack my-check --verbose

This runs the pack against the current working directory’s latest diff and prints each matched pattern with the file, line number, and matched text.

To test against a specific diff:

Terminal window
pullminder rules test --pack my-check --diff ./path/to/diff.patch

To test against a specific file:

Terminal window
pullminder rules test --pack my-check --file ./src/config.py

Before publishing, validate that all packs in the registry conform to the schema:

Terminal window
pullminder registry validate --strict

The --strict flag enables additional checks:

  • Every pattern must have a unique rule_id.
  • The regex field must compile without errors.
  • The version field must be a positive integer.
  • The severity field must be one of the allowed values.

Fix any validation errors before proceeding.

To share your pack with the Pullminder community:

Terminal window
pullminder rules publish --pack my-check

This submits the pack for review. Once approved, it appears in the official registry and can be enabled by any Pullminder user from the dashboard or CLI.

  • The pack must pass pullminder registry validate --strict.
  • The author field must match your authenticated GitHub handle.
  • The pack must include at least one pattern with a description.
  • The slug must not conflict with an existing pack in the registry.

If you prefer to keep packs private, push the registry to a Git repository and configure it in the Pullminder dashboard:

  1. Push your registry to a private GitHub repository.
  2. In the Pullminder dashboard, navigate to Settings > Registries.
  3. Click Add registry and enter the repository URL.
  4. Pullminder syncs the registry and makes its packs available for your organization.

You can also configure a custom registry via the CLI:

Terminal window
pullminder registry add https://github.com/your-org/my-rules.git

Pullminder pulls packs from custom registries on every sync cycle (default: every 15 minutes) and applies them alongside the official packs.