with one click
gabyx-githooks-setup
// Set up shared Git hooks using gabyx/Githooks (not standard git hooks). Use when a user asks to set up githooks, apply shared hooks, or configure hook repositories in a project.
// Set up shared Git hooks using gabyx/Githooks (not standard git hooks). Use when a user asks to set up githooks, apply shared hooks, or configure hook repositories in a project.
[HINT] Download the complete skill directory including SKILL.md and all related files
| name | gabyx-githooks-setup |
| description | Set up shared Git hooks using gabyx/Githooks (not standard git hooks). Use when a user asks to set up githooks, apply shared hooks, or configure hook repositories in a project. |
| autouse | false |
Set up and configure shared Git hooks using the gabyx/Githooks manager. This is not the standard git config core.hooksPath system — it is a dedicated hooks manager that supports shared hook repositories, parallel execution, trust verification, and more.
The git hooks CLI (note the space) is provided by gabyx/Githooks. Do not confuse it with standard git hook configuration.
Before proceeding, check whether gabyx/Githooks is installed:
git hooks --version 2>/dev/null
If this command fails or is not found, Githooks is not installed. Refer to INSTALL.md in this skill directory for installation methods, then return here to continue setup.
Ask which setup the user wants:
.githooks/.shared.yaml file so the repo pulls hooks from a specific shared repository, independent of the user's global config.If the user doesn't already have a shared hook repository in mind, ask if they'd like to use jaeyeom/shared-githooks (authored by the same person who wrote this plugin). It includes pre-commit checks (whitespace, non-ASCII filenames, Go linting) and commit-msg checks (subject length, conventional format). The user should review its contents before opting in.
When the shared hook repository is already in the global list (git config --global --get-all githooks.shared), all you need is:
git hooks install
This activates Githooks in the current repository. It rewires .git/hooks to the Githooks runner, which then discovers and executes both local (.githooks/) and globally-configured shared hooks.
Then enable the non-interactive runner globally (one-time per user):
git hooks config non-interactive-runner --enable --global
This makes the runner auto-answer non-fatal prompts with sensible defaults instead of falling back to a blocking GUI dialog when no terminal is attached (the typical case for git commit --amend --no-edit, editor integrations, and CI). The trust prompt remains fatal — see section 6.
After installation, check for replaced hooks (see section 2a below), then update shared hooks:
git hooks shared update
Verify with:
git hooks list
When git hooks install finds existing hook scripts in .git/hooks/, it renames them to *.replaced.githook (e.g., pre-commit → pre-commit.replaced.githook). The Githooks runner executes these in addition to shared hooks, which causes duplicate checks if the shared hooks already cover the same functionality.
After running git hooks install, check for replaced hooks:
ls .git/hooks/*.replaced.githook 2>/dev/null
If any are found:
pre-commit checks and there is a pre-commit.replaced.githook, the pre-commit checks will run twice). Provide the specific rm commands, for example:rm .git/hooks/pre-commit.replaced.githook
rm .git/hooks/commit-msg.replaced.githook
rm .git/hooks/pre-push.replaced.githook
git hooks list to see all hooks that will execute, and comparing the replaced hook contents against the shared hooks.To configure a shared hook repository for a single repo without depending on global config:
# .githooks/.shared.yaml
version: 1
urls:
- "https://github.com/<owner>/<shared-hooks-repo>.git@main"
git hooks install
git hooks config non-interactive-runner --enable --global
This auto-answers non-fatal prompts with sensible defaults so hooks never block on a GUI dialog when no terminal is attached. The trust prompt stays fatal — see section 6.
Check for replaced hooks (see section 2a above) and remove any that are redundant with the shared hooks.
Pull the shared hooks:
git hooks shared update
.githooks/.shared.yaml so other contributors get the same hooks.| Command | Purpose |
|---|---|
git hooks install | Activate Githooks in current repo |
git hooks uninstall | Remove Githooks from current repo |
git hooks shared update | Pull latest shared hook repositories |
git hooks list | Show all hooks that will run and their status |
git hooks config | Manage Githooks settings |
git hooks ignore add | Exclude specific hooks by pattern |
git hooks shared root ns:<namespace> | Show shared repo root for a namespace |
Shared hook repositories update automatically after post-merge (i.e., git pull). To update manually:
git hooks shared update
This pulls the latest from all configured shared hook repositories (both global and repo-specific). Run this after upstream hooks are updated to get fixes.
Note: git hooks shared update only updates shared hooks. Local hooks in the repo's own .githooks/ directory are part of the repo itself and are updated via normal git pull/git checkout.
On servers with multiple users, disable automatic updates to avoid parallel invocations:
git hooks config disable-shared-hooks-update --set
Githooks verifies hook checksums. When new or modified hooks are detected, it prompts for trust confirmation — and unlike other prompts, the trust prompt is fatal under the non-interactive runner enabled in steps 2 and 3. That is intentional: a hard failure tells the user a trust decision is required, instead of silently popping a GUI dialog or hanging a script.
To resolve a trust failure, trust hooks selectively by namespace.
Trusting a specific shared hook repository (recommended):
Each shared hook repo has a namespace (defined in .githooks/.namespace, or a SHA1 prefix of its URL if not set). Use git hooks list to see namespace paths, then trust by pattern:
# See namespace paths for all hooks
git hooks list
# Trust all hooks from a specific shared repo by namespace
git hooks trust hooks --pattern "ns:jaeyeom-shared-githooks/**"
This is safer than trust-all because it only trusts hooks from a known, authored source. When the shared repo updates, you may need to re-run this command to trust the new checksums.
Other trust options:
| Method | Scope | Effect |
|---|---|---|
git hooks trust hooks --pattern "ns:<namespace>/**" | Per-repo, per-user | Trusts hooks matching a namespace pattern — preferred approach |
git hooks trust hooks --all | Per-repo, per-user | Trusts all currently active hooks |
git hooks trust | Per-repo, per-user | Marks repo as trusted for the current user (each collaborator should run this locally) |
.githooks/trust-all file | Per-repo | Marks repo as trusted — do not commit this file; add it to .gitignore instead, as trust is a per-user security decision |
git hooks config trust-all --accept | Per-repo | Auto-accepts all current and future hooks (use with caution — prefer namespace-based trust instead) |
git hooks config trust-all --reset | Per-repo | Reverts trust-all decision |
GITHOOKS_SKIP_UNTRUSTED_HOOKS=true | Per-session | Skips untrusted hooks silently |
GITHOOKS_DISABLE=1 | Per-session | Disables all Githooks entirely |
For CI/automation, either set GITHOOKS_DISABLE=1 to skip hooks entirely, or use trust-all --accept so the runner auto-trusts hooks (the non-interactive runner from initial setup already handles non-fatal prompts).
When a user maintains many repos that all consume the same shared hook repository, the per-repo trust model becomes painful:
git hooks trust hooks --pattern "ns:<namespace>/**".trust-all (security-coarse) or GITHOOKS_SKIP_UNTRUSTED_HOOKS (security-off) just to keep ergonomic defaults.The trust database lives at .git/.githooks.checksums/<sha[:2]>/<sha[2:]> and is content-addressed by SHA. Each entry's stored path: field is decorative — the runner only does a SHA lookup. Pointing every repo's .git/.githooks.checksums at a single global directory therefore makes trust granted in one repo apply to every symlinked repo.
One-time setup per repo:
mkdir -p ~/.githooks/checksums-global
[ -d .git/.githooks.checksums ] && \
cp -R .git/.githooks.checksums/. ~/.githooks/checksums-global/ && \
rm -rf .git/.githooks.checksums
ln -s ~/.githooks/checksums-global .git/.githooks.checksums
After this, running git hooks trust hooks --pattern "ns:<namespace>/**" in any one repo immediately applies to all symlinked repos. A fresh clone with zero local checksums correctly inherits trust through the symlink — no prompts, hooks run normally.
Caveats:
path: field — harmless but worth noting.git clone and git init rebuild .git/, so the symlink must be reinstated on every new clone (a wrapper around git clone can automate this).--all).Upstream tracking: A proper fix (user-scoped trust store with diff-gated re-trust) is requested at gabyx/Githooks#200 but is not yet implemented.
Shared repos organize hooks as:
<repo>/.githooks/<hook-type>/<script>
For example:
.githooks/pre-commit/format-check.sh
.githooks/commit-msg/conventional-commits.sh
Each shared repo can declare a namespace via .githooks/.namespace to avoid naming conflicts.