npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

sfdx-gatekeeper

v1.1.1

Published

A lightweight pre-commit validation framework for Salesforce projects

Downloads

585

Readme

npm version Node.js License: MIT

Automated pre-commit validation for Salesforce SFDX projects.

Stop bad commits before they hit the repo. Keep your codebase clean. Ship with confidence.

What it validates: Branch naming · Commit messages · Component prefixes · Package.xml sync · Apex documentation

Why teams love it: Catch issues at commit time · Enforce standards automatically · Fully extensible with custom validations

Quick Start · Features · Report Bug


Features

  • Easy Configuration - Simple YAML config file
  • Extensible - Add your own custom validations
  • Beautiful Output - Clean, formatted terminal output with helpful tips
  • Package XML Audit - Find sync issues between force-app and package.xml
  • Apex Documentation - Enforce class and method-level comments
  • Minimal Dependencies - Only js-yaml for config parsing
  • Salesforce Focused - Built specifically for SFDX projects

Table of Contents


Installation

npm install sfdx-gatekeeper --save-dev

Note: If you encounter peer dependency conflicts, use the --legacy-peer-deps flag.


Quick Start

# 1. Initialize config folder
npx sfdx-gatekeeper init

# 2. Install git hooks
npx sfdx-gatekeeper install

# 3. Done! Commits will now be validated automatically

Sample Output

When all validations pass:

[SFDX Gatekeeper Validations]
══════════════════════════════
  ✔ Branch Naming Convention            [Pass]
  ✔ Commit Message Standards            [Pass]
  ✔ Component Prefix (MYCO_)            [Pass]
  ✔ Package XML in Sync                 [Pass]

  Result: 4/4 checks passed
═══════════════════════════════════

When validation fails:

[SFDX Gatekeeper Validations]
══════════════════════════════
  ✔ Branch Naming Convention            [Pass]
  ✘ Commit Message Standards            [Failed]
    → Must start with "Commit for"
  - Component Prefix (disabled)         [Skipped]
    → No prefix configured
  ✘ Package XML in Sync                 [Failed]
    → package.xml updated but not staged

  Result: 1/3 checks passed

  Tips:
    • Start with "Commit for" followed by type/ticket.
    • Example: "Commit for S-12345 - Fixed login validation"
    • Example: "Commit for Bug Fix - Resolved timeout issue"
    • Example: "Commit for Feature - Added bulk processing"
═══════════════════════════════════

Commands

Setup Commands

| Command | Description | |:--------|:------------| | npx sfdx-gatekeeper init | Create .sfdx-gatekeeper/ folder with config files | | npx sfdx-gatekeeper install | Install git hooks in current project | | npx sfdx-gatekeeper uninstall | Remove git hooks from current project |

Utility Commands

| Command | Description | |:--------|:------------| | npx sfdx-gatekeeper list | List all available validations (built-in and custom) | | npx sfdx-gatekeeper run pre-commit | Run pre-commit validations manually | | npx sfdx-gatekeeper run commit-msg <file> | Run commit message validation manually | | npx sfdx-gatekeeper test | Test output formatting (demo only) | | npx sfdx-gatekeeper version | Show version number | | npx sfdx-gatekeeper help | Show help message |

Audit Commands

Why Audit?

In Salesforce projects, manifest/package.xml must stay in sync with your force-app/ components for deployments to work correctly. Over time, projects can get out of sync:

  • Missing entries - New components added to force-app/ but forgotten in package.xml
  • Orphaned entries - Old components deleted from force-app/ but still listed in package.xml

This causes deployment failures, missing metadata, or bloated package files.

What Does Audit Do?

Audit compares your branch components (force-app/) against your deployment manifest (package.xml) and reports any mismatches:

┌─────────────────────┐         ┌─────────────────────┐
│   force-app/        │         │   package.xml       │
│   (Your Code)       │  ←───→  │   (Deploy Manifest) │
└─────────────────────┘         └─────────────────────┘
         │                                │
         └──── Should be in sync ─────────┘

How to Use

Basic Commands:

| Command | What it does | |:--------|:-------------| | npx sfdx-gatekeeper audit | Full audit - checks both directions | | npx sfdx-gatekeeper audit all | Same as above | | npx sfdx-gatekeeper audit missing | Find components in force-app/ but NOT in package.xml | | npx sfdx-gatekeeper audit orphan | Find entries in package.xml but NOT in force-app/ |

Export to CSV:

| Command | Output | |:--------|:-------| | npx sfdx-gatekeeper audit --csv | Full report to CSV | | npx sfdx-gatekeeper audit missing --csv | Missing components to CSV | | npx sfdx-gatekeeper audit orphan --csv | Orphaned entries to CSV |

