check-setup.sh: false "permissions 644 (should be 600)" warning on Windows Git Bash (includes fix)

Author: ppradeep123-opsCreated Sep 2, 2026Updated Sep 2, 2026

Summary

On Windows Git Bash / MSYS2 / Cygwin, the /watch SessionStart hook (hooks/scripts/check-setup.sh) prints a permissions warning for ~/.config/watch/.env on every session start, and the chmod 600 it suggests can never clear it.

This is the same problem previously raised in #170 (withdrawn by its author as a courtesy — "filed in error on my side, don't want to take up maintainer time" — not fixed) and is related to #47. The fix is still not upstream in v0.2.0, so I'm re-filing with a concrete, verified patch.

Environment

  • watch 0.2.0 (installed copy byte-identical to upstream v0.2.0)
  • Windows 11, Git Bash / MSYS2 (uname -s -> MINGW64_NT-10.0-26200)
  • /c mounted noacl (the Git for Windows default):
    C: on /c type ntfs (binary,noacl,posix=0,user,noumount,auto)

What happens

Every session start prints:

/watch: WARNING — /c/Users/<user>/.config/watch/.env has permissions 644 (should be 600).
  Fix: chmod 600 /c/Users/<user>/.config/watch/.env

Running the suggested command changes nothing, so the warning reappears on every session.

Root cause

hooks/scripts/check-setup.sh reads the mode with stat -c '%a'. Under a noacl mount, MSYS2 does not read the NTFS ACL — it synthesises a POSIX mode, and chmod is a no-op:

stat -c '%a'  before chmod 600 : 644
stat -c '%a'  after  chmod 600 : 644

Meanwhile the real NTFS ACL on the file is already owner-only (e.g. LAPTOP-XXXX\<user>:(F) after stripping inheritance with icacls). So the file was never loose, the warning is false, and the remedy it recommends does nothing. A check that reads a synthesised value cannot support a claim about permissions — on these mounts it is guaranteed to be either a false warning or false reassurance.

Proposed fix

Skip the POSIX-mode check on MSYS/Cygwin, where the value is fabricated; keep it unchanged on Linux/macOS. Real access control on Windows is governed by NTFS ACLs (via icacls), not POSIX mode.

diff
 # Warn if the secrets file has loose permissions.
-if [[ -f "$CONFIG_FILE" ]]; then
-  perms=$(stat -c '%a' "$CONFIG_FILE" 2>/dev/null || stat -f '%Lp' "$CONFIG_FILE" 2>/dev/null || echo "")
-  if [[ -n "$perms" && "$perms" != "600" && "$perms" != "400" ]]; then
-    echo "/watch: WARNING — $CONFIG_FILE has permissions $perms (should be 600)."
-    echo "  Fix: chmod 600 $CONFIG_FILE"
-  fi
-fi
+# Skip on Windows Git Bash / Cygwin: those mounts are typically `noacl`, so
+# `stat` always reports 644 for a writable file regardless of the real Windows
+# ACL, producing a permanent false warning. Access there is governed by NTFS
+# ACLs (set via icacls), not POSIX mode.
+case "$(uname -s 2>/dev/null || echo)" in
+  MINGW*|MSYS*|CYGWIN*) ;;
+  *)
+    if [[ -f "$CONFIG_FILE" ]]; then
+      perms=$(stat -c '%a' "$CONFIG_FILE" 2>/dev/null || stat -f '%Lp' "$CONFIG_FILE" 2>/dev/null || echo "")
+      if [[ -n "$perms" && "$perms" != "600" && "$perms" != "400" ]]; then
+        echo "/watch: WARNING — $CONFIG_FILE has permissions $perms (should be 600)."
+        echo "  Fix: chmod 600 $CONFIG_FILE"
+      fi
+    fi
+    ;;
+esac

Verified locally: with this patch the hook runs clean (exit 0, no warning) on Git Bash, and the check is unchanged on Linux/macOS. Happy to open a PR if that's preferred.

Source: bradautomates/claude-video