#!/bin/bash # ============================================================================================== # ================================= Claude Code Startup ======================================== # ============================================================================================== # # PURPOSE # ───────────────────────────────────────────────────────────────────────────── # Restores Claude Code's persistent data after an Unraid reboot and launches Claude. # Unraid's root filesystem lives in RAM — /root/.claude and /root/.local are wiped on # every reboot. This script symlinks both directories back to persistent appdata storage # before launching Claude, so memory, sessions, and settings survive across reboots. # # On first run with no existing persistent data, migrates from the current live locations: # /root/.claude → PERSIST_DIR/.claude (memory, sessions, settings) # /root/.local/share/claude → PERSIST_DIR/local/share/claude (installed binaries) # Subsequent runs skip the migration and only create the symlinks. # # Standalone script — no common.sh dependency. Safe to run directly from terminal # or from array_started.sh. # # ============================================================================================== # RUNTIME MODES # ============================================================================================== # # claude_startup.sh # Set up persistent symlinks only — default, used by array_started.sh on boot. # # claude_startup.sh --launch # Set up persistent symlinks and launch Claude interactively. # # ============================================================================================== PERSIST_DIR="/mnt/user/appdata/claude-code" CLAUDE_DATA="$PERSIST_DIR/.claude" CLAUDE_BIN="$PERSIST_DIR/local/share/claude" LAUNCH=false [[ "$1" == "--launch" ]] && LAUNCH=true # Standalone — no common.sh dependency _log() { echo " ✅ $*"; } _warn() { echo " ⚠️ $*"; } _err() { echo " ❌ $*" >&2; } echo "" echo "━━━ Claude Code Startup ━━━" echo "" # ── Array must be mounted ───────────────────────────────────────────────────────────────────── if ! mountpoint -q /mnt/user 2>/dev/null; then _err "Array not mounted — /mnt/user not available" exit 1 fi # ── Create persistent dirs ──────────────────────────────────────────────────────────────────── mkdir -p "$CLAUDE_DATA" "$CLAUDE_BIN" # ── Migrate .claude on first run ────────────────────────────────────────────────────────────── if [[ ! -L /root/.claude && -d /root/.claude ]]; then _warn "First run — migrating /root/.claude → $CLAUDE_DATA" cp -a /root/.claude/. "$CLAUDE_DATA/" rm -rf /root/.claude _log "Migrated .claude (memory, sessions, settings)" elif [[ -z "$(ls -A "$CLAUDE_DATA" 2>/dev/null)" && -d /root/.claude ]]; then _warn "Persistent storage empty — copying current .claude data" cp -a /root/.claude/. "$CLAUDE_DATA/" _log "Copied .claude data to persistent storage" fi # ── Migrate Claude binaries on first run ────────────────────────────────────────────────────── if [[ ! -L /root/.local/share/claude && -d /root/.local/share/claude ]]; then _warn "First run — migrating Claude binaries → $CLAUDE_BIN" cp -a /root/.local/share/claude/. "$CLAUDE_BIN/" _log "Migrated Claude binaries" fi # ── Create symlinks ─────────────────────────────────────────────────────────────────────────── # Remove any real directories first — ln -sfn silently creates inside a dir instead of # replacing it, which produces a circular symlink on subsequent runs after migration. mkdir -p /root/.local/share /root/.local/bin [[ -d /root/.claude && ! -L /root/.claude ]] && rm -rf /root/.claude ln -sfn "$CLAUDE_DATA" /root/.claude _log ".claude → $CLAUDE_DATA" [[ -d /root/.local/share/claude && ! -L /root/.local/share/claude ]] && rm -rf /root/.local/share/claude ln -sfn "$CLAUDE_BIN" /root/.local/share/claude _log "claude binary → $CLAUDE_BIN" # ── Point the claude binary at the latest installed version ─────────────────────────────────── LATEST=$(ls "$CLAUDE_BIN/versions/" 2>/dev/null | sort -V | tail -1) if [[ -z "$LATEST" ]]; then _err "No Claude versions found in $CLAUDE_BIN/versions/" _err "Install Claude Code first: npm install -g @anthropic-ai/claude-code" exit 1 fi ln -sfn "$CLAUDE_BIN/versions/$LATEST" /root/.local/bin/claude _log "claude v$LATEST ready" echo "" # ── Setup-only mode (used by array_started.sh or other callers) ───────────────────────────────── if [[ "$LAUNCH" == false ]]; then _log "Setup complete — run 'claude' to start" echo "" exit 0 fi # ── Launch ──────────────────────────────────────────────────────────────────────────────────── export PATH="$HOME/.local/bin:$PATH" exec claude