-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgit-permissions.sh
More file actions
executable file
Β·136 lines (103 loc) Β· 4.31 KB
/
git-permissions.sh
File metadata and controls
executable file
Β·136 lines (103 loc) Β· 4.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#!/bin/bash
# Git Destructive Command Permissions Hook
# Prevents Claude from running destructive git commands without explicit user approval
#
# This hook protects against:
# - Accidental data loss from git reset/restore/clean
# - Conflicts between multiple Claude sessions working simultaneously
# - Claude making assumptions about which files to discard
#
# Triggered: Pre-Tool hook for Bash commands
# Blocks: Destructive git commands that can permanently delete work
# Read the tool input from stdin (current Claude Code hook format).
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
# Skip if not a git command
if [[ ! "$COMMAND" =~ ^git[[:space:]] ]]; then
exit 0
fi
# Allow safe read-only and staging commands
if [[ "$COMMAND" =~ ^git[[:space:]]+(status|log|diff|show|branch|add|commit|stash|reflog) ]]; then
exit 0
fi
# Allow git restore --staged (only unstaging, not discarding changes)
if [[ "$COMMAND" =~ ^git[[:space:]]+restore[[:space:]]+--staged ]]; then
exit 0
fi
# BLOCK: git reset --hard (destroys all working tree and staged changes)
if [[ "$COMMAND" =~ ^git[[:space:]]+reset[[:space:]]+--hard ]]; then
cat >&2 <<EOF
π BLOCKED: Destructive git command requires explicit user approval
Command: $COMMAND
This command will PERMANENTLY DELETE all uncommitted changes in your working
tree and staging area. This cannot be undone.
β οΈ CRITICAL: Multiple Claude sessions may be working simultaneously.
This command could destroy work from other sessions or your own uncommitted changes.
To proceed: Explicitly tell Claude "yes, run git reset --hard"
(Only do this if you are absolutely certain!)
EOF
exit 2
fi
# BLOCK: git reset --mixed (destroys staged changes, keeps working tree)
if [[ "$COMMAND" =~ ^git[[:space:]]+reset[[:space:]]+--mixed ]]; then
cat >&2 <<EOF
π BLOCKED: Destructive git command requires explicit user approval
Command: $COMMAND
This command will unstage all changes. While it preserves your working tree,
it may interfere with other Claude sessions' staged changes.
To proceed: Explicitly tell Claude "yes, run git reset --mixed"
EOF
exit 2
fi
# BLOCK: git restore <files> (destroys working tree changes for specific files)
# Allow ONLY: git restore --staged
if [[ "$COMMAND" =~ ^git[[:space:]]+restore[[:space:]] ]] && [[ ! "$COMMAND" =~ --staged ]]; then
cat >&2 <<EOF
π BLOCKED: Destructive git command requires explicit user approval
Command: $COMMAND
This command will PERMANENTLY DELETE uncommitted changes to the specified files.
This cannot be undone - the changes will be lost forever.
β οΈ CRITICAL: Another Claude session or you may be working on these files.
Running this command will destroy that work.
To proceed: Explicitly tell Claude "yes, run this git restore command"
(Only do this if you are absolutely certain these changes should be discarded!)
EOF
exit 2
fi
# BLOCK: git checkout <files> (old way to restore files)
if [[ "$COMMAND" =~ ^git[[:space:]]+checkout[[:space:]] ]] && [[ "$COMMAND" =~ [[:space:]]--[[:space:]] ]]; then
cat >&2 <<EOF
π BLOCKED: Destructive git command requires explicit user approval
Command: $COMMAND
This command will PERMANENTLY DELETE uncommitted changes to the specified files.
β οΈ Use 'git restore <file>' instead (also requires approval).
To proceed: Explicitly tell Claude "yes, run this git checkout command"
EOF
exit 2
fi
# BLOCK: git clean -f or -fd (deletes untracked files)
if [[ "$COMMAND" =~ ^git[[:space:]]+clean[[:space:]].*-[fd] ]]; then
cat >&2 <<EOF
π BLOCKED: Destructive git command requires explicit user approval
Command: $COMMAND
This command will PERMANENTLY DELETE untracked files from your working tree.
This cannot be undone.
β οΈ CRITICAL: This may delete files created by other Claude sessions or by you.
To proceed: Explicitly tell Claude "yes, run git clean"
EOF
exit 2
fi
# BLOCK: Any git command with --force flag
if [[ "$COMMAND" =~ --force ]]; then
cat >&2 <<EOF
π BLOCKED: Git command with --force flag requires explicit user approval
Command: $COMMAND
The --force flag overrides safety checks and can cause data loss or
destructive changes to your repository.
To proceed: Explicitly tell Claude "yes, use --force"
EOF
exit 2
fi
# Allow other git commands (push, pull, fetch, etc.)
# Note: git push --force is already blocked above
exit 0