Zero-dependency git hooks manager. Add, remove, and run git hooks with a single command.
No dependencies. No config files. No prepare scripts. Just add a hook and ship.
Husky is the dominant choice for git hooks in Node.js projects, but it changed its API significantly in v9 and requires adding a prepare script to package.json. Lefthook is great but requires a Go binary. simple-git-hooks is close but has no CLI for managing hooks interactively.
hookguard takes a different approach:
- Zero runtime dependencies — 100% Node.js built-ins
- JSON-first config —
.hookguard/config.jsonis human-readable and git-diffable - Full CLI — add, remove, list, run, and inspect hooks without touching config files
- CI-ready — set
SKIP_HOOKS=1to bypass all hooks in pipelines - Fail-fast — each command in a hook runs sequentially; first failure stops the chain
# Install locally (recommended)
npm install --save-dev hookguard
# Or install globally
npm install -g hookguard# 1. Initialize hookguard in your repo
npx hookguard init
# 2. Add commands to git hooks
npx hookguard add pre-commit "npm test"
npx hookguard add pre-commit "npx eslint src/"
npx hookguard add commit-msg "node scripts/validate-commit.js"
npx hookguard add pre-push "npm run build"
# 3. Check what you've configured
npx hookguard list
# 4. That's it — hooks run automatically on git actionsWhat gets created:
your-repo/
└── .hookguard/
├── config.json ← Commit this (defines your hooks)
└── hooks/
├── pre-commit ← Generated, executable shell script
└── pre-push ← Generated, executable shell script
Commit .hookguard/config.json so your team shares the same hooks. The hooks/ directory is regenerated from config automatically.
Initialize hookguard in the current git repository.
hookguard initCreates .hookguard/config.json and .hookguard/hooks/. Sets git config core.hooksPath .hookguard/hooks automatically.
Add a command to a git hook. Creates the hook if it doesn't exist. Appends if the hook already has commands.
hookguard add pre-commit "npm test"
hookguard add pre-commit "npx eslint src/ --max-warnings 0"
hookguard add pre-push "npm run build && npm run typecheck"
hookguard add commit-msg "node .hookguard/scripts/validate-commit.js"Supported hooks: pre-commit, commit-msg, pre-push, prepare-commit-msg, post-commit, post-merge, pre-rebase, and all standard git hooks.
Remove all commands for a hook and delete the hook file.
hookguard remove pre-commit
hookguard remove pre-pushShow all configured hooks and their commands.
hookguard listOutput:
Configured hooks (2 hooks):
pre-commit (2 commands):
→ npm test
→ npx eslint src/
pre-push (1 command):
→ npm run build
Manually run a configured hook without triggering a git action. Useful for testing.
hookguard run pre-commit
hookguard run pre-pushExit code mirrors the hook exit code — perfect for scripting.
Show current hookguard configuration and git status.
hookguard statusOutput:
hookguard status:
Initialized: yes
Version: 1.0
Git configured: yes (core.hooksPath set)
Active hooks: 2
Hooks: pre-commit, pre-push
Remove hookguard from this repository. Deletes .hookguard/ and resets git core.hooksPath.
hookguard uninstallEvery hook script generated by hookguard checks SKIP_HOOKS=1 before running:
if [ "$SKIP_HOOKS" = "1" ]; then
exit 0
fiSet this in your CI environment to bypass hooks:
# GitHub Actions
- name: Run tests
env:
SKIP_HOOKS: "1"
run: npm testUse hookguard programmatically in your scripts:
const hookguard = require('hookguard');
// Initialize
hookguard.init('/path/to/repo');
// Add a hook
hookguard.add('pre-commit', 'npm test', { description: 'Run test suite' }, '/path/to/repo');
// List hooks
const { hooks, total } = hookguard.list('/path/to/repo');
console.log(`${total} hooks configured`);
// Get status
const status = hookguard.status('/path/to/repo');
if (!status.initialized) console.log('Not set up yet');
// Remove a hook
hookguard.remove('pre-commit', '/path/to/repo');
// Uninstall
hookguard.uninstall('/path/to/repo');All functions throw descriptive errors on failure. All paths default to process.cwd().
When you run hookguard add pre-commit "npm test", hookguard creates .hookguard/hooks/pre-commit:
#!/bin/sh
# Generated by hookguard — do not edit manually
# Manage with: hookguard add / hookguard remove
# Set SKIP_HOOKS=1 to bypass (e.g. in CI pipelines)
if [ "$SKIP_HOOKS" = "1" ]; then
exit 0
fi
# [1/2] npm test
npm test
HOOKGUARD_STATUS=$?
if [ $HOOKGUARD_STATUS -ne 0 ]; then
echo "hookguard: hook failed — npm test"
exit $HOOKGUARD_STATUS
fi
# [2/2] npx eslint src/
npx eslint src/
HOOKGUARD_STATUS=$?
if [ $HOOKGUARD_STATUS -ne 0 ]; then
echo "hookguard: hook failed — npx eslint src/"
exit $HOOKGUARD_STATUS
fiPlain shell. Readable. No magic.
| Feature | hookguard | Husky v9 | lefthook | simple-git-hooks |
|---|---|---|---|---|
| Zero dependencies | ✅ | ✅ | ❌ (Go binary) | ✅ |
| CLI management | ✅ | ❌ | ✅ | ❌ |
| JSON config | ✅ | ❌ (JS) | ✅ (YAML/TOML) | ✅ (package.json) |
prepare script needed |
❌ | ✅ | ❌ | ✅ |
| CI skip built-in | ✅ | ✅ | ✅ | ❌ |
| Programmatic API | ✅ | ❌ | ❌ | ❌ |
| Manual hook runner | ✅ | ❌ | ✅ | ❌ |
| Node.js ≥ 18 only | ✅ | ❌ | ✅ | ❌ |
Issues and PRs welcome at github.com/yonderzenith/hookguard.
MIT © Yonder Zenith LLC
If hookguard saves you time, consider sponsoring on GitHub or buying a coffee. Built by AXIOM — an autonomous AI agent experiment.