CSV filename format: package-xml-audit-YYYY-MM-DD-HHmmss.csv

Example Output

[Package.xml Audit]
══════════════════════════════

Missing in package.xml (3):
  • ApexClass: AccountHelper
  • ApexClass: ContactService
  • LightningComponentBundle: myNewComponent

Orphaned in package.xml (2):
  • ApexClass: OldUnusedClass
  • ApexTrigger: DeprecatedTrigger

Summary: 3 missing, 2 orphaned
══════════════════════════════

Tip: Audit commands work standalone - no need to run init or install first. Great for one-time cleanups or CI/CD pipelines.


Uninstallation

# Remove git hooks
npx sfdx-gatekeeper uninstall

# Remove the package
npm uninstall sfdx-gatekeeper

# (Optional) Remove config folder
rm -rf .sfdx-gatekeeper/

Configuration

Folder Structure

After running init, you'll have:

.sfdx-gatekeeper/
├── config.yml                    # Main configuration
├── metadata-mapping.json         # Metadata type mappings (editable)
└── validations/                  # Custom validations folder
    └── _sample-validation.js     # Template for custom validations

Validation Order

Validations run in the order listed in config.yml:

validations:
  enabled:
    - branch-naming      # Runs 1st
    - commit-message     # Runs 2nd
    - component-prefix   # Runs 3rd
    - package-xml        # Runs 4th
    - apex-comments      # Runs 5th (if enabled)

To change the order, simply reorder the list.


Built-in Validations

| Validation | Description | Default | |:-----------|:------------|:--------| | branch-naming | Enforces branch naming convention | Enabled | | commit-message | Validates commit message format, blocks lazy commits | Enabled | | component-prefix | Checks SF components have required prefix | Enabled | | package-xml | Validates package.xml is in sync with force-app | Enabled | | apex-comments | Checks Apex classes/triggers have documentation | Disabled |


Validation Details

1. Branch Naming (branch-naming)

Enforces branch naming patterns.

branch-naming:
  pattern: "^(feature|bugfix|hotfix|release|develop|main|master)/"
  exempt:
    - main
    - master
    - develop

Valid branches: feature/S-12345, bugfix/login-fix, hotfix/urgent-patch


2. Commit Message (commit-message)

Validates commit message format and blocks lazy/generic messages.

commit-message:
  prefix: "Commit for"
  issuePattern: "[IS]-[0-9]+"
  blockedPhrases:
    - "initial commit"
    - "dummy"
    - "wip"
  requireDescription: true

Valid format: Commit for <Type/Ticket> - <Description>

Examples:

Commit for S-12345 - Fixed login validation
Commit for Bug Fix - Resolved null pointer in UserService
Commit for AccountHelper - Added bulk processing

What it blocks:

  • Empty messages
  • Messages shorter than 10 characters
  • Generic messages: fix, update, changes, wip, test, etc.
  • Placeholder text: TODO, FIXME, your message here, etc.
  • Missing prefix or description separator

3. Component Prefix (component-prefix)

Ensures Salesforce components follow naming conventions.

Why use prefixes? Prefixes help identify custom components at a glance, prevent naming collisions with managed packages, and maintain consistency across your org.

Single prefix:

component-prefix:
  prefix: "MYCO_"
  checkTypes:
    - lwc
    - aura
    - classes
    - triggers

Example valid components with MYCO_ prefix:

| Type | Valid Name | File Path | |:-----|:-----------|:----------| | Apex Class | MYCO_AccountService | classes/MYCO_AccountService.cls | | Apex Trigger | MYCO_AccountTrigger | triggers/MYCO_AccountTrigger.trigger | | LWC | MYCO_dataTable | lwc/MYCO_dataTable/ | | Aura | MYCO_RecordForm | aura/MYCO_RecordForm/ |

Multiple prefixes (for multi-team or multi-app projects):

component-prefix:
  prefix:
    - "SALES_"      # Sales team components
    - "SERVICE_"    # Service team components
    - "UTIL_"       # Shared utility components
  checkTypes:
    - lwc
    - aura
    - classes
    - triggers

Example valid components with multiple prefixes:

| Team | Type | Component Name | |:-----|:-----|:---------------| | Sales | Apex Class | SALES_OpportunityHandler | | Sales | LWC | SALES_quoteBuilder | | Service | Apex Class | SERVICE_CaseEscalation | | Service | Aura | SERVICE_KnowledgeSearch | | Shared | Apex Class | UTIL_StringHelper | | Shared | LWC | UTIL_modal |

