From a061df4f1e98a0d51caf7060fb3e084f01098415 Mon Sep 17 00:00:00 2001 From: Peter Svensson Date: Fri, 12 Jun 2026 16:54:19 +0200 Subject: [PATCH] feat(claude): web/public media exemption in git-staging-guard The ambix web repo serves images and video straight from the repo (no CDN). Allow png/jpg/webp/avif/svg/gif/mp4/webm under public/ in the web repo (and its web.* worktrees) through the binary-extension check, with a 3MB cap instead of the global 1MB. Everything else unchanged; mp4 stays blocked outside web/public. --- .../hooks/executable_git-staging-guard.sh | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/dot_claude/hooks/executable_git-staging-guard.sh b/dot_claude/hooks/executable_git-staging-guard.sh index 3270393..60dae65 100755 --- a/dot_claude/hooks/executable_git-staging-guard.sh +++ b/dot_claude/hooks/executable_git-staging-guard.sh @@ -9,6 +9,10 @@ set -euo pipefail # 3. Staging files larger than 1MB # 4. Staging .gitignore changes on non-main/master branches # +# Exemption: web assets (png/jpg/jpeg/webp/avif/svg/gif + mp4/webm video) under +# public/ in the ambix `web` repo (incl. its `web.*` worktrees) pass the binary +# and size checks up to 3MB — the site has no CDN, media ships from the repo. +# # Override: set CLAUDE_ALLOW_BULK_ADD=1 to skip bulk-add block for one invocation. CMD=$(jq -r '.tool_input.command') @@ -42,6 +46,14 @@ fi repo_root=$(git rev-parse --show-toplevel 2>/dev/null || echo "") cur_branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "") +# web/public media exemption (images + mp4/webm): the ambix web repo serves +# media straight from the repo (no CDN). Checked per-file below. +is_web_public_media() { + [[ "$(basename "$repo_root")" == web || "$(basename "$repo_root")" == web.* ]] \ + && [[ "$1" == public/* || "$1" == */public/* ]] \ + && echo "$1" | grep -qiE '\.(png|jpe?g|webp|avif|svg|gif|mp4|webm)$' +} + # 2 + 3 + 4: per-file checks while IFS= read -r f; do [[ -z "$f" ]] && continue @@ -49,8 +61,9 @@ while IFS= read -r f; do f="${f%\"}"; f="${f#\"}" f="${f%\'}"; f="${f#\'}" - # 2. Binary extension - if echo "$f" | grep -qiE '\.(exe|bin|so|dylib|dll|a|o|dat|db|sqlite|sqlite3|class|jar|war|pyc|wasm|tar|gz|tgz|zip|7z|rar|iso|img|mp4|mov|avi|mkv|pdf)$'; then + # 2. Binary extension (web/public media exempt) + if echo "$f" | grep -qiE '\.(exe|bin|so|dylib|dll|a|o|dat|db|sqlite|sqlite3|class|jar|war|pyc|wasm|tar|gz|tgz|zip|7z|rar|iso|img|mp4|mov|avi|mkv|pdf)$' \ + && ! is_web_public_media "$f"; then echo "BLOCKED: refusing to stage binary-like file: $f" >&2 echo "If intentional, add via plain git outside this session or add ext to repo .gitattributes." >&2 exit 2 @@ -62,11 +75,15 @@ while IFS= read -r f; do full="$repo_root/$f" fi - # 3. Large file (>1MB) + # 3. Large file (>1MB; 3MB for web/public media — no CDN, media ships from repo) if [[ -f "$full" ]]; then size=$(stat -f%z "$full" 2>/dev/null || stat -c%s "$full" 2>/dev/null || echo 0) - if [[ "$size" -gt 1048576 ]]; then - echo "BLOCKED: file >1MB ($((size/1024))KB): $f" >&2 + limit=1048576 + if is_web_public_media "$f"; then + limit=3145728 + fi + if [[ "$size" -gt "$limit" ]]; then + echo "BLOCKED: file >$((limit/1048576))MB ($((size/1024))KB): $f" >&2 echo "Large files rarely belong in source PRs. Use git-lfs or add to .gitignore." >&2 exit 2 fi