#!/usr/bin/env bash # Claude Desktop — One-Click-Installer für NixOS # # Installiert: # - Nix-Wrapper-Paket (nix/default.nix) ins User-Profil via nix-env # - Natives Binary aus der Forgejo Package Registry nach ~/.local/share/claude-desktop/bin # - Desktop-Entry im System-Menue (KDE/GNOME/…) # # Aufruf: # curl -fsSL https://git.data-it-solution.de/data/claude-desktop/raw/branch/main/install.sh | bash # # Oder lokal: # ./install.sh # # Env-Vars (optional): # CLAUDE_DESKTOP_TOKEN — Forgejo Read-Token (sonst wird einmalig gefragt) # CLAUDE_DESKTOP_BRANCH — Git-Branch für Wrapper-Dateien (default: main) set -euo pipefail # --- Konfiguration --------------------------------------------------------- REPO_URL="https://git.data-it-solution.de/data/claude-desktop" PKG_BASE="https://git.data-it-solution.de/api/packages/data/generic/claude-desktop/latest" APP_DIR="$HOME/.local/share/claude-desktop" BIN_DIR="$APP_DIR/bin" TOKEN_FILE="$HOME/.config/claude-desktop/token" BRANCH="${CLAUDE_DESKTOP_BRANCH:-main}" # --- Farben ---------------------------------------------------------------- if [ -t 1 ]; then BOLD="$(tput bold)"; RED="$(tput setaf 1)"; GRN="$(tput setaf 2)" YEL="$(tput setaf 3)"; BLU="$(tput setaf 4)"; RST="$(tput sgr0)" else BOLD=""; RED=""; GRN=""; YEL=""; BLU=""; RST="" fi step() { echo "${BOLD}${BLU}▶${RST} $*"; } ok() { echo " ${GRN}✓${RST} $*"; } err() { echo "${RED}✗${RST} $*" >&2; exit 1; } # --- 1. Voraussetzungen pruefen ------------------------------------------- step "Voraussetzungen pruefen" for cmd in nix-build nix-env curl sha256sum; do command -v "$cmd" >/dev/null || err "$cmd nicht installiert. Abbruch." done ok "Nix, curl, sha256sum vorhanden" # jq ist auf Vanilla-NixOS nicht gesetzt — aus nixpkgs ziehen if ! command -v jq >/dev/null; then echo " ${YEL}!${RST} jq fehlt — hole aus nixpkgs" JQ_OUT=$(nix-build '' -A jq --no-out-link 2>/dev/null || true) if [ -n "$JQ_OUT" ] && [ -x "$JQ_OUT/bin/jq" ]; then export PATH="$JQ_OUT/bin:$PATH" ok "jq temporaer aus $JQ_OUT" else err "jq konnte nicht ueber nix-build bezogen werden. Abbruch." fi fi if [ ! -f /etc/NIXOS ] && [ ! -e /etc/nix/nix.conf ]; then echo " ${YEL}!${RST} Kein NixOS-System erkannt — der Installer setzt Nix voraus." fi # --- 2. Forgejo-Token besorgen -------------------------------------------- step "Forgejo-Token laden" TOKEN="${CLAUDE_DESKTOP_TOKEN:-}" if [ -z "$TOKEN" ] && [ -f "$TOKEN_FILE" ]; then TOKEN=$(cat "$TOKEN_FILE") ok "Token aus $TOKEN_FILE geladen" fi if [ -z "$TOKEN" ]; then echo " Forgejo Read-Token für Package Registry (Basic-Auth User: ${BOLD}data${RST}):" read -rs -p " Token: " TOKEN echo mkdir -p "$(dirname "$TOKEN_FILE")" printf '%s' "$TOKEN" > "$TOKEN_FILE" chmod 600 "$TOKEN_FILE" ok "Token in $TOKEN_FILE gespeichert (chmod 600)" fi # --- 3. Manifest laden ---------------------------------------------------- step "Manifest abrufen (latest/update.json)" MANIFEST=$(curl -fsSL --user "data:$TOKEN" "$PKG_BASE/update.json") \ || err "Manifest nicht erreichbar (Token falsch? Netz?)" VERSION=$(echo "$MANIFEST" | jq -r '.version') BINARY_NAME=$(echo "$MANIFEST" | jq -r '.binary_filename // empty') BINARY_SHA=$(echo "$MANIFEST" | jq -r '.binary_sha256 // empty') if [ -z "$BINARY_NAME" ] || [ -z "$BINARY_SHA" ]; then err "update.json enthaelt kein binary_filename/binary_sha256. Alter CI-Build? Erst neue Pipeline laufen lassen." fi ok "Version $VERSION, Binary $BINARY_NAME" # --- 4. Binary herunterladen ---------------------------------------------- step "Binary laden -> $BIN_DIR" mkdir -p "$BIN_DIR" TMP_BIN=$(mktemp) trap 'rm -f "$TMP_BIN"' EXIT curl -fsSL --user "data:$TOKEN" -o "$TMP_BIN" "$PKG_BASE/$BINARY_NAME" \ || err "Binary-Download fehlgeschlagen" ACTUAL_SHA=$(sha256sum "$TMP_BIN" | awk '{print $1}') if [ "$ACTUAL_SHA" != "$BINARY_SHA" ]; then err "SHA256-Mismatch: erwartet $BINARY_SHA, bekommen $ACTUAL_SHA" fi ok "SHA256 verifiziert" mv "$TMP_BIN" "$BIN_DIR/claude-desktop" chmod +x "$BIN_DIR/claude-desktop" ok "Binary installiert: $BIN_DIR/claude-desktop" # --- 5. Nix-Wrapper bauen ------------------------------------------------- step "Nix-Wrapper-Paket bauen" WORKDIR=$(mktemp -d) trap 'rm -f "$TMP_BIN"; rm -rf "$WORKDIR"' EXIT mkdir -p "$WORKDIR/nix" "$WORKDIR/src-tauri/icons" for f in \ "nix/default.nix" \ "nix/claude-desktop.desktop" \ "src-tauri/icons/icon.png"; do curl -fsSL -o "$WORKDIR/$f" "$REPO_URL/raw/branch/$BRANCH/$f" \ || err "Kann $f nicht laden ($REPO_URL/raw/branch/$BRANCH/$f)" done ok "Wrapper-Quelldateien geladen" pushd "$WORKDIR" >/dev/null RESULT=$(nix-build nix/default.nix --no-out-link 2>&1 | tail -1) popd >/dev/null [ -d "$RESULT" ] || err "nix-build fehlgeschlagen" ok "Paket gebaut: $RESULT" # --- 6. Ins User-Profil installieren -------------------------------------- step "Ins User-Profil installieren (nix-env)" nix-env --uninstall claude-desktop 2>/dev/null || true nix-env -i "$RESULT" ok "claude-desktop im \$PATH verfuegbar" # --- 7. Desktop-Datenbank refreshen --------------------------------------- step "Desktop-Menue aktualisieren" if command -v update-desktop-database >/dev/null; then update-desktop-database "$HOME/.nix-profile/share/applications" 2>/dev/null || true fi if command -v gtk-update-icon-cache >/dev/null; then gtk-update-icon-cache -q "$HOME/.nix-profile/share/icons/hicolor" 2>/dev/null || true fi ok "Menue + Icon-Cache aktualisiert" # --- Fertig --------------------------------------------------------------- echo echo "${BOLD}${GRN}✓ Claude Desktop v${VERSION} installiert${RST}" echo echo "Starten:" echo " ${BOLD}claude-desktop${RST} (Terminal)" echo " oder aus dem System-Menue: 'Claude Desktop'" echo echo "Updates holt die App selbstaendig (Button in Settings oder Auto-Check beim Start)."