115 lines
3.4 KiB
Markdown
115 lines
3.4 KiB
Markdown
---
|
|
name: git-guardrails
|
|
description: Set up git safety guardrails for Claude Code — block dangerous commands (push, reset --hard, clean, branch -D, checkout .) via settings.json deny/ask rules or PreToolUse hooks. Use when user wants to prevent destructive git operations or review their git safety setup.
|
|
---
|
|
|
|
# Git Guardrails for Claude Code
|
|
|
|
Prevent Claude from executing destructive git commands. Two enforcement strategies available — choose one or combine both.
|
|
|
|
## What Gets Blocked
|
|
|
|
- `git push` (all variants including `--force`)
|
|
- `git push --force` (force push — data loss risk)
|
|
- `git reset --hard` (discards uncommitted work)
|
|
- `git clean -f` / `git clean -fd` (deletes untracked files)
|
|
- `git branch -D` (force-delete branch)
|
|
- `git checkout .` / `git restore .` (discards all working changes)
|
|
- `rm -rf /*` / `sudo rm` (filesystem destruction)
|
|
|
|
## Strategy A: settings.json deny/ask rules (Fénix default)
|
|
|
|
This is the simpler approach — no scripts needed. Rules go in `~/.claude/settings.json`:
|
|
|
|
```json
|
|
{
|
|
"permissions": {
|
|
"deny": [
|
|
"Bash(rm -rf /*)",
|
|
"Bash(sudo rm:*)",
|
|
"Bash(git reset --hard:*)",
|
|
"Bash(git push --force:*)"
|
|
],
|
|
"ask": [
|
|
"Bash(git push:*)",
|
|
"Bash(git clean:*)",
|
|
"Bash(git branch -D:*)",
|
|
"Bash(git checkout .:*)",
|
|
"Bash(git restore .:*)",
|
|
"Bash(pkill:*)",
|
|
"Bash(kill:*)"
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
**deny** = hard block, Claude cannot execute even if asked.
|
|
**ask** = Claude must get user confirmation before executing.
|
|
|
|
### When to use
|
|
- Simple setups, single machine
|
|
- When you want some commands to be confirmable (ask) rather than fully blocked (deny)
|
|
- Already configured in `~/.claude/settings.json` — just merge the rules
|
|
|
|
## Strategy B: PreToolUse hook script
|
|
|
|
A shell script that intercepts Bash tool calls and blocks dangerous patterns before execution. More flexible — can use regex, log attempts, etc.
|
|
|
|
### Setup
|
|
|
|
1. Copy the bundled script:
|
|
```bash
|
|
cp scripts/block-dangerous-git.sh ~/.claude/hooks/block-dangerous-git.sh
|
|
chmod +x ~/.claude/hooks/block-dangerous-git.sh
|
|
```
|
|
|
|
2. Add to `~/.claude/settings.json`:
|
|
```json
|
|
{
|
|
"hooks": {
|
|
"PreToolUse": [
|
|
{
|
|
"matcher": "Bash",
|
|
"hooks": [
|
|
{
|
|
"type": "command",
|
|
"command": "~/.claude/hooks/block-dangerous-git.sh"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
### When to use
|
|
- When you need regex-based pattern matching
|
|
- When you want to log blocked attempts
|
|
- When deny/ask rules are too coarse
|
|
|
|
## Verify
|
|
|
|
Test the hook script:
|
|
```bash
|
|
echo '{"tool_input":{"command":"git push origin main"}}' | ~/.claude/hooks/block-dangerous-git.sh
|
|
```
|
|
Should exit code 2 and print BLOCKED to stderr.
|
|
|
|
## Fénix's current setup
|
|
|
|
Already configured in `~/.claude/settings.json`:
|
|
- **deny**: `rm -rf /*`, `sudo rm`, `git reset --hard`, `git push --force`
|
|
- **ask**: `pkill`, `kill`, `ssh`
|
|
- **CLAUDE.md**: Documents git permissions (read freely, write when asked, destructive = confirm first)
|
|
|
|
### Recommended additions to ask rules
|
|
Consider adding these to the `ask` array if not already present:
|
|
- `Bash(git clean:*)` — prevents accidental deletion of untracked files
|
|
- `Bash(git branch -D:*)` — prevents force-deleting branches
|
|
- `Bash(git checkout .:*)` — prevents discarding all working changes
|
|
- `Bash(git restore .:*)` — same as above, modern syntax
|
|
|
|
## Attribution
|
|
|
|
Adapted from [mattpocock/skills](https://github.com/mattpocock/skills) `git-guardrails-claude-code`.
|