Default behavior is now setup-only (symlinks + binary, no interactive launch) so array_started.sh can call it directly without arguments. Use --launch to start an interactive Claude session.
113 lines
5.8 KiB
Bash
Executable File
113 lines
5.8 KiB
Bash
Executable File
#!/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
|