Common prefix patterns in Salesforce:

| Pattern | Use Case | Example Components | |:--------|:---------|:-------------------| | MYCO_ | Company abbreviation | MYCO_AccountService.cls, MYCO_contactCard (LWC) | | APP_ | Application identifier | APP_InvoiceHandler.cls, APP_dashboard (LWC) | | UTIL_ | Utility/shared | UTIL_DateHelper.cls, UTIL_modal (LWC) | | INT_ | Integrations | INT_APICallout.cls, INT_webhookHandler (LWC) | | TEST_ | Test utilities | TEST_DataFactory.cls |

Disable validation (for projects without prefix convention):

component-prefix:
  prefix: ""    # Empty string disables validation

4. Package XML Sync (package-xml)

Validates that staged components are in sync with package.xml.

package-xml:
  path: "manifest/package.xml"
  forceAppPath: "force-app/main/default"
  checkDeletions: true
  skipTypes: []            # Add metadata types to skip

What it detects:

| Scenario | Error Message | |:---------|:--------------| | New component staged, not in package.xml | "Add to package.xml: ApexClass: MyClass" | | Component deleted, still in package.xml | "Remove from package.xml: ApexClass: OldClass" | | package.xml updated but not staged | "package.xml updated but not staged" |

Skip certain metadata types:

package-xml:
  skipTypes:
    - Profile
    - CustomMetadata
    - CustomLabel

Note: Types with <members>*</members> in package.xml are automatically skipped.


5. Apex Documentation (apex-comments)

Checks for class-level and method-level documentation in Apex files.

Enable by adding to the list:

validations:
  enabled:
    - branch-naming
    - commit-message
    - component-prefix
    - package-xml
    - apex-comments        # Add this line

Configuration:

apex-comments:
  requireClassComment: true      # Require class/trigger header comments
  requireMethodComment: true     # Require method-level comments
  checkTests: false              # Skip @IsTest annotated classes
  skipGettersSetters: true       # Skip getter/setter methods
  skipMethods:                   # Specific methods to skip
    - execute
    - finish

Valid comment styles:

/**
 * JavaDoc style comment
 * @author John Doe
 * @date 2024-01-15
 */
public class AccountService {

    /**
     * Retrieves accounts by type.
     * @param accountType The type of accounts to retrieve
     * @return List of matching accounts
     */
    public List<Account> getAccountsByType(String accountType) {
        // Implementation
    }
}

Or simple comments:

// Service class for account operations
public class AccountService {

    // Get accounts by type
    public List<Account> getAccountsByType(String accountType) {
        // Implementation
    }
}

Custom Validations

Create your own validations by copying the sample template.

Quick Start

# 1. Copy the sample template (remove underscore prefix)
cp .sfdx-gatekeeper/validations/_sample-validation.js \
   .sfdx-gatekeeper/validations/my-check.js

# 2. Edit my-check.js with your logic

# 3. Enable in config.yml
validations:
  enabled:
    - branch-naming
    - commit-message
    - my-check          # Your custom validation

Validation Structure

class MyValidation {
    constructor(validator) {
        this.validator = validator;
        this.config = validator.config.validations['my-check'] || {};
        this.displayName = 'My Custom Check';
    }

    run() {
        // Available methods:
        // this.validator.getStagedFiles()       - Array of staged file paths
        // this.validator.getDeletedStagedFiles() - Array of deleted staged files
        // this.validator.getCurrentBranch()     - Current branch name
        // this.validator.commitMsgFile          - Path to commit message file
        // this.validator.projectRoot            - Project root directory

        // Return object:
        // status: 'pass' | 'fail' | 'skip'
        // details: string or array of strings
        // tip: string or array of strings (shown on fail)
        
        return { status: 'pass' };
    }
}

module.exports = MyValidation;

Example: Require Test Class

class RequireTestValidation {
    constructor(validator) {
        this.validator = validator;
        this.displayName = 'Test Class Required';
    }

    run() {
        const stagedFiles = this.validator.getStagedFiles();
        
        const classes = stagedFiles.filter(f => 
            f.includes('/classes/') && f.endsWith('.cls') && !f.includes('Test')
        );
        const tests = stagedFiles.filter(f => 
            f.includes('/classes/') && f.includes('Test.cls')
        );
        
        if (classes.length > 0 && tests.length === 0) {
            return {
                status: 'fail',
                details: 'Apex class committed without test class',
                tip: 'Include a test class in your commit'
            };
        }
        return { status: 'pass' };
    }
}

module.exports = RequireTestValidation;

Note: Files starting with _ (like _sample-validation.js) are ignored and not loaded.


Metadata Mapping

