Files
claudetools/scripts/migration-restore.sh
Mike Swanson fa15b03180 sync: Auto-sync from ACG-M-L5090 at 2026-03-10 19:11:00
Synced files:
- Quote wizard frontend (all components, hooks, types, config)
- API updates (config, models, routers, schemas, services)
- Client work (bg-builders, gurushow)
- Scripts (BGB Lesley termination, CIPP, Datto, migration)
- Temp files (Bardach contacts, VWP investigation, misc)
- Credentials and session logs
- Email service, PHP API, session logs

Machine: ACG-M-L5090
Timestamp: 2026-03-10 19:11:00

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 19:59:08 -07:00

297 lines
11 KiB
Bash

#!/bin/bash
###############################################################################
# migration-restore.sh
#
# Restores a ClaudeTools environment from an encrypted migration archive.
# Works in Git Bash on Windows AND native Linux bash.
#
# Usage: ./migration-restore.sh <archive.tar.gpg> [target_dir]
# archive.tar.gpg Path to the encrypted migration archive
# target_dir Where to clone/restore (default: $HOME/ClaudeTools)
###############################################################################
set -euo pipefail
# ---------------------------------------------------------------------------
# Globals
# ---------------------------------------------------------------------------
ARCHIVE_PATH="${1:-}"
TARGET_DIR="${2:-"${HOME}/ClaudeTools"}"
GITEA_REPO="ssh://git@172.16.3.20:2222/azcomputerguru/claudetools.git"
TEMP_EXTRACT=""
WARN_COUNT=0
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
log_info() { echo "[INFO] $*"; }
log_ok() { echo "[OK] $*"; }
log_warn() { echo "[WARNING] $*"; WARN_COUNT=$((WARN_COUNT + 1)); }
log_error() { echo "[ERROR] $*"; }
cleanup() {
if [[ -n "$TEMP_EXTRACT" && -d "$TEMP_EXTRACT" ]]; then
log_info "Cleaning up temporary extraction directory..."
rm -rf "$TEMP_EXTRACT"
fi
}
trap cleanup EXIT
check_tool() {
local tool="$1"
if ! command -v "$tool" &>/dev/null; then
log_error "Required tool not found: ${tool}"
log_error "Please install ${tool} before running this script."
exit 1
fi
log_ok "Found: ${tool}"
}
# Derive the Claude projects directory name from the target path.
# On Windows (Git Bash): /d/ClaudeTools -> D--ClaudeTools
# On Linux: /home/user/ClaudeTools -> -home-user-ClaudeTools
derive_claude_project_name() {
local abs_target
abs_target="$(cd "$TARGET_DIR" && pwd)"
# Check if we are on Windows (Git Bash) by looking at path format
if [[ "$abs_target" =~ ^/([a-zA-Z])/(.*) ]]; then
# Git Bash path: /d/ClaudeTools -> D--ClaudeTools
local drive="${BASH_REMATCH[1]^^}"
local rest="${BASH_REMATCH[2]}"
echo "${drive}--${rest//\//-}"
elif [[ "$abs_target" =~ ^([a-zA-Z]):(.*) ]]; then
# Raw Windows path: D:\ClaudeTools -> D--ClaudeTools
local drive="${BASH_REMATCH[1]^^}"
local rest="${BASH_REMATCH[2]}"
rest="${rest//\\/-}"
rest="${rest//\//-}"
rest="${rest#-}"
echo "${drive}--${rest}"
else
# Linux/macOS: /home/user/ClaudeTools -> -home-user-ClaudeTools
local name="${abs_target//\//-}"
name="${name#-}"
echo "${name}"
fi
}
# ---------------------------------------------------------------------------
# Main
# ---------------------------------------------------------------------------
main() {
echo "============================================================"
echo " ClaudeTools Migration Restore"
echo " $(date '+%Y-%m-%d %H:%M:%S')"
echo "============================================================"
echo ""
# ------------------------------------------------------------------
# Validate arguments
# ------------------------------------------------------------------
if [[ -z "$ARCHIVE_PATH" ]]; then
log_error "Usage: $0 <archive.tar.gpg> [target_dir]"
log_error " archive.tar.gpg Encrypted migration archive"
log_error " target_dir Restore location (default: \$HOME/ClaudeTools)"
exit 1
fi
if [[ ! -f "$ARCHIVE_PATH" ]]; then
log_error "Archive not found: ${ARCHIVE_PATH}"
exit 1
fi
log_info "Archive: ${ARCHIVE_PATH}"
log_info "Target dir: ${TARGET_DIR}"
echo ""
# ------------------------------------------------------------------
# Check required tools
# ------------------------------------------------------------------
log_info "--- Checking required tools ---"
check_tool git
check_tool gpg
check_tool tar
echo ""
# ------------------------------------------------------------------
# Decrypt archive
# ------------------------------------------------------------------
log_info "--- Decrypting archive ---"
log_info "You will be prompted for the passphrase."
echo ""
TEMP_EXTRACT="$(mktemp -d 2>/dev/null || mktemp -d -t 'migration-restore')"
local tar_tmp="${TEMP_EXTRACT}/archive.tar"
if [[ -n "${GPG_PASSPHRASE:-}" ]]; then
echo "$GPG_PASSPHRASE" | gpg --batch --yes --passphrase-fd 0 \
--decrypt --output "$tar_tmp" "$ARCHIVE_PATH"
else
gpg --decrypt --output "$tar_tmp" "$ARCHIVE_PATH"
fi
if [[ ! -f "$tar_tmp" ]]; then
log_error "Decryption failed. Check your passphrase and try again."
exit 1
fi
log_ok "Archive decrypted."
echo ""
# ------------------------------------------------------------------
# Extract archive to temp location
# ------------------------------------------------------------------
log_info "--- Extracting archive ---"
local extract_dir="${TEMP_EXTRACT}/contents"
mkdir -p "$extract_dir"
tar -xf "$tar_tmp" -C "$extract_dir"
rm -f "$tar_tmp"
log_ok "Archive extracted."
# Show manifest if present
if [[ -f "${extract_dir}/MIGRATION_MANIFEST.txt" ]]; then
echo ""
log_info "--- Migration Manifest ---"
cat "${extract_dir}/MIGRATION_MANIFEST.txt"
echo ""
fi
# ------------------------------------------------------------------
# Clone repository
# ------------------------------------------------------------------
log_info "--- Cloning repository ---"
if [[ -d "$TARGET_DIR/.git" ]]; then
log_warn "Target directory already contains a git repo: ${TARGET_DIR}"
log_info "Skipping clone; will overlay migration files into existing repo."
elif [[ -d "$TARGET_DIR" ]]; then
# Directory exists but is not a git repo
log_warn "Target directory exists but is not a git repo: ${TARGET_DIR}"
log_info "Attempting clone into existing directory..."
git clone "$GITEA_REPO" "${TARGET_DIR}.tmp"
# Move .git and tracked files into existing directory
mv "${TARGET_DIR}.tmp/.git" "${TARGET_DIR}/"
# Checkout working tree into existing directory
(cd "$TARGET_DIR" && git checkout -- .)
rm -rf "${TARGET_DIR}.tmp"
log_ok "Cloned repository into existing directory."
else
git clone "$GITEA_REPO" "$TARGET_DIR"
log_ok "Cloned repository to: ${TARGET_DIR}"
fi
echo ""
# ------------------------------------------------------------------
# Overlay non-git files from migration archive
# ------------------------------------------------------------------
log_info "--- Restoring non-git files ---"
# Copy everything except claude-context (handled separately) and manifest
local item
for item in "$extract_dir"/*; do
local basename
basename="$(basename "$item")"
# Skip claude-context dir and manifest
if [[ "$basename" == "claude-context" || "$basename" == "MIGRATION_MANIFEST.txt" ]]; then
continue
fi
if [[ -d "$item" ]]; then
cp -a "$item" "$TARGET_DIR/"
log_ok "Restored directory: ${basename}"
elif [[ -f "$item" ]]; then
cp -a "$item" "$TARGET_DIR/"
log_ok "Restored file: ${basename}"
fi
done
# Handle dotfiles (hidden files/dirs from archive root)
for item in "$extract_dir"/.*; do
local basename
basename="$(basename "$item")"
[[ "$basename" == "." || "$basename" == ".." ]] && continue
if [[ -d "$item" ]]; then
# Merge directory contents (e.g., .claude/)
cp -a "$item"/. "$TARGET_DIR/${basename}/" 2>/dev/null || cp -a "$item" "$TARGET_DIR/"
log_ok "Restored directory: ${basename}"
elif [[ -f "$item" ]]; then
cp -a "$item" "$TARGET_DIR/"
log_ok "Restored file: ${basename}"
fi
done
echo ""
# ------------------------------------------------------------------
# Restore Claude AI context
# ------------------------------------------------------------------
log_info "--- Restoring Claude AI context ---"
local claude_ctx_src="${extract_dir}/claude-context"
if [[ -d "$claude_ctx_src" ]]; then
local project_name
project_name="$(derive_claude_project_name)"
local claude_ctx_dst="${HOME}/.claude/projects/${project_name}"
mkdir -p "$claude_ctx_dst"
cp -a "$claude_ctx_src"/. "$claude_ctx_dst/"
log_ok "Restored Claude context to: ${claude_ctx_dst}"
else
log_warn "No claude-context directory found in archive. Skipping."
fi
echo ""
# ------------------------------------------------------------------
# Initialize submodules
# ------------------------------------------------------------------
log_info "--- Initializing git submodules ---"
(cd "$TARGET_DIR" && git submodule update --init --recursive) && \
log_ok "Submodules initialized." || \
log_warn "Submodule initialization had issues. You may need to run it manually."
echo ""
# ------------------------------------------------------------------
# Summary and post-restore checklist
# ------------------------------------------------------------------
echo "============================================================"
echo " Restore Complete"
echo "============================================================"
echo ""
echo " Target: ${TARGET_DIR}"
echo " Warnings: ${WARN_COUNT}"
echo ""
echo "============================================================"
echo " Post-Restore Checklist"
echo "============================================================"
echo ""
echo " [ ] Verify credentials.md contains correct, unredacted values"
echo " File: ${TARGET_DIR}/credentials.md"
echo ""
echo " [ ] Set up Python virtual environment for MCP servers"
echo " cd ${TARGET_DIR} && python -m venv .venv"
echo " source .venv/bin/activate (or .venv\\Scripts\\activate on Windows)"
echo " pip install -r requirements.txt"
echo ""
echo " [ ] Configure Claude Code CLI"
echo " Run: claude (first launch will prompt for authentication)"
echo " Verify .claude/ context was restored correctly"
echo ""
echo " [ ] Test Gitea SSH access"
echo " Run: ssh -p 2222 git@172.16.3.20"
echo " If it fails, copy your SSH keys and update ~/.ssh/config"
echo ""
echo " [ ] Rebuild grepai index"
echo " The semantic search index is machine-specific."
echo " Run grepai indexing from within Claude Code."
echo ""
echo " [ ] Verify .env and .mcp.json values are correct for new machine"
echo ""
echo " [ ] Test database connectivity"
echo " Ensure 172.16.3.30:3306 is reachable from this machine"
echo ""
log_ok "Done."
}
main "$@"