Skip to content

Pre-commit Hooks

CI pipelines catch threats after a push. By then the code is in git history, visible to collaborators, and potentially already deployed. A pre-commit hook stops the commit entirely — keeping your repository clean from the start, before anything leaves your machine.

CI catches issues after a push, which means threats travel through git history and may be visible to collaborators before anyone acts on them. A pre-commit hook stops the commit entirely if threats are found, keeping your repository clean from the start.

Firmis is well-suited for pre-commit use because it is:

  • Fast — most projects scan in under 3 seconds
  • Zero-install — runs via npx with no prior setup
  • Offline — no network requests for the core scan (OSV check is optional)

Husky is the standard pre-commit hook manager for Node.js projects.

  1. Install Husky and configure it:

    Terminal
    npx husky init
  2. Add the Firmis scan command to .husky/pre-commit:

    .husky/pre-commit
    #!/usr/bin/env sh
    . "$(dirname -- "$0")/_/husky.sh"
    # Run Firmis on staged files — fail commit if high/critical threats found
    npx firmis scan . --severity high --quiet
  3. Make the hook executable:

    Terminal
    chmod +x .husky/pre-commit
  4. Add Husky to your package.json prepare script so it installs for all contributors:

    package.json
    {
    "scripts": {
    "prepare": "husky"
    }
    }

For large projects, scanning only the files staged for commit reduces hook latency.

.husky/pre-commit
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
# Get staged files
STAGED=$(git diff --cached --name-only --diff-filter=ACM | head -50)
if [ -z "$STAGED" ]; then
exit 0
fi
# Write staged file list to a temp file
TMPFILE=$(mktemp)
echo "$STAGED" > "$TMPFILE"
# Scan only the project root (firmis auto-discovers components)
npx firmis scan . --severity high --quiet
EXIT_CODE=$?
rm -f "$TMPFILE"
exit $EXIT_CODE

What to scan: full project vs. staged files only

Section titled “What to scan: full project vs. staged files only”
ApproachSpeedCoverageRecommended for
Full project scan1–5sAll agent componentsMost projects
Staged files onlyFasterOnly committed filesLarge monorepos

For most projects, scanning the full project is the right choice. Firmis auto-discovers AI agent components (Claude Skills, MCP servers, Cursor rules, etc.) and needs the full directory tree to find them. Scanning staged files individually can miss threats in component manifests that reference files not staged in the current commit.

If you need to commit without running the hook (for example, to commit a work-in-progress or suppress a known false positive), use:

Terminal
git commit --no-verify -m "wip: work in progress"

Rather than bypassing the hook, add false positives to .firmisignore.

.firmisignore
# Suppress a specific rule on a specific file
test/fixtures/evil-server.ts # firmis-ignore: sd-015
# Ignore an entire directory
test/fixtures/

See Ignoring Findings for full .firmisignore syntax.