diff --git a/lib/design-tool-gate.sh b/lib/design-tool-gate.sh index d14a560..b72f20b 100755 --- a/lib/design-tool-gate.sh +++ b/lib/design-tool-gate.sh @@ -51,6 +51,33 @@ PROFILE_FILE="$PROFILES_DIR/$PROFILE.profile" [ -x "$PROFILE_SH" ] || { echo "design-gate: profile.sh not executable at $PROFILE_SH" >&2; exit 2; } [ -f "$PROFILE_FILE" ] || { echo "design-gate: profile '$PROFILE' not found" >&2; exit 2; } +# Ensure the claude CLI + its node runtime are reachable even when a skill/hook +# shells this script out with a sanitized PATH. The interactive alias +# claude->dtach_claude never reaches a non-interactive subshell; the real binary +# AND its node bin dir are what matter (claude's shebang needs node, same dir). +# If `command -v claude` already resolves, do nothing; else probe known install +# dirs and prepend. nvm keeps old node versions after an upgrade, so pick the +# newest that actually ships claude (sort -V), not the first glob match. +ensure_claude_on_path() { + command -v claude >/dev/null 2>&1 && return + local cand + for cand in \ + "$HOME/.claude/local/claude" \ + "$HOME/.local/bin/claude" \ + /usr/local/bin/claude; do + [ -x "$cand" ] && { PATH="$(dirname "$cand"):$PATH"; return; } + done + local m newest matches=() + for m in "$HOME"/.nvm/versions/node/*/bin/claude; do + [ -x "$m" ] && matches+=("$m") + done + if [ "${#matches[@]}" -gt 0 ]; then + newest="$(printf '%s\n' "${matches[@]}" | sort -V | tail -1)" + PATH="$(dirname "$newest"):$PATH" + fi +} +ensure_claude_on_path + # Gate scope: the "# GATE-BLOCK:" allowlist (one or more lines, concatenated). # Empty => fall back to "every gate-relevant entry is in scope" (coarse). core_set="$(grep '^# GATE-BLOCK:' "$PROFILE_FILE" 2>/dev/null \