Edit .sfdx-gatekeeper/metadata-mapping.json to customize metadata type detection:

{
  "folderToType": {
    "classes": "ApexClass",
    "triggers": "ApexTrigger",
    "lwc": "LightningComponentBundle",
    "aura": "AuraDefinitionBundle",
    "myCustomFolder": "MyCustomMetadataType"
  },
  "folderBasedTypes": [
    "lwc",
    "aura",
    "experiences"
  ],
  "fileExtensions": {
    "classes": ".cls",
    "triggers": ".trigger"
  }
}

Team Setup

Overview

SFDX Gatekeeper supports zero-config setup for developers. The DevOps Lead configures everything once, commits it to the repo, and developers just run npm install.

For DevOps Lead / Tech Lead (One-Time Setup)

Step 1: Install and initialize

# Install as dev dependency
npm install sfdx-gatekeeper --save-dev

# Create config folder with templates
npx sfdx-gatekeeper init

Step 2: Configure validations

Edit .sfdx-gatekeeper/config.yml with your team's standards:

validations:
  enabled:
    - branch-naming
    - commit-message
    - component-prefix
    - package-xml

  component-prefix:
    prefix:
      - "SALES_"
      - "SERVICE_"
    checkTypes:
      - lwc
      - aura
      - classes
      - triggers

  branch-naming:
    pattern: "^(feature|bugfix|hotfix)/[A-Z]+-[0-9]+-.+"

Step 3: Test locally

# Install hooks on your machine
npx sfdx-gatekeeper install

# Test with a bad commit
git commit -m "bad"  # Should fail

# Test with a good commit
git commit -m "feat(auth): add login validation"  # Should pass

Step 4: Add auto-install script

Add the prepare script to your project's package.json:

{
  "scripts": {
    "prepare": "npx sfdx-gatekeeper install || true"
  },
  "devDependencies": {
    "sfdx-gatekeeper": "^1.1.0"
  }
}

The || true prevents errors if .git folder doesn't exist (e.g., in CI or fresh downloads).

Step 5: Commit everything

git add package.json package-lock.json .sfdx-gatekeeper/
git commit -m "chore: setup pre-commit validations with sfdx-gatekeeper"
git push

For Developers (Zero Config!)

After DevOps commits the setup, developers just:

# Clone the repo
git clone <repo-url>
cd <project>

# Install dependencies (hooks auto-install!)
npm install

# Output:
# > prepare
# > npx sfdx-gatekeeper install
# ✔ Git hooks installed successfully!

# Done! Just code and commit normally

What Gets Shared vs Local

| File/Folder | Committed? | Shared? | Purpose | |-------------|------------|---------|---------| | .sfdx-gatekeeper/config.yml | ✅ Yes | ✅ Team-wide | Validation rules | | .sfdx-gatekeeper/validations/ | ✅ Yes | ✅ Team-wide | Custom validations | | package.json (prepare script) | ✅ Yes | ✅ Team-wide | Auto-install hooks | | .git/hooks/commit-msg | ❌ No | ❌ Local | Created by prepare |

Updating Configuration

When DevOps updates .sfdx-gatekeeper/config.yml:

# Developers just pull
git pull origin develop

# Hooks automatically use the updated config
# No reinstall needed!

Audit-Only Usage

If you only need to check package.xml sync without installing commit hooks:

# Install
npm install sfdx-gatekeeper --save-dev

# Run audit (no init or install needed)
npx sfdx-gatekeeper audit                 # Full audit to console
npx sfdx-gatekeeper audit missing         # Only missing components
npx sfdx-gatekeeper audit orphan          # Only orphaned entries
npx sfdx-gatekeeper audit --csv           # Export full report to CSV
npx sfdx-gatekeeper audit missing --csv   # Export missing to CSV

This is useful for:

  • One-time cleanup of legacy projects
  • CI/CD pipeline checks before deployment
  • Verifying package.xml before a release

Bypassing Hooks (Emergency)

If you need to bypass validation temporarily:

git commit --no-verify -m "Emergency fix"

Warning: Use sparingly. Consider fixing the validation issue instead.


Troubleshooting

| Issue | Solution | |:------|:---------| | Peer dependency conflicts | Use --legacy-peer-deps flag | | Hooks not running | Run npx sfdx-gatekeeper install again | | Wrong validation order | Reorder items in config.yml under enabled | | Skip a validation | Remove it from enabled list or set config to skip | | package.xml false positive | Add metadata type to skipTypes |


Requirements

  • Node.js >= 14.0.0
  • Git

Author

Milanjeet Singh


License

MIT - see the LICENSE file for details.