Jake Shore cb28c2649f Initial commit: Clawdbot Memory System installer
One-command persistent memory for Clawdbot.
Prevents context amnesia during compaction with:
- Two-layer memory: Markdown source of truth + SQLite vector search
- Pre-compaction flush to save context before it's lost
- Semantic search across all memory files
- Daily logs, research intel, and project tracking templates
- Interactive installer with dry-run and uninstall support
2026-02-10 13:35:36 -05:00

763 lines
23 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<![CDATA[#!/usr/bin/env bash
set -euo pipefail
# ============================================================================
# Clawdbot Memory System — One-Command Installer
# https://github.com/BusyBee3333/clawdbot-memory-system
#
# Usage:
# bash install.sh # Interactive install
# bash install.sh --dry-run # Preview changes without applying
# bash install.sh --uninstall # Remove memory system config
# ============================================================================
VERSION="1.0.0"
# --- Colors & Formatting ---
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
CYAN='\033[0;36m'
BOLD='\033[1m'
DIM='\033[2m'
NC='\033[0m' # No Color
# --- State ---
DRY_RUN=false
UNINSTALL=false
CLAWDBOT_DIR=""
WORKSPACE_DIR=""
CONFIG_FILE=""
AGENTS_FILE=""
MEMORY_DIR=""
PROVIDER=""
API_KEY=""
CHANGES_MADE=()
FILES_INDEXED=0
EXISTING_MEMORY_FILES=0
# --- Parse Args ---
for arg in "$@"; do
case "$arg" in
--dry-run) DRY_RUN=true ;;
--uninstall) UNINSTALL=true ;;
--help|-h)
echo "Clawdbot Memory System Installer v${VERSION}"
echo ""
echo "Usage:"
echo " bash install.sh Interactive install"
echo " bash install.sh --dry-run Preview changes without applying"
echo " bash install.sh --uninstall Remove memory system config"
exit 0
;;
*)
echo -e "${RED}Unknown option: $arg${NC}"
echo "Use --help for usage information."
exit 1
;;
esac
done
# --- Helper Functions ---
info() { echo -e "${BLUE}${NC} $1"; }
success() { echo -e "${GREEN}${NC} $1"; }
warn() { echo -e "${YELLOW}⚠️${NC} $1"; }
error() { echo -e "${RED}${NC} $1"; }
step() { echo -e "\n${BOLD}${MAGENTA}$1${NC}"; }
detail() { echo -e " ${DIM}$1${NC}"; }
dry() { echo -e " ${CYAN}[dry-run]${NC} $1"; }
banner() {
echo ""
echo -e "${BOLD}${MAGENTA}"
echo " ╔══════════════════════════════════════════════╗"
echo " ║ 🧠 Clawdbot Memory System v${VERSION}"
echo " ║ Never lose context to compaction again ║"
echo " ╚══════════════════════════════════════════════╝"
echo -e "${NC}"
}
# --- Detect Clawdbot Installation ---
detect_clawdbot() {
step "🔍 Detecting Clawdbot installation..."
# Check common locations
for dir in "$HOME/.clawdbot" "$HOME/.openclaw" "$HOME/.moltbot"; do
if [[ -d "$dir" ]]; then
CLAWDBOT_DIR="$dir"
break
fi
done
if [[ -z "$CLAWDBOT_DIR" ]]; then
error "Clawdbot installation not found!"
echo ""
echo " Looked in:"
echo " ~/.clawdbot"
echo " ~/.openclaw"
echo " ~/.moltbot"
echo ""
echo " Make sure Clawdbot is installed first:"
echo " https://docs.clawd.bot/getting-started"
exit 1
fi
success "Found Clawdbot at ${BOLD}${CLAWDBOT_DIR}${NC}"
# Find config file
CONFIG_FILE="${CLAWDBOT_DIR}/clawdbot.json"
if [[ ! -f "$CONFIG_FILE" ]]; then
# Try alternate names
for name in "openclaw.json" "moltbot.json"; do
if [[ -f "${CLAWDBOT_DIR}/${name}" ]]; then
CONFIG_FILE="${CLAWDBOT_DIR}/${name}"
break
fi
done
fi
if [[ ! -f "$CONFIG_FILE" ]]; then
error "Config file not found at ${CONFIG_FILE}"
echo " Run 'clawdbot doctor' first to initialize your setup."
exit 1
fi
success "Found config at ${BOLD}${CONFIG_FILE}${NC}"
# Find workspace
WORKSPACE_DIR=$(python3 -c "
import json, os
with open('${CONFIG_FILE}') as f:
cfg = json.load(f)
ws = cfg.get('agents', {}).get('defaults', {}).get('workspace', '')
if not ws:
ws = os.path.expanduser('~') + '/' + os.path.basename('${CLAWDBOT_DIR}') + '/workspace'
print(os.path.expanduser(ws))
" 2>/dev/null || echo "${CLAWDBOT_DIR}/workspace")
if [[ ! -d "$WORKSPACE_DIR" ]]; then
warn "Workspace directory not found at ${WORKSPACE_DIR}"
if $DRY_RUN; then
dry "Would create workspace directory"
else
mkdir -p "$WORKSPACE_DIR"
success "Created workspace directory"
fi
fi
success "Workspace: ${BOLD}${WORKSPACE_DIR}${NC}"
MEMORY_DIR="${WORKSPACE_DIR}/memory"
AGENTS_FILE="${WORKSPACE_DIR}/AGENTS.md"
}
# --- Check Dependencies ---
check_deps() {
step "🔧 Checking dependencies..."
# Check for jq
if ! command -v jq &>/dev/null; then
warn "jq is not installed (needed for safe JSON config patching)"
echo ""
if command -v brew &>/dev/null; then
echo -e " Install with Homebrew? ${DIM}(recommended)${NC}"
read -rp " [Y/n] " yn
yn=${yn:-Y}
if [[ "$yn" =~ ^[Yy] ]]; then
if $DRY_RUN; then
dry "Would run: brew install jq"
else
echo " Installing jq..."
brew install jq
success "jq installed"
fi
else
error "jq is required. Install it manually:"
echo " brew install jq"
echo " # or: sudo apt-get install jq"
echo " # or: https://jqlang.github.io/jq/download/"
exit 1
fi
else
error "jq is required but not installed."
echo ""
echo " Install jq:"
echo " macOS: brew install jq"
echo " Ubuntu/Debian: sudo apt-get install jq"
echo " Other: https://jqlang.github.io/jq/download/"
exit 1
fi
else
success "jq found: $(jq --version)"
fi
# Check for clawdbot CLI
if ! command -v clawdbot &>/dev/null; then
# Try openclaw or moltbot
if command -v openclaw &>/dev/null; then
alias clawdbot=openclaw
success "openclaw CLI found"
elif command -v moltbot &>/dev/null; then
alias clawdbot=moltbot
success "moltbot CLI found"
else
warn "clawdbot CLI not found in PATH"
detail "Index building will be skipped — run manually after install"
fi
else
success "clawdbot CLI found"
fi
}
# --- Check Existing Memory Files ---
check_existing() {
step "📂 Checking existing memory files..."
if [[ -d "$MEMORY_DIR" ]]; then
EXISTING_MEMORY_FILES=$(find "$MEMORY_DIR" -name "*.md" -type f 2>/dev/null | wc -l | tr -d ' ')
if [[ "$EXISTING_MEMORY_FILES" -gt 0 ]]; then
info "Found ${BOLD}${EXISTING_MEMORY_FILES}${NC} existing memory files in ${MEMORY_DIR}"
detail "These will be preserved and indexed"
else
info "Memory directory exists but is empty"
fi
else
info "No existing memory directory — will create one"
fi
# Check for MEMORY.md
if [[ -f "${WORKSPACE_DIR}/MEMORY.md" ]]; then
info "Found existing MEMORY.md — will be included in index"
fi
}
# --- Create Memory Directory & Templates ---
setup_memory_dir() {
step "📝 Setting up memory directory and templates..."
if $DRY_RUN; then
if [[ ! -d "$MEMORY_DIR" ]]; then
dry "Would create ${MEMORY_DIR}/"
fi
dry "Would copy template files to ${MEMORY_DIR}/"
return
fi
# Create memory directory
if [[ ! -d "$MEMORY_DIR" ]]; then
mkdir -p "$MEMORY_DIR"
success "Created ${MEMORY_DIR}/"
CHANGES_MADE+=("Created memory/ directory")
else
info "Memory directory already exists"
fi
# Copy templates (don't overwrite existing)
local script_dir
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
local templates_dir="${script_dir}/templates"
# If running from curl, download templates
if [[ ! -d "$templates_dir" ]]; then
local base_url="https://raw.githubusercontent.com/BusyBee3333/clawdbot-memory-system/main/templates"
templates_dir=$(mktemp -d)
for tmpl in TEMPLATE-daily.md TEMPLATE-research-intel.md TEMPLATE-project-tracking.md; do
curl -sL "${base_url}/${tmpl}" -o "${templates_dir}/${tmpl}" 2>/dev/null || true
done
fi
# Copy each template if it doesn't exist
for tmpl_file in "${templates_dir}"/TEMPLATE-*.md; do
[[ -f "$tmpl_file" ]] || continue
local basename
basename=$(basename "$tmpl_file")
if [[ ! -f "${MEMORY_DIR}/${basename}" ]]; then
cp "$tmpl_file" "${MEMORY_DIR}/${basename}"
success "Added template: ${basename}"
CHANGES_MADE+=("Added ${basename}")
else
detail "Template already exists: ${basename}"
fi
done
# Create today's daily log if none exists
local today
today=$(date +%Y-%m-%d)
if [[ ! -f "${MEMORY_DIR}/${today}.md" ]]; then
cat > "${MEMORY_DIR}/${today}.md" << 'DAILY'
# Daily Log — $(date +%Y-%m-%d)
## What We Worked On
- Set up Clawdbot Memory System 🧠
## Decisions Made
- Installed persistent memory to prevent context loss during compaction
## Next Steps
- Use the memory system naturally — agent will write daily logs
- Check `memory/` directory for accumulated context over time
## Open Questions / Blockers
-
## Notable Context
Memory system installed and indexed. Agent should now persist important context
across sessions automatically.
DAILY
# Fix the date in the file
sed -i.bak "s/\$(date +%Y-%m-%d)/${today}/g" "${MEMORY_DIR}/${today}.md" 2>/dev/null && rm -f "${MEMORY_DIR}/${today}.md.bak"
success "Created today's daily log: ${today}.md"
CHANGES_MADE+=("Created daily log ${today}.md")
fi
}
# --- Choose Embedding Provider ---
choose_provider() {
step "🤖 Choose your embedding provider..."
echo ""
echo -e " ${BOLD}1)${NC} ${GREEN}OpenAI${NC} ${DIM}(recommended — fast, cheap ~\$0.02/M tokens)${NC}"
echo -e " ${BOLD}2)${NC} ${BLUE}Gemini${NC} ${DIM}(free tier available)${NC}"
echo -e " ${BOLD}3)${NC} ${YELLOW}Local${NC} ${DIM}(free, offline, slower first run)${NC}"
echo ""
read -rp " Choose [1/2/3] (default: 1): " choice
choice=${choice:-1}
case "$choice" in
1) PROVIDER="openai" ;;
2) PROVIDER="gemini" ;;
3) PROVIDER="local" ;;
*)
warn "Invalid choice, defaulting to OpenAI"
PROVIDER="openai"
;;
esac
success "Selected: ${BOLD}${PROVIDER}${NC}"
# Prompt for API key if needed
if [[ "$PROVIDER" == "openai" ]]; then
if [[ -n "${OPENAI_API_KEY:-}" ]]; then
info "Found OPENAI_API_KEY in environment"
else
echo ""
echo -e " ${DIM}OpenAI API key is needed for embeddings.${NC}"
echo -e " ${DIM}Get one at: https://platform.openai.com/api-keys${NC}"
echo -e " ${DIM}(Press Enter to skip — you can set it later as OPENAI_API_KEY)${NC}"
echo ""
read -rsp " OpenAI API Key: " API_KEY
echo ""
if [[ -n "$API_KEY" ]]; then
success "API key provided"
else
warn "No API key provided — set OPENAI_API_KEY env var before using memory search"
fi
fi
elif [[ "$PROVIDER" == "gemini" ]]; then
if [[ -n "${GEMINI_API_KEY:-}" ]]; then
info "Found GEMINI_API_KEY in environment"
else
echo ""
echo -e " ${DIM}Gemini API key is needed for embeddings.${NC}"
echo -e " ${DIM}Get one at: https://aistudio.google.com/apikey${NC}"
echo -e " ${DIM}(Press Enter to skip — you can set it later as GEMINI_API_KEY)${NC}"
echo ""
read -rsp " Gemini API Key: " API_KEY
echo ""
if [[ -n "$API_KEY" ]]; then
success "API key provided"
else
warn "No API key provided — set GEMINI_API_KEY env var before using memory search"
fi
fi
fi
}
# --- Patch clawdbot.json ---
patch_config() {
step "⚙️ Patching clawdbot.json..."
# Check if memorySearch already configured
local existing_provider
existing_provider=$(jq -r '.agents.defaults.memorySearch.provider // empty' "$CONFIG_FILE" 2>/dev/null || true)
if [[ -n "$existing_provider" ]]; then
info "memorySearch already configured (provider: ${existing_provider})"
echo ""
read -rp " Overwrite with new provider ($PROVIDER)? [y/N] " yn
yn=${yn:-N}
if [[ ! "$yn" =~ ^[Yy] ]]; then
info "Keeping existing config"
return
fi
fi
if $DRY_RUN; then
dry "Would back up ${CONFIG_FILE}${CONFIG_FILE}.pre-memory-backup"
dry "Would add memorySearch config (provider: ${PROVIDER})"
if [[ -n "$API_KEY" ]]; then
dry "Would add API key to config"
fi
return
fi
# Back up config
cp "$CONFIG_FILE" "${CONFIG_FILE}.pre-memory-backup"
success "Backed up config → ${CONFIG_FILE}.pre-memory-backup"
# Build the memorySearch config based on provider
local memory_config
case "$PROVIDER" in
openai)
memory_config='{"provider":"openai","model":"text-embedding-3-small"}'
if [[ -n "$API_KEY" ]]; then
memory_config=$(echo "$memory_config" | jq --arg key "$API_KEY" '. + {remote: {apiKey: $key}}')
fi
;;
gemini)
memory_config='{"provider":"gemini","model":"gemini-embedding-001"}'
if [[ -n "$API_KEY" ]]; then
memory_config=$(echo "$memory_config" | jq --arg key "$API_KEY" '. + {remote: {apiKey: $key}}')
fi
;;
local)
memory_config='{"provider":"local"}'
;;
esac
# Merge into config using jq (safe, non-destructive)
local tmp_file
tmp_file=$(mktemp)
jq --argjson ms "$memory_config" '
.agents.defaults.memorySearch = (
(.agents.defaults.memorySearch // {}) * $ms
)
' "$CONFIG_FILE" > "$tmp_file"
# Validate the result is valid JSON
if jq empty "$tmp_file" 2>/dev/null; then
mv "$tmp_file" "$CONFIG_FILE"
success "Added memorySearch config (provider: ${PROVIDER})"
CHANGES_MADE+=("Patched clawdbot.json with memorySearch (${PROVIDER})")
else
rm -f "$tmp_file"
error "Failed to patch config — restoring backup"
cp "${CONFIG_FILE}.pre-memory-backup" "$CONFIG_FILE"
exit 1
fi
}
# --- Patch AGENTS.md ---
patch_agents() {
step "📋 Updating AGENTS.md with memory instructions..."
# Check if already patched
if [[ -f "$AGENTS_FILE" ]] && grep -q "memory_search\|Daily memory log\|Pre-compaction flush" "$AGENTS_FILE" 2>/dev/null; then
info "AGENTS.md already contains memory instructions"
return
fi
if $DRY_RUN; then
dry "Would append memory instructions to ${AGENTS_FILE}"
return
fi
# Get the patch content
local script_dir
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
local patch_file="${script_dir}/config/agents-memory-patch.md"
local patch_content
if [[ -f "$patch_file" ]]; then
patch_content=$(cat "$patch_file")
else
# Download if running from curl
patch_content=$(curl -sL "https://raw.githubusercontent.com/BusyBee3333/clawdbot-memory-system/main/config/agents-memory-patch.md" 2>/dev/null || true)
fi
if [[ -z "$patch_content" ]]; then
# Fallback: inline the patch
patch_content='
## Memory System (auto-added by clawdbot-memory-system installer)
### Mandatory Memory Recall
Before answering ANY question about prior work, decisions, or context from previous sessions:
1. Use `memory_search` to find relevant memories
2. Check today'\''s daily log: `memory/YYYY-MM-DD.md`
3. Check yesterday'\''s log if today'\''s is sparse
4. Only say "I don'\''t recall" if memory search returns nothing
### Daily Memory Log
- Write to `memory/YYYY-MM-DD.md` throughout the session
- Log: decisions, preferences, project progress, action items, blockers
- Be specific — future-you needs exact details, not vague summaries
### Pre-Compaction Flush
When you sense a session is getting long or receive a compaction warning:
- Write ALL important unsaved context to today'\''s daily log
- Include: what we were working on, where we left off, any pending decisions
- This is your safety net against amnesia
### Research Intel System
For ongoing research/monitoring projects:
- Store in: `memory/{project}-research-intel.md`
- Current week'\''s detailed intel at TOP
- Compressed 1-3 sentence summaries of previous weeks at BOTTOM
- Check for active research intel files on strategic questions
### Git Backup
End of session: `cd ~/.clawdbot/workspace && git add -A && git commit -m "session backup" && git push`
'
fi
if [[ -f "$AGENTS_FILE" ]]; then
echo "" >> "$AGENTS_FILE"
echo "$patch_content" >> "$AGENTS_FILE"
else
echo "$patch_content" > "$AGENTS_FILE"
fi
success "Added memory instructions to AGENTS.md"
CHANGES_MADE+=("Updated AGENTS.md with memory habits")
}
# --- Build Index ---
build_index() {
step "🔨 Building memory search index..."
if $DRY_RUN; then
dry "Would run: clawdbot memory index --verbose"
dry "Would run: clawdbot memory status --deep"
return
fi
if ! command -v clawdbot &>/dev/null; then
warn "clawdbot CLI not in PATH — skipping index build"
detail "Run manually: clawdbot memory index --verbose"
return
fi
echo ""
info "Indexing memory files..."
echo -e "${DIM}"
if clawdbot memory index --verbose 2>&1; then
echo -e "${NC}"
success "Index built successfully"
else
echo -e "${NC}"
warn "Index build had issues (this may be normal on first run)"
detail "Check: clawdbot memory status --deep"
fi
echo ""
info "Verifying installation..."
echo -e "${DIM}"
if clawdbot memory status --deep 2>&1; then
echo -e "${NC}"
success "Memory system verified"
else
echo -e "${NC}"
warn "Status check had warnings (embedding provider may need API key)"
fi
# Count indexed files
FILES_INDEXED=$(find "$MEMORY_DIR" -name "*.md" -type f 2>/dev/null | wc -l | tr -d ' ')
if [[ -f "${WORKSPACE_DIR}/MEMORY.md" ]]; then
FILES_INDEXED=$((FILES_INDEXED + 1))
fi
}
# --- Print Summary ---
print_summary() {
echo ""
echo -e "${BOLD}${GREEN}"
echo " ╔══════════════════════════════════════════════╗"
echo " ║ 🎉 Installation Complete! ║"
echo " ╚══════════════════════════════════════════════╝"
echo -e "${NC}"
if [[ ${#CHANGES_MADE[@]} -gt 0 ]]; then
echo -e " ${BOLD}Changes made:${NC}"
for change in "${CHANGES_MADE[@]}"; do
echo -e " ${GREEN}${NC} ${change}"
done
echo ""
fi
if [[ "$EXISTING_MEMORY_FILES" -gt 0 ]]; then
echo -e " ${BOLD}Migration:${NC}"
echo -e " 📁 ${EXISTING_MEMORY_FILES} existing memory files preserved and indexed"
echo ""
fi
echo -e " ${BOLD}Index:${NC}"
echo -e " 📊 ${FILES_INDEXED} memory files indexed"
echo -e " 🤖 Provider: ${PROVIDER}"
echo ""
echo -e " ${BOLD}${CYAN}Next steps:${NC}"
echo ""
echo -e " ${BOLD}1.${NC} Restart the gateway to apply config changes:"
echo -e " ${DIM}clawdbot gateway restart${NC}"
echo ""
echo -e " ${BOLD}2.${NC} Start chatting! Your agent will now:"
echo -e " • Write daily logs to memory/${DIM}YYYY-MM-DD${NC}.md"
echo -e " • Search memories before answering about prior work"
echo -e " • Flush context before compaction"
echo ""
echo -e " ${BOLD}3.${NC} Verify anytime with:"
echo -e " ${DIM}clawdbot memory status --deep${NC}"
echo ""
if [[ -n "$API_KEY" ]]; then
echo -e " ${YELLOW}⚠️ Your API key was saved to clawdbot.json.${NC}"
echo -e " ${DIM} Alternatively, set it as an env var and remove from config.${NC}"
echo ""
fi
echo -e " ${DIM}Problems? See: https://github.com/BusyBee3333/clawdbot-memory-system#troubleshooting${NC}"
echo ""
}
# --- Print Dry Run Summary ---
print_dry_summary() {
echo ""
echo -e "${BOLD}${CYAN}"
echo " ╔══════════════════════════════════════════════╗"
echo " ║ 📋 Dry Run Summary ║"
echo " ╚══════════════════════════════════════════════╝"
echo -e "${NC}"
echo ""
echo -e " No changes were made. Run without ${CYAN}--dry-run${NC} to apply."
echo ""
}
# --- Uninstall ---
do_uninstall() {
banner
step "🗑️ Uninstalling Clawdbot Memory System..."
detect_clawdbot
echo ""
warn "This will:"
echo " • Remove memorySearch config from clawdbot.json"
echo " • Remove memory instructions from AGENTS.md"
echo ""
echo -e " ${BOLD}This will NOT delete your memory/ files.${NC}"
echo " Your memories are safe — only the config is removed."
echo ""
read -rp " Continue? [y/N] " yn
yn=${yn:-N}
if [[ ! "$yn" =~ ^[Yy] ]]; then
info "Cancelled"
exit 0
fi
# Remove memorySearch from config
if [[ -f "$CONFIG_FILE" ]] && jq -e '.agents.defaults.memorySearch' "$CONFIG_FILE" &>/dev/null; then
cp "$CONFIG_FILE" "${CONFIG_FILE}.pre-uninstall-backup"
local tmp_file
tmp_file=$(mktemp)
jq 'del(.agents.defaults.memorySearch)' "$CONFIG_FILE" > "$tmp_file"
if jq empty "$tmp_file" 2>/dev/null; then
mv "$tmp_file" "$CONFIG_FILE"
success "Removed memorySearch from config"
else
rm -f "$tmp_file"
error "Failed to patch config"
fi
else
info "No memorySearch config found"
fi
# Remove memory instructions from AGENTS.md
if [[ -f "$AGENTS_FILE" ]]; then
if grep -q "Memory System (auto-added by clawdbot-memory-system installer)" "$AGENTS_FILE" 2>/dev/null; then
cp "$AGENTS_FILE" "${AGENTS_FILE}.pre-uninstall-backup"
# Remove everything from the memory system header to the end of that section
sed -i.bak '/## Memory System (auto-added by clawdbot-memory-system installer)/,$ { /## Memory System (auto-added by clawdbot-memory-system installer)/d; /^## [^M]/!d; }' "$AGENTS_FILE" 2>/dev/null
# Simpler approach: use python to remove the section
python3 -c "
import re
with open('${AGENTS_FILE}') as f:
content = f.read()
# Remove the auto-added section
pattern = r'\n*## Memory System \(auto-added by clawdbot-memory-system installer\).*'
content = re.sub(pattern, '', content, flags=re.DOTALL)
with open('${AGENTS_FILE}', 'w') as f:
f.write(content.rstrip() + '\n')
" 2>/dev/null || true
rm -f "${AGENTS_FILE}.bak"
success "Removed memory instructions from AGENTS.md"
else
info "No auto-added memory instructions found in AGENTS.md"
fi
fi
echo ""
success "Uninstall complete"
echo ""
echo -e " ${DIM}Your memory/ files were preserved.${NC}"
echo -e " ${DIM}Config backups saved as .pre-uninstall-backup files.${NC}"
echo -e " ${DIM}Run 'clawdbot gateway restart' to apply changes.${NC}"
echo ""
exit 0
}
# ============================================================================
# Main Flow
# ============================================================================
# Handle uninstall
if $UNINSTALL; then
do_uninstall
fi
# Banner
banner
if $DRY_RUN; then
echo -e " ${CYAN}${BOLD}Running in dry-run mode — no changes will be made${NC}"
echo ""
fi
# Step 1: Detect Clawdbot
detect_clawdbot
# Step 2: Check dependencies
check_deps
# Step 3: Check existing files
check_existing
# Step 4: Choose provider
choose_provider
# Step 5: Set up memory directory
setup_memory_dir
# Step 6: Patch clawdbot.json
patch_config
# Step 7: Patch AGENTS.md
patch_agents
# Step 8: Build index
build_index
# Step 9: Summary
if $DRY_RUN; then
print_dry_summary
else
print_summary
fi
]]>