#!/usr/bin/env bash set -euo pipefail # Build and bundle Clawdis into a minimal .app we can open. # Outputs to dist/Clawdis.app ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)" APP_ROOT="$ROOT_DIR/dist/Clawdis.app" BUILD_PATH="$ROOT_DIR/apps/macos/.build" PRODUCT="Clawdis" BUNDLE_ID="${BUNDLE_ID:-com.steipete.clawdis.debug}" PKG_VERSION="$(cd "$ROOT_DIR" && node -p "require('./package.json').version" 2>/dev/null || echo "0.0.0")" BUILD_TS=$(date -u +"%Y-%m-%dT%H:%M:%SZ") GIT_COMMIT=$(cd "$ROOT_DIR" && git rev-parse --short HEAD 2>/dev/null || echo "unknown") GIT_BUILD_NUMBER=$(cd "$ROOT_DIR" && git rev-list --count HEAD 2>/dev/null || echo "0") APP_VERSION="${APP_VERSION:-$PKG_VERSION}" APP_BUILD="${APP_BUILD:-$GIT_BUILD_NUMBER}" BUILD_CONFIG="${BUILD_CONFIG:-debug}" SPARKLE_PUBLIC_ED_KEY="${SPARKLE_PUBLIC_ED_KEY:-AGCY8w5vHirVfGGDGc8Szc5iuOqupZSh9pMj/Qs67XI=}" SPARKLE_FEED_URL="${SPARKLE_FEED_URL:-https://raw.githubusercontent.com/steipete/clawdis/main/appcast.xml}" AUTO_CHECKS=true if [[ "$BUNDLE_ID" == *.debug ]]; then SPARKLE_FEED_URL="" AUTO_CHECKS=false fi echo "๐Ÿ“ฆ Ensuring deps (pnpm install)" (cd "$ROOT_DIR" && pnpm install --no-frozen-lockfile --config.node-linker=hoisted) if [[ "${SKIP_TSC:-0}" != "1" ]]; then echo "๐Ÿ“ฆ Building JS (pnpm exec tsc)" (cd "$ROOT_DIR" && pnpm exec tsc -p tsconfig.json) else echo "๐Ÿ“ฆ Skipping TS build (SKIP_TSC=1)" fi cd "$ROOT_DIR/apps/macos" echo "๐Ÿ”จ Building $PRODUCT ($BUILD_CONFIG)" swift build -c "$BUILD_CONFIG" --product "$PRODUCT" --build-path "$BUILD_PATH" BIN="$BUILD_PATH/$BUILD_CONFIG/$PRODUCT" echo "pkg: binary $BIN" >&2 echo "๐Ÿงน Cleaning old app bundle" rm -rf "$APP_ROOT" mkdir -p "$APP_ROOT/Contents/MacOS" mkdir -p "$APP_ROOT/Contents/Resources" mkdir -p "$APP_ROOT/Contents/Resources/Relay" mkdir -p "$APP_ROOT/Contents/Frameworks" echo "๐Ÿ“„ Writing Info.plist" cat > "$APP_ROOT/Contents/Info.plist" < CFBundleIdentifier ${BUNDLE_ID} CFBundleShortVersionString ${APP_VERSION} CFBundleVersion ${APP_BUILD} CFBundleName Clawdis CFBundleExecutable Clawdis CFBundleIconFile Clawdis CFBundlePackageType APPL LSMinimumSystemVersion 15.0 LSUIElement CFBundleURLTypes CFBundleURLName com.steipete.clawdis.deeplink CFBundleURLSchemes clawdis ClawdisBuildTimestamp ${BUILD_TS} ClawdisGitCommit ${GIT_COMMIT} SUFeedURL ${SPARKLE_FEED_URL} SUPublicEDKey ${SPARKLE_PUBLIC_ED_KEY} SUEnableAutomaticChecks <${AUTO_CHECKS}/> NSUserNotificationUsageDescription Clawdis needs notification permission to show alerts for agent actions. NSScreenCaptureDescription Clawdis captures the screen when the agent needs screenshots for context. NSCameraUsageDescription Clawdis can capture photos or short video clips when requested by the agent. NSMicrophoneUsageDescription Clawdis needs the mic for Voice Wake tests and agent audio capture. NSSpeechRecognitionUsageDescription Clawdis uses speech recognition to detect your Voice Wake trigger phrase. NSAppleEventsUsageDescription Clawdis needs Automation (AppleScript) permission to drive Terminal and other apps for agent actions. NSAppTransportSecurity NSExceptionDomains 100.100.100.100 NSExceptionAllowsInsecureHTTPLoads NSIncludesSubdomains PLIST echo "๐Ÿšš Copying binary" cp "$BIN" "$APP_ROOT/Contents/MacOS/Clawdis" chmod +x "$APP_ROOT/Contents/MacOS/Clawdis" # SwiftPM outputs ad-hoc signed binaries; strip the signature before install_name_tool to avoid warnings. /usr/bin/codesign --remove-signature "$APP_ROOT/Contents/MacOS/Clawdis" 2>/dev/null || true SPARKLE_FRAMEWORK="$BUILD_PATH/$BUILD_CONFIG/Sparkle.framework" if [ -d "$SPARKLE_FRAMEWORK" ]; then echo "โœจ Embedding Sparkle.framework" cp -R "$SPARKLE_FRAMEWORK" "$APP_ROOT/Contents/Frameworks/" chmod -R a+rX "$APP_ROOT/Contents/Frameworks/Sparkle.framework" install_name_tool -add_rpath "@executable_path/../Frameworks" "$APP_ROOT/Contents/MacOS/Clawdis" fi echo "๐Ÿ–ผ Copying app icon" cp "$ROOT_DIR/apps/macos/Sources/Clawdis/Resources/Clawdis.icns" "$APP_ROOT/Contents/Resources/Clawdis.icns" RELAY_DIR="$APP_ROOT/Contents/Resources/Relay" if [[ "${SKIP_GATEWAY_PACKAGE:-0}" != "1" ]]; then if ! command -v bun >/dev/null 2>&1; then echo "ERROR: bun missing. Install bun to package the embedded gateway." >&2 exit 1 fi echo "๐Ÿงฐ Building bundled relay (bun --compile)" mkdir -p "$RELAY_DIR" RELAY_OUT="$RELAY_DIR/clawdis" bun build "$ROOT_DIR/dist/macos/relay.js" \ --compile \ --bytecode \ --outfile "$RELAY_OUT" \ -e electron \ --define "__CLAWDIS_VERSION__=\\\"$PKG_VERSION\\\"" chmod +x "$RELAY_OUT" echo "๐ŸŽจ Copying gateway A2UI host assets" rm -rf "$RELAY_DIR/a2ui" cp -R "$ROOT_DIR/src/canvas-host/a2ui" "$RELAY_DIR/a2ui" echo "๐Ÿง  Copying bundled skills" rm -rf "$RELAY_DIR/skills" cp -R "$ROOT_DIR/skills" "$RELAY_DIR/skills" echo "๐Ÿ“„ Writing embedded runtime package.json (Pi compatibility)" cat > "$RELAY_DIR/package.json" <&2 fi else echo "๐Ÿงฐ Skipping gateway payload packaging (SKIP_GATEWAY_PACKAGE=1)" fi echo "โน Stopping any running Clawdis" killall -q Clawdis 2>/dev/null || true echo "๐Ÿ” Signing bundle (auto-selects signing identity if SIGN_IDENTITY is unset)" "$ROOT_DIR/scripts/codesign-mac-app.sh" "$APP_ROOT" echo "โœ… Bundle ready at $APP_ROOT"