#!/usr/bin/env bash # ============================================================================== # remove.sh — Multi-Agent Mux (MAM) Orchestration Uninstaller # ============================================================================== # Safely removes MAM orchestration skills, virtual environment, and metadata. # Leaves pre-existing user configurations and files untouched by reading # the installation manifest (.mam/install_manifest.txt). # ============================================================================== set -euo pipefail TARGET_DIR="" FORCE=0 PURGE_ENV=0 # Parse arguments while [[ $# -gt 0 ]]; do case "$1" in -y|--yes|--force) FORCE=1 shift ;; --purge-env) PURGE_ENV=1 shift ;; *) TARGET_DIR="$1" shift ;; esac done if [ -z "$TARGET_DIR" ]; then TARGET_DIR="$(pwd)" fi echo "====================================================================" echo "⚡ Starting Multi-Agent Mux (MAM) Uninstallation" echo "📂 Target Workspace: $TARGET_DIR" echo "====================================================================" if [ ! -d "$TARGET_DIR" ]; then echo "❌ Error: Target directory '$TARGET_DIR' does not exist." >&2 exit 1 fi cd "$TARGET_DIR" # 1. Non-interactive input safety guard (set -e read crash prevention) if [ ! -t 0 ] && [ $FORCE -eq 0 ]; then echo "❌ Error: Non-interactive terminal detected. Please run with -y/--yes/--force." >&2 exit 1 fi # Check if there is anything to remove MANIFEST_FILE=".mam/install_manifest.txt" any_exist=0 manifest_files=() # Load the install manifest if it exists if [ -f "$MANIFEST_FILE" ]; then any_exist=1 while IFS= read -r line; do if [ -n "$line" ]; then manifest_files+=("$line") fi done < "$MANIFEST_FILE" else # Fallback to the core MAM directories to check if any exist fallback_assets=( ".agents/skills/lib.sh" ".agents/skills/multi-agent-mux-create" ".agents/skills/multi-agent-mux-delegate-job" ".agents/skills/multi-agent-mux-monitor" ".agents/skills/multi-agent-mux-resume" ".agents/skills/multi-agent-mux-status" ".agents/skills/multi-agent-mux-stop" ".venv" ".mam" ) for asset in "${fallback_assets[@]}"; do if [ -e "$asset" ] || [ -h "$asset" ]; then any_exist=1 break fi done fi if [ $any_exist -eq 0 ]; then echo "â„šī¸ No MAM assets detected in '$TARGET_DIR'. Nothing to do." exit 0 fi # Request confirmation if not forced if [ $FORCE -eq 0 ]; then echo "âš ī¸ WARNING: This will permanently remove the MAM orchestration skills, " echo " virtual environment (.venv), local metadata (.mam), and docs." echo " (Your own custom files inside .agents/ will NOT be touched)." if ! read -p "❓ Are you sure you want to proceed? [y/N]: " -r response; then response="n" fi if [[ ! "$response" =~ ^[yY](es)?$ ]]; then echo "❌ Uninstallation cancelled by user." exit 0 fi fi delete_asset() { local asset="$1" if [ -e "$asset" ] || [ -h "$asset" ]; then echo "đŸ—‘ī¸ Removing: $asset" rm -rf "$asset" fi } # 2. Uninstall files using the manifest if present if [ ${#manifest_files[@]} -gt 0 ]; then echo "📜 Manifest found. Reversing installer-created files..." for f in ${manifest_files[@]+"${manifest_files[@]}"}; do # Skip .env and remove.sh for now, they are handled separately if [ "$f" = ".env" ] || [ "$f" = "remove.sh" ]; then continue fi delete_asset "$f" done else # Fallback: Delete MAM skills manually (only if manifest is missing) echo "âš ī¸ No manifest found. Deleting standard MAM skills..." delete_asset ".agents/skills/lib.sh" delete_asset ".agents/skills/multi-agent-mux-create" delete_asset ".agents/skills/multi-agent-mux-delegate-job" delete_asset ".agents/skills/multi-agent-mux-monitor" delete_asset ".agents/skills/multi-agent-mux-resume" delete_asset ".agents/skills/multi-agent-mux-status" delete_asset ".agents/skills/multi-agent-mux-stop" fi # 3. Clean up empty parent directories under .agents recursively to avoid littering if [ -d ".agents" ]; then find .agents -depth -type d -exec rmdir {} + 2>/dev/null || true fi # 4. Remove virtual environment, monitor cache, and metadata database delete_asset ".venv" delete_asset ".cache/multi-agent-mux-monitor" delete_asset ".mam" # Deletes manifest file too # 5. Clean up .env file (Only if created by installer, or forced with --purge-env) # If .env is in manifest, it means MAM created it. env_created_by_mam=0 for f in ${manifest_files[@]+"${manifest_files[@]}"}; do if [ "$f" = ".env" ]; then env_created_by_mam=1 break fi done if [ -f ".env" ]; then should_delete_env=0 if [ $PURGE_ENV -eq 1 ]; then should_delete_env=1 elif [ $env_created_by_mam -eq 1 ]; then # Even if MAM created it, ask or rename to backup to prevent loss of custom secrets if [ $FORCE -eq 1 ]; then should_delete_env=1 else if ! read -p "❓ MAM-created '.env' found. Delete it? (Saying No preserves it) [y/N]: " -r env_response; then env_response="n" fi if [[ "$env_response" =~ ^[yY](es)?$ ]]; then should_delete_env=1 fi fi fi if [ $should_delete_env -eq 1 ]; then delete_asset ".env" else if [ $env_created_by_mam -eq 1 ]; then backup_name=".env.mam-backup" if [ -e "$backup_name" ]; then backup_name=".env.mam-backup.$(date +%Y%m%d%H%M%S)" fi echo "💾 Backing up .env configuration to $backup_name..." mv ".env" "$backup_name" else echo "â„šī¸ Preserving user-owned .env configuration." fi fi fi # 6. Remove uninstaller file itself (if we are in the target root) # Simple check: only delete remove.sh if it is recorded in the manifest remove_in_manifest=0 for f in ${manifest_files[@]+"${manifest_files[@]}"}; do if [ "$f" = "remove.sh" ]; then remove_in_manifest=1 break fi done if [ -f "remove.sh" ] && [ $remove_in_manifest -eq 1 ]; then echo "đŸ—‘ī¸ Removing uninstaller: remove.sh" # Self-delete is the final action rm -f "remove.sh" fi echo "====================================================================" echo "🎉 Uninstallation complete!" echo "===================================================================="