diff --git a/.claude/hooks/session-start.sh b/.claude/hooks/session-start.sh index b17f6e97ba..35cddfb3b4 100755 --- a/.claude/hooks/session-start.sh +++ b/.claude/hooks/session-start.sh @@ -1,59 +1,12 @@ #!/bin/bash # Session start hook: Configure proxy auth, SSL trust, and Android SDK for Claude Code on the web +set -euo pipefail # Only run in remote (web) environments if [ "${CLAUDE_CODE_REMOTE:-}" != "true" ]; then exit 0 fi -# --- Fix no_proxy: remove *.google.com and *.googleapis.com so traffic routes through proxy --- -# The default no_proxy in Claude Code web includes *.google.com and *.googleapis.com, -# which causes JVM/curl to bypass the proxy for Google Maven (dl.google.com). -# These domains MUST go through the proxy for authenticated egress to work. -fix_no_proxy() { - local var="$1" - local val="${!var:-}" - if [ -n "$val" ]; then - # Remove *.google.com, *.googleapis.com entries from the comma-separated list - local fixed - fixed=$(echo "$val" | tr ',' '\n' | grep -v -E '^\*\.google\.com$|^\*\.googleapis\.com$' | tr '\n' ',' | sed 's/,$//') - export "$var=$fixed" - fi -} - -fix_no_proxy no_proxy -fix_no_proxy NO_PROXY - -# --- Fix JAVA_TOOL_OPTIONS: remove nonProxyHosts that bypass Google domains --- -# JAVA_TOOL_OPTIONS may contain -Dhttp.nonProxyHosts=...|*.google.com|*.googleapis.com -# which prevents the JVM from routing Google Maven traffic through the proxy. -if [ -n "${JAVA_TOOL_OPTIONS:-}" ]; then - # Remove the nonProxyHosts entries for google.com and googleapis.com from the JVM options - # Strategy: rewrite the -Dhttp.nonProxyHosts value to exclude google patterns - JAVA_TOOL_OPTIONS=$(echo "$JAVA_TOOL_OPTIONS" | sed -E ' - s/-Dhttp\.nonProxyHosts=[^ ]*/\n&\n/g - ' | while IFS= read -r line; do - if [[ "$line" == -Dhttp.nonProxyHosts=* ]]; then - # Extract the value, remove google patterns, reconstruct - val="${line#-Dhttp.nonProxyHosts=}" - fixed=$(echo "$val" | tr '|' '\n' | grep -v -E '^\*\.google\.com$|^\*\.googleapis\.com$' | tr '\n' '|' | sed 's/|$//') - echo "-Dhttp.nonProxyHosts=$fixed" - else - echo "$line" - fi - done | tr '\n' ' ' | sed 's/ */ /g; s/^ //; s/ $//') - export JAVA_TOOL_OPTIONS -fi - -# Export fixed env vars for the session -if [ -n "${CLAUDE_ENV_FILE:-}" ]; then - echo "export no_proxy='${no_proxy:-}'" >> "$CLAUDE_ENV_FILE" - echo "export NO_PROXY='${NO_PROXY:-}'" >> "$CLAUDE_ENV_FILE" - echo "export JAVA_TOOL_OPTIONS='$JAVA_TOOL_OPTIONS'" >> "$CLAUDE_ENV_FILE" -fi - -echo "Fixed proxy bypass settings (no_proxy, JAVA_TOOL_OPTIONS)" >&2 - # --- Proxy credentials: configure Maven/Gradle if authenticated proxy is set --- proxy="${https_proxy:-${HTTPS_PROXY:-}}" if [ -n "$proxy" ] && echo "$proxy" | grep -q '@'; then @@ -146,11 +99,68 @@ if [ -n "$ANTHROPIC_CA_PEM" ]; then rm -f "$TMPCA" fi -# --- Project setup: local.properties and env vars (before SDK download so these always run) --- ANDROID_SDK_DIR="/root/android-sdk" -REPO_ROOT="$(git -C "$(dirname "$0")" rev-parse --show-toplevel 2>/dev/null || echo "${CLAUDE_PROJECT_DIR:-/home/user/amethyst}")" +SDK_REPO_BASE="https://dl.google.com/android/repository" + +# Install Android SDK packages by downloading directly with curl +# (sdkmanager cannot reach the SDK repository through the proxy) +install_sdk_package() { + local zip_url="$1" + local dest_dir="$2" + local inner_dir="$3" # top-level dir inside the zip + + if [ -d "$dest_dir" ]; then + return 0 + fi + + echo "Downloading $zip_url..." + local TMP_ZIP + TMP_ZIP=$(mktemp /tmp/sdk-pkg.XXXXXX.zip) + curl -fsSL "$zip_url" -o "$TMP_ZIP" + + local TMP_DIR + TMP_DIR=$(mktemp -d) + unzip -q "$TMP_ZIP" -d "$TMP_DIR" + rm -f "$TMP_ZIP" + + mkdir -p "$(dirname "$dest_dir")" + mv "$TMP_DIR/$inner_dir" "$dest_dir" + rm -rf "$TMP_DIR" + echo "Installed to $dest_dir" +} + +# Install Android platform 36 +install_sdk_package \ + "$SDK_REPO_BASE/platform-36_r02.zip" \ + "$ANDROID_SDK_DIR/platforms/android-36" \ + "android-36" + +# Install build-tools 36.0.0 (zip uses "android-16" as inner dir name) +install_sdk_package \ + "$SDK_REPO_BASE/build-tools_r36_linux.zip" \ + "$ANDROID_SDK_DIR/build-tools/36.0.0" \ + "android-16" + +# Install platform-tools +install_sdk_package \ + "$SDK_REPO_BASE/platform-tools_r37.0.0-linux.zip" \ + "$ANDROID_SDK_DIR/platform-tools" \ + "platform-tools" + +# Accept SDK licenses (create license files manually) +echo "Writing SDK license files..." +mkdir -p "$ANDROID_SDK_DIR/licenses" +# android-sdk-license +echo -e "\n24333f8a63b6825ea9c5514f83c2829b004d1fee" > "$ANDROID_SDK_DIR/licenses/android-sdk-license" +echo -e "\n84831b9409646a918e30573bab4c9c91346d8abd" >> "$ANDROID_SDK_DIR/licenses/android-sdk-license" +# android-sdk-preview-license +echo -e "\n84831b9409646a918e30573bab4c9c91346d8abd" > "$ANDROID_SDK_DIR/licenses/android-sdk-preview-license" +echo -e "\n504667f4c0de7af1a06de9f4b1727b84351f2910" >> "$ANDROID_SDK_DIR/licenses/android-sdk-preview-license" +# intel-android-extra-license +echo -e "\nd975f751698a77b662f1254ddbeed3901e976f5a" > "$ANDROID_SDK_DIR/licenses/intel-android-extra-license" # Create local.properties if missing +REPO_ROOT="$(git -C "$(dirname "$0")" rev-parse --show-toplevel 2>/dev/null || echo "${CLAUDE_PROJECT_DIR:-/home/user/Amber}")" LOCAL_PROPS="$REPO_ROOT/local.properties" if [ ! -f "$LOCAL_PROPS" ]; then echo "sdk.dir=$ANDROID_SDK_DIR" > "$LOCAL_PROPS" @@ -164,123 +174,7 @@ if [ -n "${CLAUDE_ENV_FILE:-}" ]; then echo "export PATH=\$PATH:$ANDROID_SDK_DIR/platform-tools" >> "$CLAUDE_ENV_FILE" fi -# --- Install standalone ktlint (fallback for spotlessApply when Gradle can't resolve AGP) --- -# The egress proxy may block dl.google.com (Google Maven), preventing Gradle from resolving -# the Android Gradle Plugin. Since spotlessApply depends on Gradle's plugin resolution, -# we install ktlint standalone as a reliable alternative. -KTLINT_VERSION="1.5.0" -KTLINT_BIN="/usr/local/bin/ktlint" -if [ ! -x "$KTLINT_BIN" ]; then - echo "Installing ktlint $KTLINT_VERSION..." >&2 - if curl -fsSL "https://github.com/pinterest/ktlint/releases/download/${KTLINT_VERSION}/ktlint" -o "$KTLINT_BIN" 2>/dev/null; then - chmod +x "$KTLINT_BIN" - echo "Installed ktlint $KTLINT_VERSION to $KTLINT_BIN" >&2 - else - echo "WARNING: Failed to install ktlint (GitHub may be unreachable)" >&2 - fi -fi +cd "$CLAUDE_PROJECT_DIR" +./gradlew --version > /dev/null 2>&1 -# Create a spotless-apply wrapper that mimics the Gradle spotless configuration -cat > /usr/local/bin/spotless-apply << 'SPOTLESS_SCRIPT' -#!/bin/bash -# Standalone spotless-apply: runs ktlint with the same settings as the Gradle spotless plugin. -# Use this when ./gradlew spotlessApply fails due to proxy/network issues. -set -euo pipefail - -REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)" -cd "$REPO_ROOT" - -if ! command -v ktlint &>/dev/null; then - echo "ERROR: ktlint not found. Install it first." >&2 - exit 1 -fi - -echo "Running ktlint format on Kotlin sources..." -# Find all Kotlin source files matching the spotless target pattern (src/**/*.kt) -# Exclude build directories -ktlint --format "**/*.kt" 2>&1 | grep -v "^$" || true - -echo "Done. Files formatted with ktlint." -SPOTLESS_SCRIPT -chmod +x /usr/local/bin/spotless-apply - -# --- Android SDK download (non-fatal: warns if dl.google.com is blocked) --- -SDK_REPO_BASE="https://dl.google.com/android/repository" - -install_sdk_package() { - local zip_url="$1" - local dest_dir="$2" - local inner_dir="$3" # top-level dir inside the zip - - if [ -d "$dest_dir" ]; then - return 0 - fi - - echo "Downloading $zip_url..." >&2 - local TMP_ZIP - TMP_ZIP=$(mktemp /tmp/sdk-pkg.XXXXXX.zip) - if ! curl -fsSL "$zip_url" -o "$TMP_ZIP" 2>/dev/null; then - rm -f "$TMP_ZIP" - echo "WARNING: Failed to download $zip_url (dl.google.com may be blocked by proxy)" >&2 - echo " -> Add dl.google.com to the egress proxy allowlist to fix this" >&2 - return 1 - fi - - local TMP_DIR - TMP_DIR=$(mktemp -d) - unzip -q "$TMP_ZIP" -d "$TMP_DIR" - rm -f "$TMP_ZIP" - - mkdir -p "$(dirname "$dest_dir")" - mv "$TMP_DIR/$inner_dir" "$dest_dir" - rm -rf "$TMP_DIR" - echo "Installed to $dest_dir" >&2 -} - -sdk_ok=true - -# Install Android platform 36 -if ! install_sdk_package \ - "$SDK_REPO_BASE/platform-36_r02.zip" \ - "$ANDROID_SDK_DIR/platforms/android-36" \ - "android-36"; then - sdk_ok=false -fi - -# Install build-tools 36.0.0 (zip uses "android-16" as inner dir name) -if ! install_sdk_package \ - "$SDK_REPO_BASE/build-tools_r36_linux.zip" \ - "$ANDROID_SDK_DIR/build-tools/36.0.0" \ - "android-16"; then - sdk_ok=false -fi - -# Install platform-tools -if ! install_sdk_package \ - "$SDK_REPO_BASE/platform-tools_r37.0.0-linux.zip" \ - "$ANDROID_SDK_DIR/platform-tools" \ - "platform-tools"; then - sdk_ok=false -fi - -if [ "$sdk_ok" = true ]; then - # Accept SDK licenses (create license files manually) - echo "Writing SDK license files..." >&2 - mkdir -p "$ANDROID_SDK_DIR/licenses" - echo -e "\n24333f8a63b6825ea9c5514f83c2829b004d1fee" > "$ANDROID_SDK_DIR/licenses/android-sdk-license" - echo -e "\n84831b9409646a918e30573bab4c9c91346d8abd" >> "$ANDROID_SDK_DIR/licenses/android-sdk-license" - echo -e "\n84831b9409646a918e30573bab4c9c91346d8abd" > "$ANDROID_SDK_DIR/licenses/android-sdk-preview-license" - echo -e "\n504667f4c0de7af1a06de9f4b1727b84351f2910" >> "$ANDROID_SDK_DIR/licenses/android-sdk-preview-license" - echo -e "\nd975f751698a77b662f1254ddbeed3901e976f5a" > "$ANDROID_SDK_DIR/licenses/intel-android-extra-license" - echo "Android SDK setup complete." >&2 -else - echo "WARNING: Android SDK download failed. dl.google.com is likely blocked by the egress proxy." >&2 - echo " -> Gradle builds requiring AGP will fail until dl.google.com is added to the proxy allowlist." >&2 - echo " -> Use 'spotless-apply' (standalone ktlint) instead of './gradlew spotlessApply'." >&2 -fi - -# Warm up Gradle wrapper (non-fatal) -cd "$REPO_ROOT" -./gradlew --version > /dev/null 2>&1 || true - -echo "Session start hook complete." >&2 +echo "Android SDK setup complete." \ No newline at end of file