-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsettings.json
More file actions
136 lines (136 loc) · 6.21 KB
/
Copy pathsettings.json
File metadata and controls
136 lines (136 loc) · 6.21 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
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"permissions": {
"deny": [
"Bash(rm -rf *)",
"Bash(rm -fr *)",
"Bash(rm -r *)",
"Bash(rm -R *)",
"Bash(rm --recursive *)",
"Bash(sudo *)",
"Bash(git push --force*)",
"Bash(git push * --force*)",
"Bash(git reset --hard*)",
"Bash(git checkout -- .)",
"Bash(git clean -f*)",
"Bash(pip install *--break-system-packages*)",
"Edit(~/.bashrc)",
"Write(~/.bashrc)",
"Edit(~/.zshrc)",
"Write(~/.zshrc)",
"Edit(~/.ssh/**)",
"Write(~/.ssh/**)",
"Read(~/.ssh/**)",
"Edit(~/.gnupg/**)",
"Read(~/.gnupg/**)",
"Write(~/.gnupg/**)",
"Edit(~/.aws/**)",
"Read(~/.aws/**)",
"Write(~/.aws/**)",
"Edit(~/.config/gh/**)",
"Read(~/.config/gh/**)",
"Write(~/.config/gh/**)",
"Edit(~/.git-credentials)",
"Read(~/.git-credentials)",
"Write(~/.git-credentials)",
"Edit(~/.docker/config)",
"Read(~/.docker/config)",
"Write(~/.docker/config)",
"Edit(~/.kube/**)",
"Read(~/.kube/**)",
"Write(~/.kube/**)",
"Edit(~/.npmrc)",
"Read(~/.npmrc)",
"Write(~/.npmrc)",
"Edit(~/.pypirc)",
"Read(~/.pypirc)",
"Write(~/.pypirc)",
"Read(./.env)",
"Read(./.env.*)",
"Read(./**/.env)",
"Read(./**/.env.*)",
"Edit(./.env)",
"Edit(./.env.*)",
"Edit(./**/.env)",
"Edit(./**/.env.*)",
"Write(./.env)",
"Write(./.env.*)",
"Write(./**/.env)",
"Write(./**/.env.*)"
],
"allow": [
"Read",
"Glob",
"Grep",
"Bash(python scripts/quality/*)",
"Bash(python3 scripts/quality/*)",
"Bash(ruff *)",
"Bash(shellcheck *)",
"Bash(git status*)",
"Bash(git diff*)",
"Bash(git log*)",
"Bash(git branch*)",
"Bash(pwd)",
"Bash(which *)",
"Bash(wc *)"
]
},
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "command -v jq >/dev/null 2>&1 || { echo 'BLOCKED: jq is required for safety hooks but is not installed.' >&2; exit 2; }; CMD=$(jq -r '.tool_input.command // empty'); if echo \"$CMD\" | grep -qiE '(^|;[[:space:]]*|&&[[:space:]]*|[|][|][[:space:]]*|[|][[:space:]]*)rm[[:space:]]' && echo \"$CMD\" | grep -qiE '(^|[[:space:]])-[a-zA-Z]*[rR]|--recursive'; then echo 'BLOCKED: recursive rm is not allowed. Remove files individually or use trash.' >&2; exit 2; fi"
},
{
"type": "command",
"command": "command -v jq >/dev/null 2>&1 || { echo 'BLOCKED: jq is required for safety hooks but is not installed.' >&2; exit 2; }; CMD=$(jq -r '.tool_input.command // empty'); if echo \"$CMD\" | grep -qE '(^|[[:space:]])git[[:space:]]+push([[:space:]]+[^[:space:]]+)*([[:space:]]+(refs/heads/)?(main|master)([[:space:]]|$)|[[:space:]]+[^[:space:]]+:(refs/heads/)?(main|master)([[:space:]]|$))'; then echo 'BLOCKED: Do not push directly to main/master. Use a feature branch.' >&2; exit 2; fi"
},
{
"type": "command",
"command": "command -v jq >/dev/null 2>&1 || { echo 'BLOCKED: jq is required for safety hooks but is not installed.' >&2; exit 2; }; CMD=$(jq -r '.tool_input.command // empty'); if echo \"$CMD\" | grep -qE 'git[[:space:]]+reset[[:space:]]+--hard'; then echo 'BLOCKED: git reset --hard is not allowed.' >&2; exit 2; fi"
},
{
"type": "command",
"command": "command -v jq >/dev/null 2>&1 || { echo 'BLOCKED: jq is required for safety hooks but is not installed.' >&2; exit 2; }; CMD=$(jq -r '.tool_input.command // empty'); if echo \"$CMD\" | grep -qE '(^|[[:space:]])git[[:space:]]+push([[:space:]]|$).*([[:space:]]--force(-with-lease)?([[:space:]]|$)|[[:space:]]-f([[:space:]]|$))'; then echo 'BLOCKED: Force push is not allowed.' >&2; exit 2; fi"
},
{
"type": "command",
"command": "command -v jq >/dev/null 2>&1 || { echo 'BLOCKED: jq is required for safety hooks but is not installed.' >&2; exit 2; }; CMD=$(jq -r '.tool_input.command // empty'); if echo \"$CMD\" | grep -qiE '((~|\\$HOME|\\$\\{HOME\\}|/home/[^/]+|/Users/[^/]+|/root)/(\\.ssh|\\.aws|\\.gnupg|\\.docker/config|\\.kube|\\.npmrc|\\.pypirc)|(~|\\$HOME|\\$\\{HOME\\}|/home/[^/]+|/Users/[^/]+|/root)/\\.git-credentials|(^|[[:space:]])\\.env([[:space:]]|$)|/\\.env(\\.|$))'; then echo 'BLOCKED: Accessing secrets/credentials via bash is not allowed.' >&2; exit 2; fi"
}
]
},
{
"matcher": "Read",
"hooks": [
{
"type": "command",
"command": "command -v jq >/dev/null 2>&1 || { echo 'BLOCKED: jq is required for safety hooks but is not installed.' >&2; exit 2; }; FILE=$(jq -r '.tool_input.file_path // empty'); if echo \"$FILE\" | grep -qiE '(\\.env$|\\.env\\.|/\\.ssh/|/\\.aws/|/\\.gnupg/|/\\.git-credentials|/\\.docker/config|/\\.kube/|/\\.npmrc|/\\.pypirc|/Keychains/)'; then echo \"BLOCKED: Reading secrets/credentials ($FILE) is not allowed.\" >&2; exit 2; fi"
}
]
},
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "command -v jq >/dev/null 2>&1 || { echo 'BLOCKED: jq is required for safety hooks but is not installed.' >&2; exit 2; }; FILE=$(jq -r '.tool_input.file_path // empty'); if echo \"$FILE\" | grep -qiE '(\\.bashrc|\\.zshrc|/\\.ssh/|/\\.aws/|/\\.gnupg/|/\\.git-credentials|/\\.docker/config|/\\.kube/|/\\.npmrc|/\\.pypirc|/\\.config/gh/|\\.env$|\\.env\\.)'; then echo \"BLOCKED: Editing shell config or credentials ($FILE) is not allowed.\" >&2; exit 2; fi"
}
]
}
],
"Notification": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "if command -v osascript >/dev/null 2>&1; then osascript -e 'display notification \"Claude Code needs your attention\" with title \"Claude Code\"' >/dev/null 2>&1; elif command -v notify-send >/dev/null 2>&1; then notify-send 'Claude Code' 'Claude Code needs your attention' >/dev/null 2>&1; fi"
}
]
}
]
}
}