A zero-dependency git hooks manager. One Python file, stdlib only.
Copy hookpack.py somewhere on your PATH (or run it directly), then install hooks into a repository:
# install the secret scanner and whitespace trimmer (both pre-commit) $ hookpack add secretscan $ hookpack add trimtrail
Pass --work-dir DIR before the subcommand to target another repository:
$ hookpack --work-dir ~/code/myrepo add trimtrail
All commands:
| Command | Description |
|---|---|
hookpack add NAME | Install a hook into the current repo |
hookpack remove NAME | Remove an installed hook |
hookpack list | List available and installed hooks |
hookpack doctor | Verify managed hooks, print hook dir, check PATH |
| Hook | Event | What it does |
|---|---|---|
secretscan |
pre-commit | Runs the secretgate scanner (python3 secretgate.py scan .). Uses a local secretgate.py at the repo root if present, otherwise downloads the pinned copy to .git/hookpack/cache/. If neither works (e.g. no network), it prints a notice and skips gracefully instead of blocking your commit. |
trimtrail |
pre-commit | Strips trailing whitespace from staged text files (binary files are detected via grep -I and skipped), then re-stages the fixed files. |
# hookpack:managed marker. Any pre-existing hook without that marker is refused with a clear error (exit 1) — hookpack never touches a hook file it did not create..git/hookpack/<name>.hook; a single dispatcher is generated at .git/hooks/<event> (e.g. .git/hooks/pre-commit) and runs every managed hook for that event — any hook exiting non-zero fails the commit (the last non-zero status wins).hookpack remove deletes the hook file and regenerates dispatchers (a dispatcher with no remaining managed hooks is deleted too), and linked git worktrees are supported — the shared git-dir hooks directory is resolved via git rev-parse --git-path hooks.A zero dependency git hooks manager installs and runs git hooks
(pre-commit, pre-push, commit-msg) without a package ecosystem. hookpack
is a single Python file using only the standard library — no Node, no
virtualenv, no pip install, no .pre-commit-config.yaml.
If the machine has Python 3, it works.
pre-commit is excellent but pulls in a Python package, a
per-repo virtualenv cache, and a config schema that assumes network
access to resolve hook repositories. hookpack assumes nothing: each hook
is one small script, dispatchers are written into
.git/hooks/ between managed markers, and removing hookpack
cleanly removes only what it added. For air-gapped CI, minimal containers,
and "I just want a pre-commit secret scan" repos, it is the lighter path.
Use hookpack's secretscan hook: it fetches the
single-file secretgate
scanner with curl at run time and blocks commits containing API keys,
tokens, or private keys. No scanner needs to be installed —
python3 hookpack.py add secretscan is the whole setup.
No. Every file hookpack manages carries a # hookpack:managed
marker, and hookpack refuses — with an error, before writing anything —
to modify any hook file that lacks that marker. Your hand-written hooks
are never overwritten, and hookpack remove deletes only
hookpack's own files.
Yes. Every release attaches a self-contained signed receipt,
hookpack-<tag>-proof.md, with the exact release file
embedded. One command proves it:
python3 ethkey.py verify hookpack-<tag>-proof.md --require
0xFD4090e27C1f946Ff01a265cAa7d4ACA662acC15 exits 0 only if the
payload hash, the EIP-191 signature, and the signer all check out — or
paste the receipt into the
browser
verifier (the link pre-fills the address).
The legacy <tag>.sig.txt asset is still attached for
compatibility.
hookpack is part of a small family of curl-and-run tools:
Zero-dependency, curl-and-run secret scanner. Powers the secretscan hook.
GitHub Action wrapper that runs secretgate checks in CI.
Lightweight crypto signing tool — paste any release receipt into the browser verifier.
Related reading: how to vet a GitHub bounty payout rail (the other thing our agents build).