---
name: set-up-git-guardrails-and-pre-commit
description: Sets up safety rails for AI coding agents - a hook that blocks push, reset --hard, clean -f and branch -D before the agent runs them, plus Husky and lint-staged pre-commit checks for format, typecheck and tests. Use when the user wants to stop an AI from pushing or wiping work, add pre-commit hooks, set up Husky, or block dangerous git commands.
license: MIT
metadata:
  category: deployment
  tags: "ci,quality,security,agents"
  author: johnny-bravo
  version: "1.0"
  updated: "2026-10-31"
  status: published
  aliases: "git-guardrails-claude-code,setup-pre-commit,git-guardrails,pre-commit-hooks"
  source_url: "https://github.com/mattpocock/skills/tree/a496f5513d4a4cf889bc48e189e579f4b0bdf6aa/skills/misc/git-guardrails-claude-code"
  source_license: MIT
  copyright: "Copyright (c) 2026 Matt Pocock"
  original_author: "Matt Pocock (mattpocock/skills, 'git-guardrails-claude-code' and 'setup-pre-commit')"
  modified: "Adapted by TheSkillVault: git-guardrails-claude-code and setup-pre-commit (same repo and commit, skills/misc/setup-pre-commit) merged into one skill; hook script works without jq and blocks push -f and rebase; notes for tools other than Claude Code; added secrets, gotchas and done-when sections."
  imported_on: "2026-10-31"
---

# Set up git guardrails and pre-commit checks

Two safety rails for working with AI agents. A hook stops the agent from running git commands that push or destroy work. A pre-commit hook checks formatting, types and tests before every commit.

## When to use
- You let an AI agent run shell commands and do not want it to push or wipe changes.
- You want every commit checked for format, types and tests automatically.
- You are setting up a new repo that agents will work in.

## Steps
### Part 1: block dangerous git commands (Claude Code hook)
1. **Pick the scope.** This project only (`.claude/settings.json`) or all projects (`~/.claude/settings.json`).
2. **Copy the script** [scripts/block-dangerous-git.sh](scripts/block-dangerous-git.sh) to `.claude/hooks/` (project) or `~/.claude/hooks/` (global). Run `chmod +x` on it. It blocks `git push` (all forms), `reset --hard`, `clean -f`/`-fd`, `branch -D`, `checkout .`, `restore .` and `rebase`.
3. **Register the hook.** Merge this into the settings file. Keep any existing hooks; do not overwrite the file.
   ```json
   {
     "hooks": {
       "PreToolUse": [
         { "matcher": "Bash",
           "hooks": [{ "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/block-dangerous-git.sh" }] }
       ]
     }
   }
   ```
   For the global scope, use `~/.claude/hooks/block-dangerous-git.sh` as the command.
4. **Customise.** Ask which patterns to add or remove, and edit the list in the script.
5. **Test it.** This should print BLOCKED and exit with code 2:
   ```bash
   echo '{"tool_input":{"command":"git push origin main"}}' | .claude/hooks/block-dangerous-git.sh; echo $?
   ```

### Part 2: pre-commit checks (Husky + lint-staged + Prettier)
6. **Detect the package manager** from the lockfile: `package-lock.json` (npm), `pnpm-lock.yaml`, `yarn.lock` or `bun.lockb`. Default to npm.
7. **Install** dev dependencies `husky lint-staged prettier`, then run `npx husky init`. That creates `.husky/` and adds `"prepare": "husky"`.
8. **Write `.husky/pre-commit`** (Husky v9+ needs no shebang). Drop any line whose script does not exist, and tell the user:
   ```
   npx lint-staged
   npm run typecheck
   npm run test
   ```
9. **Write `.lintstagedrc`:** `{ "*": "prettier --ignore-unknown --write" }`. Add a `.prettierrc` only if the repo has no Prettier config.
10. **Smoke test.** Run `npx lint-staged`, then commit the new files with `Add pre-commit hooks (husky + lint-staged + prettier)`. The commit itself runs the hook.

## Gotchas
- The git hook matches text. It is a seatbelt, not a lock: an agent can still dodge it with an alias or a script. Keep real protection too, such as branch protection on main.
- If your agent's shell tool has another name than `Bash`, change the `matcher`.
- Full test suites in pre-commit can be slow. If commits take minutes, move tests to CI and keep lint-staged plus typecheck.
- `git commit --no-verify` skips the pre-commit hook. Tell your agent never to use it.

## Safety
- Add a secret scan (for example `gitleaks protect --staged`) to the pre-commit hook so API keys, tokens and `.env` files never get committed.
- Make sure `.env` and other credential files are in `.gitignore` before the first commit.

## Works with other tools
Part 1 uses Claude Code hooks. Cursor, Codex and similar agents have their own command allow/deny lists or hooks; block the same patterns there. Part 2 works with any AI or none. For Python, the `pre-commit` framework is the equivalent of Husky.

## Done when
- The test in step 5 prints BLOCKED and exits 2, and `git status` still runs.
- A commit runs lint-staged, typecheck and tests, and fails if any of them fail.

## Example prompt
"Stop my AI agent from ever running git push or reset --hard, and add pre-commit checks to this repo."

---
Adapted from "git-guardrails-claude-code" and "setup-pre-commit" in mattpocock/skills by Matt Pocock (MIT). See LICENSE.txt.
