Skip to content

Commit c9efaca

Browse files
authored
fix(hooks): use POSIX [[:space:]] in guard-git.sh grep patterns (#1170)
PR #1146 fixed BSD sed portability by replacing \s with [[:space:]] in sed patterns, but the grep -qE patterns in the same file still used \s. \s is a vendor extension (GNU/BSD grep accept it in ERE mode) but is not POSIX ERE, so it can fail on stricter graps such as busybox in Alpine containers. Replace all occurrences with [[:space:]] for uniform POSIX compliance and consistency with the existing sed patterns. Closes #1157
1 parent 05630b2 commit c9efaca

1 file changed

Lines changed: 12 additions & 12 deletions

File tree

.claude/hooks/guard-git.sh

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,12 @@ if [ -z "$COMMAND" ]; then
2222
fi
2323

2424
# Act on git and gh commands (may appear after cd "..." &&)
25-
if ! echo "$COMMAND" | grep -qE '(^|\s|&&\s*)(git|gh)\s+'; then
25+
if ! echo "$COMMAND" | grep -qE '(^|[[:space:]]|&&[[:space:]]*)(git|gh)[[:space:]]+'; then
2626
exit 0
2727
fi
2828

2929
# Normalize: strip `git -C "<path>"` / `git -C <path>` so downstream subcommand
30-
# patterns (git\s+push, git\s+commit, …) match regardless of whether `-C` is
30+
# patterns (git[[:space:]]+push, git[[:space:]]+commit, …) match regardless of whether `-C` is
3131
# present. detect_work_dir still inspects the raw $COMMAND to find the target.
3232
# The unquoted pattern requires a non-quote first char so it does not mis-match
3333
# the opening `"` of a quoted path (which would leave a trailing `path"` in
@@ -53,34 +53,34 @@ deny() {
5353
# --- Block dangerous commands ---
5454

5555
# git add . / git add -A / git add --all (broad staging)
56-
if echo "$NCOMMAND" | grep -qE '(^|\s|&&\s*)git\s+add\s+(\.\s*$|-A|--all)'; then
56+
if echo "$NCOMMAND" | grep -qE '(^|[[:space:]]|&&[[:space:]]*)git[[:space:]]+add[[:space:]]+(\.[[:space:]]*$|-A|--all)'; then
5757
deny "BLOCKED: 'git add .' / 'git add -A' stages ALL changes including other sessions' work. Stage specific files instead: git add <file1> <file2>"
5858
fi
5959

6060
# git reset (unstaging / hard reset)
61-
if echo "$NCOMMAND" | grep -qE '(^|\s|&&\s*)git\s+reset'; then
61+
if echo "$NCOMMAND" | grep -qE '(^|[[:space:]]|&&[[:space:]]*)git[[:space:]]+reset'; then
6262
deny "BLOCKED: 'git reset' can unstage or destroy other sessions' work. To unstage your own files, use: git restore --staged <file>"
6363
fi
6464

6565
# git checkout -- <file> (reverting files)
66-
if echo "$NCOMMAND" | grep -qE '(^|\s|&&\s*)git\s+checkout\s+--'; then
66+
if echo "$NCOMMAND" | grep -qE '(^|[[:space:]]|&&[[:space:]]*)git[[:space:]]+checkout[[:space:]]+--'; then
6767
deny "BLOCKED: 'git checkout -- <file>' reverts working tree changes and may destroy other sessions' edits. If you need to discard your own changes, be explicit about which files."
6868
fi
6969

7070
# git restore (reverting) — EXCEPT git restore --staged (safe unstaging)
71-
if echo "$NCOMMAND" | grep -qE '(^|\s|&&\s*)git\s+restore'; then
72-
if ! echo "$NCOMMAND" | grep -qE '(^|\s|&&\s*)git\s+restore\s+--staged'; then
71+
if echo "$NCOMMAND" | grep -qE '(^|[[:space:]]|&&[[:space:]]*)git[[:space:]]+restore'; then
72+
if ! echo "$NCOMMAND" | grep -qE '(^|[[:space:]]|&&[[:space:]]*)git[[:space:]]+restore[[:space:]]+--staged'; then
7373
deny "BLOCKED: 'git restore <file>' reverts working tree changes and may destroy other sessions' edits. To unstage files safely, use: git restore --staged <file>"
7474
fi
7575
fi
7676

7777
# git clean (delete untracked files)
78-
if echo "$NCOMMAND" | grep -qE '(^|\s|&&\s*)git\s+clean'; then
78+
if echo "$NCOMMAND" | grep -qE '(^|[[:space:]]|&&[[:space:]]*)git[[:space:]]+clean'; then
7979
deny "BLOCKED: 'git clean' deletes untracked files that may belong to other sessions."
8080
fi
8181

8282
# git stash (hides all changes)
83-
if echo "$NCOMMAND" | grep -qE '(^|\s|&&\s*)git\s+stash'; then
83+
if echo "$NCOMMAND" | grep -qE '(^|[[:space:]]|&&[[:space:]]*)git[[:space:]]+stash'; then
8484
deny "BLOCKED: 'git stash' hides all working tree changes including other sessions' work. In worktree mode, commit your changes directly instead."
8585
fi
8686

@@ -158,21 +158,21 @@ validate_branch_name() {
158158

159159
# --- Branch name validation on push ---
160160

161-
if echo "$NCOMMAND" | grep -qE '(^|\s|&&\s*)git\s+push'; then
161+
if echo "$NCOMMAND" | grep -qE '(^|[[:space:]]|&&[[:space:]]*)git[[:space:]]+push'; then
162162
validate_branch_name push
163163
fi
164164

165165
# --- Branch name validation on gh pr create ---
166166

167-
if echo "$NCOMMAND" | grep -qE '(^|\s|&&\s*)gh\s+pr\s+create'; then
167+
if echo "$NCOMMAND" | grep -qE '(^|[[:space:]]|&&[[:space:]]*)gh[[:space:]]+pr[[:space:]]+create'; then
168168
# `gh pr create` does not use `git -C`; detect_work_dir falls through to the
169169
# `cd` path or cwd. No subcommand hint to pass.
170170
validate_branch_name
171171
fi
172172

173173
# --- Commit validation against edit log ---
174174

175-
if echo "$NCOMMAND" | grep -qE '(^|\s|&&\s*)git\s+commit'; then
175+
if echo "$NCOMMAND" | grep -qE '(^|[[:space:]]|&&[[:space:]]*)git[[:space:]]+commit'; then
176176
# Resolve the target worktree so the edit log and staged-file listing come
177177
# from the same repo the commit targets (e.g. `git -C <pr-worktree> commit`).
178178
WORK_DIR=$(detect_work_dir commit)

0 commit comments

Comments
 (0)