From b81651b133c97f2b46cc35cea8aba9b0ca9c600c Mon Sep 17 00:00:00 2001 From: Jack Chan Date: Tue, 30 Jun 2026 03:14:09 +0000 Subject: [PATCH] fix: keep ~/.claude/hooks scripts executable after skeleton copy The container entrypoint seeds the home from /etc/skel.agent with cp -rT --no-preserve=mode to keep home files agent-writable, but that strips the +x bit baked into the skeleton hook scripts. Claude Code execs ~/.claude/hooks/*.sh directly (stop-test-runner, test-runner, gitleaks-precommit referenced from managed-settings.json), so they failed with 'Permission denied' on the Stop and PreToolUse events. Re-assert +x on ~/.claude/hooks/*.sh in the entrypoint: once before the fast-path exit so already-initialized homes are repaired, and once after the skeleton copy so the first session on a fresh home works too. Co-Authored-By: Claude Opus 4.8 --- image.nix | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/image.nix b/image.nix index 0420173..1567970 100644 --- a/image.nix +++ b/image.nix @@ -767,6 +767,16 @@ let HOME_DIR="/home/agent" SKEL_DIR="/etc/skel.agent" + # Claude Code execs ~/.claude/hooks/*.sh directly (from managed-settings.json + # and ~/.claude/settings.json), so they must stay executable. The skeleton + # copy below uses --no-preserve=mode to keep home files agent-writable, which + # strips the +x bit baked into the skel scripts. Re-assert it on every start + # — placed before the fast-path so homes initialized prior to this fix are + # repaired too. Cheap idempotent glob; safe to run unconditionally. + if [ -d "$HOME_DIR/.claude/hooks" ]; then + chmod +x "$HOME_DIR"/.claude/hooks/*.sh 2>/dev/null || true + fi + # Fast-path: check if already initialized with same UID:GID MARKER_FILE="$HOME_DIR/.container_initialized" if [ -f "$MARKER_FILE" ]; then @@ -780,6 +790,9 @@ let if [ ! -f "$HOME_DIR/.bashrc" ] && [ -d "$SKEL_DIR" ]; then echo "Initializing home directory from skeleton..." cp -rT --no-preserve=mode "$SKEL_DIR" "$HOME_DIR" + # Restore +x on hook scripts stripped by --no-preserve=mode (see above), so + # the very first session after init can run them. + chmod +x "$HOME_DIR"/.claude/hooks/*.sh 2>/dev/null || true fi # Adjust UID/GID if different from container defaults