From 49978489fc78c3914a78bc9f2c184c419b4c5752 Mon Sep 17 00:00:00 2001 From: carlos-alm Date: Sun, 17 May 2026 18:52:05 -0600 Subject: [PATCH] fix(hooks): use portable sed for guard-git -C work_dir detection The `;t;` chained sed expression in `detect_work_dir` is a GNU-ism: BSD sed (macOS default) parses it as `t` branching to a label named `;s/...` and errors out, leaving `work_dir` empty. The hook then falls back to the ambient cwd's branch and denies legitimate `git -C /other-worktree push` calls from agents running in worktrees with non-conforming branch names. Split the one-liner into two sed invocations (quoted form first, then unquoted as a fallback). Behavior is identical on GNU sed and now works on BSD sed. Closes #1135 --- .claude/hooks/guard-git.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.claude/hooks/guard-git.sh b/.claude/hooks/guard-git.sh index 46f96759..e347046e 100644 --- a/.claude/hooks/guard-git.sh +++ b/.claude/hooks/guard-git.sh @@ -117,8 +117,14 @@ detect_work_dir() { # `git -C` is the explicit git-level override and wins over any ambient cd prefix, # so check it first (e.g. `cd /tmp && git -C /worktree push` targets /worktree). # Greedy `.*-C` anchors on the LAST `-C` in the chosen segment. + # Split into two sed invocations (quoted form, then unquoted) — BSD sed (macOS) + # parses `;t;` as a `t` branch to a label named `;s/...`, not as "branch on + # substitution made; end statement", so the GNU one-liner errors on macOS. if echo "$search_str" | grep -qE 'git\s+([^&|;]*\s)?-C\s+'; then - work_dir=$(echo "$search_str" | sed -nE 's/.*-C[[:space:]]+"([^"]+)".*/\1/p;t;s/.*-C[[:space:]]+([^[:space:]]+).*/\1/p') + work_dir=$(echo "$search_str" | sed -nE 's/.*-C[[:space:]]+"([^"]+)".*/\1/p') + if [ -z "$work_dir" ]; then + work_dir=$(echo "$search_str" | sed -nE 's/.*-C[[:space:]]+([^[:space:]]+).*/\1/p') + fi fi if [ -z "$work_dir" ] && echo "$COMMAND" | grep -qE '^\s*cd\s+'; then work_dir=$(echo "$COMMAND" | sed -nE 's/^\s*cd\s+"?([^"&]+)"?\s*&&.*/\1/p')