skillmake
← marketplace
engineerstoolsha:315da17d06432980manual

mp-git-guardrails

Use when you want Claude Code's Bash tool to refuse dangerous git commands (push, reset --hard, clean -f, branch -D, checkout .) via a PreToolUse hook installed in .claude/settings.json or ~/.claude/settings.json.

One-line install
curl --create-dirs -fsSL https://skillmake.xyz/i/mp-git-guardrails -o ~/.claude/skills/mp-git-guardrails/SKILL.md

The hash above pins this exact content. The file we serve at /api/marketplace/mp-git-guardrails-315da17d/raw always matches sha:315da17d06432980.

4,458 chars · ~1,115 tokens
---
name: mp-git-guardrails
description: "Use when you want Claude Code's Bash tool to refuse dangerous git commands (push, reset --hard, clean -f, branch -D, checkout .) via a PreToolUse hook installed in .claude/settings.json or ~/.claude/settings.json."
source: https://github.com/mattpocock/skills/blob/main/skills/misc/git-guardrails-claude-code/SKILL.md
generated: 2026-05-12T18:05:01.929Z
category: tool
audience: engineers
---

## When to use

- Adding a safety net so a runaway agent can't `git push --force` or `git reset --hard` on your behalf
- Sharing the same guardrails across all projects via the global ~/.claude/settings.json scope
- Customising the blocked-command list (add/remove patterns) per project
- Smoke-testing the hook with a single echo'd JSON payload before relying on it

## Key concepts

### PreToolUse Bash matcher

A Claude Code hook type that runs BEFORE the Bash tool executes a command. Returning exit code 2 + a stderr message blocks the call and shows Claude the rejection message. Matcher `"Bash"` scopes the hook to the Bash tool only.

### blocked command set

By default: `git push` (all variants including --force), `git reset --hard`, `git clean -f` / `git clean -fd`, `git branch -D`, `git checkout .`, `git restore .`. Section 4 of the skill prompts the user to edit this list if they want different patterns.

### project vs global scope

Step 1 asks the user: install for this project only (`.claude/settings.json` + `.claude/hooks/`) or for all projects (`~/.claude/settings.json` + `~/.claude/hooks/`). Global scope means new repos get the same guardrails by default.

### merge, don't overwrite

If the target settings file already has hooks, the new PreToolUse entry must be MERGED into the existing array. Overwriting wipes other settings (permissions, model overrides, etc.).

### verify with echo'd JSON

Smoke test: `echo '{"tool_input":{"command":"git push origin main"}}' | <path-to-script>` should exit 2 and print a BLOCKED message to stderr. If it doesn't, the hook won't actually fire when Claude tries to push.

## API reference

```
Project-scope settings.json
```

Drop into `.claude/settings.json`. `$CLAUDE_PROJECT_DIR` resolves to the repo root so the hook path is portable across machines.

```
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/block-dangerous-git.sh"
          }
        ]
      }
    ]
  }
}
```

```
Global-scope settings.json
```

Drop into `~/.claude/settings.json` so every project on the machine inherits the guardrail.

```
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "~/.claude/hooks/block-dangerous-git.sh"
          }
        ]
      }
    ]
  }
}
```

```
Smoke-test the hook
```

Confirm the script actually blocks before relying on it.

```
echo '{"tool_input":{"command":"git push origin main"}}' | <path-to-script>
# expect: exit code 2 + BLOCKED message on stderr
```

## Gotchas

- Don't overwrite an existing settings.json — MERGE the new hook into hooks.PreToolUse so other settings survive.
- Make the copied script executable with `chmod +x` after copying — Claude Code won't run a non-executable hook.
- Project scope uses `"$CLAUDE_PROJECT_DIR"/.claude/hooks/…`; global scope uses `~/.claude/hooks/…`. Mixing the paths breaks the hook silently.
- Customisation step 4 is optional but important — if you actually need `git push` for something legit (e.g. CI bootstrap), edit the script before installing.
- The smoke test must show exit code 2 AND a BLOCKED message. Exit 0 means the hook ran but didn't refuse — Claude will proceed anyway.
- Default block list covers the common destructive cases but not every edge — e.g. `git remote remove origin` isn't blocked. Add patterns as you discover gaps.
- Hooks only intercept Bash. A skill that uses a non-Bash tool to invoke git (via MCP, etc.) bypasses this entirely.
- Removing the hook later: delete the PreToolUse entry from settings.json AND the script file — leaving an orphan script causes confusion the next time you debug hooks.

---
Generated by SkillMake from https://github.com/mattpocock/skills/blob/main/skills/misc/git-guardrails-claude-code/SKILL.md on 2026-05-12T18:05:01.929Z.
Verify against source before relying on details.

File: ~/.claude/skills/mp-git-guardrails/SKILL.md