#!/usr/bin/env bash set -euo pipefail # Backup helper for OpenClaude local stack. # # Creates timestamped backup with: # - OpenClaude/Claude config files (if present) # - env profiles (without rewriting) # - Ollama model list and metadata # - optional Qdrant collection snapshot (if API is reachable) # # Usage: # ./backup.sh # ./backup.sh --output-dir /path/to/backups # ./backup.sh --collection mydocs OUTPUT_DIR="${OUTPUT_DIR:-$HOME/openclaude-backups}" COLLECTION="${QDRANT_COLLECTION:-docs}" QDRANT_URL="${QDRANT_URL:-http://127.0.0.1:6333}" STAMP="$(date +%Y%m%d_%H%M%S)" TARGET="" while [[ $# -gt 0 ]]; do case "$1" in --output-dir) OUTPUT_DIR="$2" shift 2 ;; --collection) COLLECTION="$2" shift 2 ;; *) echo "Unknown argument: $1" exit 2 ;; esac done mkdir -p "$OUTPUT_DIR" TARGET="${OUTPUT_DIR}/backup_${STAMP}" mkdir -p "$TARGET" echo "==> Backup target: $TARGET" copy_if_exists() { local src="$1" local dst="$2" if [[ -e "$src" ]]; then mkdir -p "$(dirname "$dst")" cp -R "$src" "$dst" echo " copied: $src" fi } echo "==> Backing up configs" copy_if_exists "$HOME/.claude/settings.json" "$TARGET/config/claude/settings.json" copy_if_exists "$HOME/.claude.json" "$TARGET/config/claude/claude.json" copy_if_exists "$HOME/.config/openclaude/profiles" "$TARGET/config/openclaude/profiles" echo "==> Backing up model inventory" if command -v ollama >/dev/null 2>&1; then ollama list > "$TARGET/ollama_models.txt" || true ollama ps > "$TARGET/ollama_running.txt" || true echo " saved: ollama model inventory" else echo " skip: ollama not installed" fi echo "==> Exporting Qdrant collection (if available)" if curl -fsS "${QDRANT_URL}/collections/${COLLECTION}" >/dev/null 2>&1; then mkdir -p "$TARGET/qdrant" curl -fsS "${QDRANT_URL}/collections/${COLLECTION}" > "$TARGET/qdrant/${COLLECTION}_meta.json" # Try to export up to 10000 points via scroll API. # This is a practical backup for small/medium collections. curl -fsS -X POST "${QDRANT_URL}/collections/${COLLECTION}/points/scroll" \ -H "Content-Type: application/json" \ -d '{"limit":10000,"with_payload":true,"with_vector":false}' \ > "$TARGET/qdrant/${COLLECTION}_points.json" || true echo " saved: qdrant metadata and points snapshot" else echo " skip: qdrant collection not reachable (${COLLECTION})" fi cat > "$TARGET/RESTORE_NOTES.txt" < 3) Restore Qdrant collection data: - Ensure Qdrant is running. - Recreate collection if needed. - Reindex from source docs (recommended) OR replay points from: $TARGET/qdrant/${COLLECTION}_points.json Note: reindex from original documents is the safest restore method. EOF echo echo "Backup completed: $TARGET"