install.sh aborted with npm EEXIST when claude was already present: the binary is a native-installer symlink (~/.local/bin/claude -> ~/.local/share/claude/versions/*) that npm does not own, and the npm prefix (~/.local, set for BLK-013) targets the same path. The `else err` branch turned EEXIST into a fatal exit. No presence guard existed, unlike the RTK/GSD steps. - install.sh: skip-if-present guard (command -v claude), mirroring the RTK/GSD pattern; npm only runs on a truly fresh machine. - update-all.sh: pick updater by channel — npm for npm-managed installs, `claude update` for native installs (npm would EEXIST). Co-Authored-By: Claude <noreply@anthropic.com>
117 lines
3.5 KiB
Bash
Executable File
117 lines
3.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# ============================================================
|
|
# Claude Code — Bootstrap installer
|
|
# Installs Claude Code CLI, authenticates, then sets up
|
|
# symlinks and plugins for the claude-config repo.
|
|
# ============================================================
|
|
set -euo pipefail
|
|
|
|
RED='\033[0;31m'; GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'; BLUE='\033[0;34m'; NC='\033[0m'
|
|
ok() { echo -e "${GREEN}✓${NC} $1"; }
|
|
warn() { echo -e "${YELLOW}⚠${NC} $1"; }
|
|
info() { echo -e "${BLUE}→${NC} $1"; }
|
|
err() { echo -e "${RED}✗${NC} $1"; exit 1; }
|
|
|
|
REPO="$(cd "$(dirname "$0")" && pwd)"
|
|
|
|
echo ""
|
|
echo "═══ claude-config bootstrap installer ═══"
|
|
echo ""
|
|
|
|
# ── 1. Check prerequisites ──
|
|
echo "── Checking prerequisites..."
|
|
|
|
# node + npm drive the Claude Code CLI install below. On a fresh machine
|
|
# they may be absent — install the current LTS via nvm instead of aborting.
|
|
install_node_via_nvm() {
|
|
info "Node.js/npm missing — installing LTS via nvm..."
|
|
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
|
|
export NVM_DIR="${NVM_DIR:-$HOME/.nvm}"
|
|
# shellcheck source=/dev/null
|
|
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
|
|
nvm install --lts
|
|
}
|
|
|
|
if ! command -v node &>/dev/null || ! command -v npm &>/dev/null; then
|
|
install_node_via_nvm
|
|
fi
|
|
|
|
if ! command -v node &>/dev/null; then
|
|
err "Node.js install failed — install it manually: https://nodejs.org"
|
|
fi
|
|
|
|
NODE_MAJOR=$(node -v | sed 's/v//' | cut -d. -f1)
|
|
if [ "$NODE_MAJOR" -lt 18 ]; then
|
|
err "Node.js >= 18 required (found $(node -v))"
|
|
fi
|
|
ok "Node.js $(node -v)"
|
|
|
|
if ! command -v npm &>/dev/null; then
|
|
err "npm not found (expected alongside Node.js)"
|
|
fi
|
|
ok "npm $(npm -v)"
|
|
|
|
# ── 2. Install Claude Code CLI ──
|
|
echo ""
|
|
echo "── Installing Claude Code..."
|
|
|
|
# Idempotent: an existing claude (native installer under ~/.local/share/claude,
|
|
# or any prior install) already owns ~/.local/bin/claude — npm cannot clobber a
|
|
# symlink it does not manage (EEXIST). Mirror the RTK/GSD skip-if-present guard;
|
|
# upgrades are `make update`'s job (update-all.sh), not first-time install.
|
|
if command -v claude &>/dev/null; then
|
|
ok "Claude Code already installed ($(claude --version 2>/dev/null | head -1))"
|
|
elif npm install -g @anthropic-ai/claude-code@latest; then
|
|
ok "Claude Code installed: $(claude --version 2>/dev/null || echo 'unknown')"
|
|
else
|
|
err "Claude Code installation failed"
|
|
fi
|
|
|
|
# ── 3. Authenticate ──
|
|
echo ""
|
|
echo "── Authentication"
|
|
echo ""
|
|
echo " You need to log in to Claude Code."
|
|
echo " This will open an interactive session."
|
|
echo ""
|
|
printf " Press Enter to launch 'claude login'... "
|
|
read -r
|
|
|
|
if claude login; then
|
|
ok "Authenticated"
|
|
else
|
|
warn "Login exited with non-zero status"
|
|
warn "You can retry later with: claude login"
|
|
fi
|
|
|
|
# ── 4. Init git submodules ──
|
|
echo ""
|
|
echo "── Initializing submodules..."
|
|
cd "$REPO"
|
|
if git submodule update --init 2>/dev/null; then
|
|
ok "Submodules initialized"
|
|
else
|
|
warn "Submodule init failed — some plugins may be unavailable"
|
|
fi
|
|
|
|
# ── 5. Symlink config into ~/.claude/ ──
|
|
echo ""
|
|
echo "── Setting up symlinks..."
|
|
bash "$REPO/link.sh"
|
|
|
|
# ── 6. Install plugins ──
|
|
echo ""
|
|
echo "── Installing plugins..."
|
|
bash "$REPO/install-plugins.sh"
|
|
|
|
# ── Done ──
|
|
echo ""
|
|
echo "═══════════════════════════════════════════"
|
|
echo ""
|
|
ok "Bootstrap complete!"
|
|
echo ""
|
|
echo " Start Claude Code in any project with:"
|
|
echo " claude"
|
|
echo ""
|