#!/bin/bash # Skills 101 with Claude Code — Setup Script for macOS # Usage: curl -fsSL https://learn.mervia.academy/courses/skills-101-with-claude-code/companion/scripts/setup-mac.sh | bash set -e # Colors GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' RED='\033[0;31m' BOLD='\033[1m' NC='\033[0m' info() { echo -e "${BLUE}[INFO]${NC} $1"; } success() { echo -e "${GREEN}[OK]${NC} $1"; } warn() { echo -e "${YELLOW}[!]${NC} $1"; } fail() { echo -e "${RED}[ERROR]${NC} $1"; } INSTALLED=() SKIPPED=() FAILED=() echo "" echo -e "${BLUE}${BOLD}Skills 101 with Claude Code — macOS Setup${NC}" echo -e "${BLUE}===========================================${NC}" echo "" # ─── 1. Claude Code ───────────────────────────────────── info "Checking Claude Code..." if command -v claude &> /dev/null; then success "Claude Code already installed" SKIPPED+=("Claude Code") else info "Installing Claude Code (official installer)..." if curl -fsSL https://claude.ai/install.sh | bash; then # Refresh PATH to pick up newly installed binary export PATH="$HOME/.claude/bin:$HOME/.local/bin:/usr/local/bin:$PATH" # Ensure PATH is persisted in shell profile CLAUDE_BIN="" for dir in "$HOME/.claude/bin" "$HOME/.local/bin" "/usr/local/bin"; do if [ -x "$dir/claude" ]; then CLAUDE_BIN="$dir" break fi done if [ -n "$CLAUDE_BIN" ]; then # Detect shell profile SHELL_RC="" case "${SHELL:-}" in */zsh) SHELL_RC="$HOME/.zshrc" ;; */bash) SHELL_RC="$HOME/.bash_profile" ;; esac if [ -n "$SHELL_RC" ] && ! grep -q "$CLAUDE_BIN" "$SHELL_RC" 2>/dev/null; then echo '' >> "$SHELL_RC" echo '# Claude Code' >> "$SHELL_RC" echo "export PATH=\"$CLAUDE_BIN:\$PATH\"" >> "$SHELL_RC" info "Added $CLAUDE_BIN to $SHELL_RC" fi fi INSTALLED+=("Claude Code") else FAILED+=("Claude Code") fi fi # ─── 2. VS Code ───────────────────────────────────────── info "Checking VS Code..." if command -v code &> /dev/null; then success "VS Code already installed" SKIPPED+=("VS Code") elif [ -d "/Applications/Visual Studio Code.app" ]; then success "VS Code already installed (shell command not set up — see next steps)" SKIPPED+=("VS Code") else info "Installing VS Code..." VSCODE_ZIP="/tmp/vscode-mac.zip" if curl -fsSL "https://code.visualstudio.com/sha/download?build=stable&os=darwin-universal" -o "$VSCODE_ZIP"; then unzip -q "$VSCODE_ZIP" -d /Applications/ rm -f "$VSCODE_ZIP" if [ -d "/Applications/Visual Studio Code.app" ]; then INSTALLED+=("VS Code") else FAILED+=("VS Code") fi else fail "Download failed." echo "" echo -e " Please install VS Code manually:" echo -e " 1. Go to ${BLUE}https://code.visualstudio.com/${NC}" echo -e " 2. Click Download and install like any other app" echo "" FAILED+=("VS Code (manual install needed)") fi fi # ─── 3. Node.js ───────────────────────────────────────── info "Checking Node.js..." if command -v node &> /dev/null; then success "Node.js already installed — $(node --version)" SKIPPED+=("Node.js") else # Fetch the latest LTS version number from nodejs.org NODE_VERSION=$(curl -fsSL https://nodejs.org/dist/index.json | grep -o '"version":"v[0-9.]*"' | head -1 | grep -o 'v[0-9.]*') if [ -z "$NODE_VERSION" ]; then NODE_VERSION="v22.15.0" warn "Could not detect latest version, using $NODE_VERSION" fi # Detect architecture ARCH=$(uname -m) if [ "$ARCH" = "arm64" ]; then NODE_PKG="node-${NODE_VERSION}-darwin-arm64.pkg" else NODE_PKG="node-${NODE_VERSION}-darwin-x64.pkg" fi info "Installing Node.js ${NODE_VERSION}..." NODE_PKG_PATH="/tmp/$NODE_PKG" if curl -fsSL "https://nodejs.org/dist/${NODE_VERSION}/${NODE_PKG}" -o "$NODE_PKG_PATH"; then info "This may ask for your Mac password (characters won't show — that's normal)." if sudo installer -pkg "$NODE_PKG_PATH" -target /; then rm -f "$NODE_PKG_PATH" export PATH="/usr/local/bin:$PATH" INSTALLED+=("Node.js ${NODE_VERSION}") else rm -f "$NODE_PKG_PATH" FAILED+=("Node.js") fi else fail "Download failed." echo "" echo -e " Please install Node.js manually:" echo -e " 1. Go to ${BLUE}https://nodejs.org/${NC}" echo -e " 2. Download the LTS version and install like any other app" echo "" FAILED+=("Node.js (manual install needed)") fi fi # ─── Summary ───────────────────────────────────────────── echo "" echo -e "${BLUE}${BOLD}Setup Summary${NC}" echo -e "${BLUE}===========================================${NC}" if [ ${#SKIPPED[@]} -gt 0 ]; then echo "" echo -e "${GREEN}Already had:${NC}" for item in "${SKIPPED[@]}"; do echo " $item"; done fi if [ ${#INSTALLED[@]} -gt 0 ]; then echo "" echo -e "${GREEN}Newly installed:${NC}" for item in "${INSTALLED[@]}"; do echo " $item"; done fi if [ ${#FAILED[@]} -gt 0 ]; then echo "" echo -e "${RED}Failed:${NC}" for item in "${FAILED[@]}"; do echo " $item"; done echo "" warn "Please share the error above in the LINE group for help." fi # Final verification echo "" echo -e "${BOLD}Final check:${NC}" command -v claude &> /dev/null && echo -e " ${GREEN}claude${NC}" || echo -e " ${RED}claude — not found${NC}" (command -v code &> /dev/null || [ -d "/Applications/Visual Studio Code.app" ]) && echo -e " ${GREEN}VS Code${NC}" || echo -e " ${RED}VS Code — not found${NC}" command -v node &> /dev/null && echo -e " ${GREEN}node $(node --version)${NC}" || echo -e " ${RED}node — not found${NC}" echo "" echo -e "${YELLOW}${BOLD}Next steps:${NC}" echo "" echo " 1. Log in to Claude:" echo -e " ${BOLD}claude${NC}" echo " (choose 'Login with Claude.ai' and follow the browser)" echo ""