#!/usr/bin/env bash # Build the image and add a "Claude RE Workstation" launcher to the desktop's # application menu. The launcher runs ./run.sh from this checkout, so keep # the checkout where it is (re-run this script after moving it). # # Usage: ./install.sh [--uninstall] # --uninstall remove the launcher and its icons (the image is kept; # remove it with: docker rmi claude-re-setup:latest) # # RUNTIME=podman is passed on to the launcher. set -euo pipefail IMAGE="${IMAGE:-claude-re-setup:latest}" RUNTIME="${RUNTIME:-docker}" app_id="claude-re-setup" script_dir="$(dirname "$(readlink -f "$0")")" data_home="${XDG_DATA_HOME:-$HOME/.local/share}" desktop_file="$data_home/applications/$app_id.desktop" icon_root="$data_home/icons/hicolor" icon_sizes=(16 32 48 128 256) die() { echo "error: $*" >&2; exit 1; } info() { echo "==> $*"; } refresh_caches() { command -v update-desktop-database >/dev/null \ && update-desktop-database -q "$data_home/applications" || true command -v gtk-update-icon-cache >/dev/null && [[ -f "$icon_root/index.theme" ]] \ && gtk-update-icon-cache -q -t "$icon_root" || true } case "${1:-}" in --uninstall) rm -f "$desktop_file" for size in "${icon_sizes[@]}"; do rm -f "$icon_root/${size}x${size}/apps/$app_id.png" done refresh_caches info "Removed the launcher. The image is still there: $RUNTIME rmi $IMAGE" exit 0 ;; -h|--help) sed -n '2,10p' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;; "") ;; *) die "unknown argument: $1" ;; esac # The desktop entry quotes the path; these characters would need escaping # there, so such a checkout location is refused instead. [[ "$script_dir" != *[\"\`\$\\%]* ]] \ || die "the checkout path contains a character a .desktop file can't hold: $script_dir" # --- Image ------------------------------------------------------------------- info "Building $IMAGE (cached layers are reused)" RUNTIME="$RUNTIME" IMAGE="$IMAGE" "$script_dir/run.sh" --build-only # --- Icons ------------------------------------------------------------------- # Claude Desktop's own icons, taken from the image, under this launcher's # name so they don't clash with a natively installed Claude Desktop. info "Installing icons" cid="$("$RUNTIME" create "$IMAGE")" trap '"$RUNTIME" rm "$cid" >/dev/null 2>&1 || true' EXIT for size in "${icon_sizes[@]}"; do dir="$icon_root/${size}x${size}/apps" mkdir -p "$dir" "$RUNTIME" cp "$cid:/usr/share/icons/hicolor/${size}x${size}/apps/claude-desktop.png" \ "$dir/$app_id.png" done # --- Desktop entry ----------------------------------------------------------- exec_line="\"$script_dir/run.sh\"" [[ "$RUNTIME" != docker ]] && exec_line="env RUNTIME=$RUNTIME $exec_line" info "Writing $desktop_file" mkdir -p "$(dirname "$desktop_file")" cat > "$desktop_file" </dev/null; then desktop-file-validate "$desktop_file" fi refresh_caches info "Done. Start \"Claude RE Workstation\" from the application menu."