#!/usr/bin/env bash # # Marius Müller Media — Komplett-Setup (Mac) # # Aufruf (eine Zeile, ins Terminal einfügen): # curl -fsSL https://setup.mariusmueller.media | bash # # Installiert alles, was im ganzen Kurs gebraucht wird: # • Apple-Entwicklerwerkzeuge (bringen git und python3 mit) # • Homebrew (der Paketmanager für den Mac) # • Node, git, GitHub-CLI, Python 3 # • Beautiful Soup (zum Auslesen von Webseiten) # • den Skill "find-skills" # # Grundsatz: Das Skript bricht nie ab. Was schon da ist, wird übersprungen. # Was nicht klappt, steht am Ende ruhig in der Zusammenfassung. LOG="/tmp/mm-setup.log" : > "$LOG" FEHLT=() GETAN=() kopf() { printf "\n\033[1m%s\033[0m\n" "$1"; } ok() { printf "\033[32m ✓\033[0m %s\n" "$1"; GETAN+=("$1"); } da() { printf "\033[32m ✓\033[0m %s\n" "$1"; } tun() { printf " … %s\n" "$1"; } hm() { printf "\033[33m •\033[0m %s\n" "$1"; FEHLT+=("$2"); } printf "\n\033[1m Marius Müller Media — Komplett-Setup\033[0m\n" printf " ------------------------------------\n" printf " Das dauert je nach Internet 5 bis 20 Minuten.\n" printf " Du musst nichts tun außer einmal dein Passwort eingeben.\n" if [ "$(uname -s)" != "Darwin" ]; then printf "\n Diese Zeile ist für den Mac. Für Windows nimm:\n" printf " irm https://setup.mariusmueller.media/win | iex\n\n" exit 0 fi # --------------------------------------------------------------------------- kopf "1. Apple-Entwicklerwerkzeuge (bringen git und python3 mit)" if xcode-select -p >/dev/null 2>&1; then da "Sind schon installiert." else tun "Fehlen noch. Gleich geht ein Fenster auf." printf "\n" printf " \033[1mKlick dort auf „Installieren\" und warte, bis es fertig ist.\033[0m\n" printf " Das ist der größte Brocken (rund 1 GB) und dauert am längsten.\n\n" xcode-select --install >>"$LOG" 2>&1 # bis zu 30 Minuten geduldig warten warte=0 while ! xcode-select -p >/dev/null 2>&1; do sleep 15 warte=$((warte + 15)) [ $((warte % 120)) -eq 0 ] && tun "läuft noch … ($((warte / 60)) Minuten)" if [ "$warte" -ge 1800 ]; then break; fi done if xcode-select -p >/dev/null 2>&1; then ok "Apple-Entwicklerwerkzeuge installiert." else hm "Noch nicht fertig — läuft vielleicht im Hintergrund weiter." "Apple-Entwicklerwerkzeuge" fi fi # --------------------------------------------------------------------------- kopf "2. Homebrew" brew_pfad() { [ -x /opt/homebrew/bin/brew ] && { echo /opt/homebrew/bin/brew; return; } [ -x /usr/local/bin/brew ] && { echo /usr/local/bin/brew; return; } command -v brew 2>/dev/null } BREW="$(brew_pfad)" if [ -n "$BREW" ]; then da "Ist schon installiert." else tun "Wird installiert — dabei fragt der Mac nach deinem Passwort." printf "\n \033[1mBeim Tippen bewegt sich nichts. Das ist normal.\033[0m\n\n" NONINTERACTIVE=1 /bin/bash -c \ "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" >>"$LOG" 2>&1 BREW="$(brew_pfad)" [ -n "$BREW" ] && ok "Homebrew installiert." || hm "Hat nicht geklappt." "Homebrew" fi if [ -n "$BREW" ]; then eval "$("$BREW" shellenv)" 2>/dev/null ZEILE="eval \"\$($BREW shellenv)\"" for RC in "$HOME/.zprofile" "$HOME/.zshrc"; do [ -e "$RC" ] || [ "$RC" = "$HOME/.zprofile" ] || continue grep -q "brew shellenv" "$RC" 2>/dev/null || printf "\n%s\n" "$ZEILE" >> "$RC" done fi # --------------------------------------------------------------------------- kopf "3. Werkzeuge" hol() { # hol if command -v "$1" >/dev/null 2>&1; then da "$3 ist da." elif [ -n "$BREW" ]; then tun "$3 wird installiert …" if "$BREW" install "$2" >>"$LOG" 2>&1; then ok "$3 installiert." else hm "$3 ließ sich nicht installieren." "$3"; fi else hm "$3 fehlt (ohne Homebrew nicht möglich)." "$3" fi } # Node braucht mindestens 22.20 — über absolute Pfade prüfen, weil im # Suchpfad (z. B. durch nvm) eine ältere Version davorstehen kann. version_reicht() { # $1 = Pfad zu node [ -x "$1" ] || return 1 v="$("$1" -v 2>/dev/null)"; v="${v#v}" maj="${v%%.*}"; rest="${v#*.}"; min="${rest%%.*}" case "$maj" in ''|*[!0-9]*) return 1 ;; esac case "$min" in ''|*[!0-9]*) min=0 ;; esac [ "$maj" -gt 22 ] && return 0 [ "$maj" -eq 22 ] && [ "$min" -ge 20 ] && return 0 return 1 } finde_node() { NODE="" for kandidat in "$(command -v node 2>/dev/null)" \ /opt/homebrew/bin/node \ /usr/local/bin/node; do [ -n "$kandidat" ] || continue if version_reicht "$kandidat"; then NODE="$kandidat"; return 0; fi done return 1 } if finde_node; then da "Node $("$NODE" -v) ist da." elif [ -n "$BREW" ]; then tun "Node wird installiert …" "$BREW" install node >>"$LOG" 2>&1 hash -r 2>/dev/null || true if finde_node; then ok "Node $("$NODE" -v) installiert." else hm "Node ließ sich nicht installieren." "Node"; fi else hm "Node fehlt." "Node" fi # Hinweis, falls im Terminal eine ältere Version davorsteht (nvm & Co.) if [ -n "${NODE:-}" ]; then IM_PFAD="$(command -v node 2>/dev/null)" if [ -n "$IM_PFAD" ] && [ "$IM_PFAD" != "$NODE" ] && ! version_reicht "$IM_PFAD"; then printf "\033[33m •\033[0m In deinem Terminal zeigt „node\" noch auf %s — stört hier nicht.\n" "$("$IM_PFAD" -v)" fi fi hol git git "git" hol gh gh "GitHub-Werkzeug (gh)" hol python3 python "Python 3" # Beautiful Soup if command -v python3 >/dev/null 2>&1; then if python3 -c "import bs4" >/dev/null 2>&1; then da "Beautiful Soup ist da." else tun "Beautiful Soup wird installiert …" # Drei Anläufe, weil Python je nach Herkunft andere Regeln hat: # normal (python.org) → --user (Apple-Python) → --break-system-packages (Homebrew) python3 -m pip install --quiet beautifulsoup4 requests >>"$LOG" 2>&1 \ || python3 -m pip install --quiet --user beautifulsoup4 requests >>"$LOG" 2>&1 \ || python3 -m pip install --quiet --break-system-packages beautifulsoup4 requests >>"$LOG" 2>&1 if python3 -c "import bs4" >/dev/null 2>&1; then ok "Beautiful Soup installiert." else hm "Beautiful Soup ließ sich nicht installieren." "Beautiful Soup"; fi fi fi # --------------------------------------------------------------------------- kopf "4. Skill" if [ -n "${NODE:-}" ]; then BIN="$(dirname "$NODE")" tun "find-skills wird installiert …" if PATH="$BIN:$PATH" "$BIN/npx" --yes skills@latest add vercel-labs/skills --global --yes >>"$LOG" 2>&1; then ok "find-skills installiert." else hm "Der Skill ließ sich nicht installieren." "find-skills" fi else hm "Ohne Node kein Skill." "find-skills" fi # --------------------------------------------------------------------------- printf "\n\033[1m Zusammenfassung\033[0m\n" printf " ---------------\n" for g in "${GETAN[@]}"; do printf "\033[32m ✓\033[0m %s\n" "$g"; done [ ${#GETAN[@]} -eq 0 ] && printf " Es war schon alles da — nichts zu tun.\n" if [ ${#FEHLT[@]} -gt 0 ]; then printf "\n\033[33m Das hat noch nicht geklappt:\033[0m\n" for f in "${FEHLT[@]}"; do printf " • %s\n" "$f"; done printf "\n Kein Drama. Sag Claude einfach:\n" printf " \033[1m„Bei mir hat %s nicht funktioniert, schau in /tmp/mm-setup.log\"\033[0m\n" "${FEHLT[0]}" else printf "\n\033[1m Fertig — du hast alles, was der Kurs braucht.\033[0m\n" fi printf "\n Starte Claude Code einmal neu, dann kann es losgehen.\n\n" exit 0