install.sh builds the image (run.sh --build-only) and adds a "Claude RE Workstation" desktop entry that starts this checkout's run.sh, with Claude Desktop's icons taken from the image under their own name. --uninstall removes the launcher and icons again. run.sh gains --build-only, which needs no display, and shows errors in a zenity dialog when it has no terminal, as when started from the menu. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
100 lines
3.5 KiB
Bash
Executable File
100 lines
3.5 KiB
Bash
Executable File
#!/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" <<EOF
|
|
[Desktop Entry]
|
|
Type=Application
|
|
Name=Claude RE Workstation
|
|
GenericName=Reverse-engineering workstation
|
|
Comment=Claude Desktop with Ghidra and REA in Docker
|
|
Keywords=Claude;Ghidra;REA;Reverse;Engineering;Firmware;
|
|
Exec=$exec_line
|
|
Path=$script_dir
|
|
Icon=$app_id
|
|
Terminal=false
|
|
Categories=Development;
|
|
StartupNotify=true
|
|
# Claude Desktop's windows in the container carry this class, so docks
|
|
# group them under this launcher.
|
|
StartupWMClass=com.anthropic.Claude
|
|
EOF
|
|
|
|
if command -v desktop-file-validate >/dev/null; then
|
|
desktop-file-validate "$desktop_file"
|
|
fi
|
|
refresh_caches
|
|
|
|
info "Done. Start \"Claude RE Workstation\" from the application menu."
|