diff --git a/README.md b/README.md index 1dcf5aa..ef13dc1 100644 --- a/README.md +++ b/README.md @@ -64,14 +64,14 @@ mo --version # Show installed version ## Quick Launchers -Generate Spotlight / Shortcuts launchers with one command: +One command sets up Raycast + Alfred shortcuts for `mo clean` and `mo uninstall`: ```bash -curl -fsSL https://raw.githubusercontent.com/tw93/mole/main/integrations/setup-shortcut-apps.sh | bash +curl -fsSL https://raw.githubusercontent.com/tw93/mole/main/integrations/setup-quick-launchers.sh | bash ``` -This drops tiny apps such as “Mole Clean” into `~/Applications` so you can trigger them from Spotlight, Dock, or the Shortcuts app. -For Alfred, Shortcuts details, and more, see [integrations/README.md](integrations/README.md). +Done! Raycast gets “Clean Mac / Uninstall Apps”, Alfred gets `mclean / muninstall`. +Details and manual options live in [integrations/README.md](integrations/README.md). ## Features in Detail diff --git a/integrations/README.md b/integrations/README.md index 2cb50d5..80f05f7 100644 --- a/integrations/README.md +++ b/integrations/README.md @@ -2,22 +2,17 @@ Quick launcher integrations for Mole. -## Shortcut Apps (Spotlight & Shortcuts) - -Generate ready-to-use launcher apps (Clean / Dry Run / Uninstall): +## Raycast + Alfred (clean & uninstall) ```bash -curl -fsSL https://raw.githubusercontent.com/tw93/Mole/main/integrations/setup-shortcut-apps.sh | bash +curl -fsSL https://raw.githubusercontent.com/tw93/Mole/main/integrations/setup-quick-launchers.sh | bash ``` -This drops them into `~/Applications`, so you can trigger Mole via Spotlight, Dock, or Shortcuts (“Open App” action). -Prefer to craft your own shortcut? Add “Run Shell Script”: +This command: -```bash -mo clean -``` - -Dry run: `mo clean --dry-run` • Uninstall: `mo uninstall` +- Adds two Raycast Script Commands (`Clean Mac`, `Uninstall Apps`) to the usual Raycast directories and opens the Script Commands panel so you can reload immediately. +- Creates two Alfred workflows with keywords `mclean` and `muninstall` so you can type and run Mole in Alfred. +Both launchers call your locally installed `mo`/`mole` binary directly—no extra prompts or AppleScript permissions needed. ## Alfred @@ -34,9 +29,8 @@ For uninstall: `mo uninstall` ## Uninstall ```bash -rm -rf ~/Applications/Mole\ Clean*.app -rm -rf ~/Applications/Mole\ Uninstall\ Apps.app -# Legacy Raycast script commands (if you installed them before switching) rm -rf ~/Documents/Raycast/Scripts/mole-*.sh rm -rf ~/Library/Application\ Support/Raycast/script-commands/mole-*.sh +# Alfred workflows live in: +# ~/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.* ``` diff --git a/integrations/raycast/mole-clean-dry-run.sh b/integrations/raycast/mole-clean-dry-run.sh deleted file mode 100755 index a6f12be..0000000 --- a/integrations/raycast/mole-clean-dry-run.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash - -# Required parameters: -# @raycast.schemaVersion 1 -# @raycast.title Clean Mac (Dry Run) -# @raycast.mode fullOutput -# @raycast.packageName Mole - -# Optional parameters: -# @raycast.icon 👀 -# @raycast.needsConfirmation false - -# Documentation: -# @raycast.description Preview what Mole would clean without making changes -# @raycast.author tw93 -# @raycast.authorURL https://github.com/tw93/Mole - -# Detect mo/mole installation -if command -v mo >/dev/null 2>&1; then - MO_BIN="mo" -elif command -v mole >/dev/null 2>&1; then - MO_BIN="mole" -else - echo "❌ Mole not found. Install from:" - echo " https://github.com/tw93/Mole" - exit 1 -fi - -# Run dry-run -echo "👀 Previewing cleanup..." -echo "" -"$MO_BIN" clean --dry-run diff --git a/integrations/raycast/mole-clean.sh b/integrations/raycast/mole-clean.sh deleted file mode 100755 index 7ee0261..0000000 --- a/integrations/raycast/mole-clean.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash - -# Required parameters: -# @raycast.schemaVersion 1 -# @raycast.title Clean Mac -# @raycast.mode fullOutput -# @raycast.packageName Mole - -# Optional parameters: -# @raycast.icon 🐹 -# @raycast.needsConfirmation true - -# Documentation: -# @raycast.description Deep clean your Mac using Mole -# @raycast.author tw93 -# @raycast.authorURL https://github.com/tw93/Mole - -# Detect mo/mole installation -if command -v mo >/dev/null 2>&1; then - MO_BIN="mo" -elif command -v mole >/dev/null 2>&1; then - MO_BIN="mole" -else - echo "❌ Mole not found. Install from:" - echo " https://github.com/tw93/Mole" - exit 1 -fi - -# Run cleanup -echo "🐹 Starting cleanup..." -echo "" -"$MO_BIN" clean diff --git a/integrations/raycast/mole-uninstall.sh b/integrations/raycast/mole-uninstall.sh deleted file mode 100755 index 8ae9b37..0000000 --- a/integrations/raycast/mole-uninstall.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash - -# Required parameters: -# @raycast.schemaVersion 1 -# @raycast.title Uninstall Apps -# @raycast.mode fullOutput -# @raycast.packageName Mole - -# Optional parameters: -# @raycast.icon 🗑️ -# @raycast.needsConfirmation true - -# Documentation: -# @raycast.description Completely uninstall apps using Mole -# @raycast.author tw93 -# @raycast.authorURL https://github.com/tw93/Mole - -# Detect mo/mole installation -if command -v mo >/dev/null 2>&1; then - MO_BIN="mo" -elif command -v mole >/dev/null 2>&1; then - MO_BIN="mole" -else - echo "❌ Mole not found. Install from:" - echo " https://github.com/tw93/Mole" - exit 1 -fi - -# Run uninstall -echo "🗑️ Starting app uninstaller..." -echo "" -"$MO_BIN" uninstall diff --git a/integrations/setup-quick-launchers.sh b/integrations/setup-quick-launchers.sh new file mode 100644 index 0000000..80c0e70 --- /dev/null +++ b/integrations/setup-quick-launchers.sh @@ -0,0 +1,235 @@ +#!/bin/bash +# Create Raycast script commands and Alfred keywords for Mole (clean + uninstall). + +set -euo pipefail + +BLUE='\033[0;34m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +RED='\033[0;31m' +NC='\033[0m' + +ICON_STEP="➜" +ICON_SUCCESS="✓" +ICON_WARN="!" +ICON_ERR="✗" + +log_step() { echo -e "${BLUE}${ICON_STEP}${NC} $1"; } +log_success() { echo -e "${GREEN}${ICON_SUCCESS}${NC} $1"; } +log_warn() { echo -e "${YELLOW}${ICON_WARN}${NC} $1"; } +log_error() { echo -e "${RED}${ICON_ERR}${NC} $1"; } + +detect_mo() { + if command -v mo >/dev/null 2>&1; then + command -v mo + elif command -v mole >/dev/null 2>&1; then + command -v mole + else + log_error "Mole not found. Install it first via Homebrew or ./install.sh." + exit 1 + fi +} + +write_raycast_script() { + local target="$1" + local title="$2" + local command="$3" + cat > "$target" < /dev/null 2>&1; then + log_step "Raycast settings opened. Run “Reload Script Directories”." + else + log_warn "Could not auto-open Raycast. Open it manually to reload scripts." + fi +} + +uuid() { + if command -v uuidgen >/dev/null 2>&1; then + uuidgen + else + # Fallback pseudo UUID + openssl rand -hex 16 | sed 's/\(..\)/\1/g' | cut -c1-32 + fi +} + +create_alfred_workflow() { + local mo_bin="$1" + local prefs_dir="${ALFRED_PREFS_DIR:-$HOME/Library/Application Support/Alfred/Alfred.alfredpreferences}" + local workflows_dir="$prefs_dir/workflows" + + if [[ ! -d "$workflows_dir" ]]; then + log_warn "Alfred preferences not found at $workflows_dir. Skipping Alfred workflow." + return + fi + + log_step "Installing Alfred workflows..." + local workflows=( + "fun.tw93.mole.clean|Mole Clean|mclean|Run Mole clean|\"${mo_bin}\" clean" + "fun.tw93.mole.uninstall|Mole Uninstall|muninstall|Uninstall apps via Mole|\"${mo_bin}\" uninstall" + ) + + for entry in "${workflows[@]}"; do + IFS="|" read -r bundle name keyword subtitle command <<< "$entry" + local workflow_uid="user.workflow.$(uuid | tr '[:upper:]' '[:lower:]')" + local input_uid + local action_uid + input_uid="$(uuid)" + action_uid="$(uuid)" + local dir="$workflows_dir/$workflow_uid" + mkdir -p "$dir" + + cat > "$dir/info.plist" < + + + + bundleid + ${bundle} + createdby + Mole + name + ${name} + objects + + + config + + argumenttype + 2 + keyword + ${keyword} + subtext + ${subtitle} + text + ${name} + withspace + + + type + alfred.workflow.input.keyword + uid + ${input_uid} + version + 1 + + + config + + concurrently + + escaping + 102 + script + #!/bin/bash +PATH="/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin" +${command} + + scriptargtype + 1 + scriptfile + + type + 0 + + type + alfred.workflow.action.script + uid + ${action_uid} + version + 2 + + + connections + + ${input_uid} + + + destinationuid + ${action_uid} + modifiers + 0 + modifiersubtext + + + + + uid + ${workflow_uid} + version + 1 + + +EOF + log_success "Workflow ready: ${name} (keyword: ${keyword})" + done + + log_step "Open Alfred preferences → Workflows if you need to adjust keywords." +} + +main() { + echo "" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo " Mole Quick Launchers" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + + local mo_bin + mo_bin="$(detect_mo)" + log_step "Detected Mole binary at: ${mo_bin}" + + create_raycast_commands "$mo_bin" + create_alfred_workflow "$mo_bin" + + echo "" + log_success "Done! Raycast (search “Clean Mac”) and Alfred (keywords: mclean / muninstall) are ready." + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo "" +} + +main "$@" diff --git a/integrations/setup-raycast.sh b/integrations/setup-raycast.sh deleted file mode 100755 index fb00527..0000000 --- a/integrations/setup-raycast.sh +++ /dev/null @@ -1,76 +0,0 @@ -#!/bin/bash -# One-line Raycast integration installer -# Usage: curl -fsSL https://raw.githubusercontent.com/tw93/Mole/main/integrations/setup-raycast.sh | bash - -set -euo pipefail - -BLUE='\033[0;34m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -RED='\033[0;31m' -NC='\033[0m' - -ICON_STEP="➜" -ICON_SUCCESS="✓" -ICON_WARN="!" -ICON_ERR="✗" - -log_step() { echo -e "${BLUE}${ICON_STEP}${NC} $1"; } -log_success() { echo -e "${GREEN}${ICON_SUCCESS}${NC} $1"; } -log_warn() { echo -e "${YELLOW}${ICON_WARN}${NC} $1"; } -log_error() { echo -e "${RED}${ICON_ERR}${NC} $1"; } - -DEFAULT_DIR="$HOME/Library/Application Support/Raycast/script-commands" -ALT_DIR="$HOME/Documents/Raycast/Scripts" -RAYCAST_DIRS=() - -if [[ -d "$DEFAULT_DIR" ]]; then - RAYCAST_DIRS+=("$DEFAULT_DIR") -fi -if [[ -d "$ALT_DIR" ]]; then - RAYCAST_DIRS+=("$ALT_DIR") -fi -if [[ ${#RAYCAST_DIRS[@]} -eq 0 ]]; then - RAYCAST_DIRS+=("$DEFAULT_DIR") -fi - -BASE_URL="https://raw.githubusercontent.com/tw93/Mole/main/integrations/raycast" -SCRIPTS=(mole-clean.sh mole-clean-dry-run.sh mole-uninstall.sh) - -echo "" -echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -echo " Mole × Raycast Script Commands" -echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" - -log_step "Checking Raycast installation..." -if [[ ! -d "/Applications/Raycast.app" ]]; then - log_warn "Raycast not found. Install it from https://raycast.com" - exit 1 -fi - -log_step "Syncing scripts (${#SCRIPTS[@]}) to Raycast directories..." -for dir in "${RAYCAST_DIRS[@]}"; do - mkdir -p "$dir" - for script in "${SCRIPTS[@]}"; do - curl -fsSL "$BASE_URL/$script" -o "$dir/$script" - chmod +x "$dir/$script" - done - log_success "Scripts ready in: $dir" -done - -echo "" -log_success "All set! Next steps:" -cat < /dev/null 2>&1; then - log_step "Raycast settings opened so you can confirm the directory." -else - log_warn "Could not auto-open Raycast. Launch it manually if needed." -fi -echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -echo "" diff --git a/integrations/setup-shortcut-apps.sh b/integrations/setup-shortcut-apps.sh deleted file mode 100644 index a3b5506..0000000 --- a/integrations/setup-shortcut-apps.sh +++ /dev/null @@ -1,93 +0,0 @@ -#!/bin/bash -# Create double-clickable Mole launchers (works great with Spotlight & Shortcuts). - -set -euo pipefail - -BLUE='\033[0;34m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -RED='\033[0;31m' -NC='\033[0m' - -ICON_STEP="➜" -ICON_SUCCESS="✓" -ICON_WARN="!" -ICON_ERR="✗" - -log_step() { echo -e "${BLUE}${ICON_STEP}${NC} $1"; } -log_success() { echo -e "${GREEN}${ICON_SUCCESS}${NC} $1"; } -log_warn() { echo -e "${YELLOW}${ICON_WARN}${NC} $1"; } -log_error() { echo -e "${RED}${ICON_ERR}${NC} $1"; } - -if ! command -v osascript >/dev/null 2>&1 || ! command -v osacompile >/dev/null 2>&1; then - log_error "This installer needs AppleScript tools (osascript / osacompile). They ship with macOS." - exit 1 -fi - -# Resolve Mole executable -if command -v mo >/dev/null 2>&1; then - MO_BIN="$(command -v mo)" -elif command -v mole >/dev/null 2>&1; then - MO_BIN="$(command -v mole)" -else - log_error "Couldn't find Mole. Install via Homebrew or the install.sh script first." - exit 1 -fi - -APP_DIR_BASE="${APP_DIR_BASE:-$HOME/Applications}" -mkdir -p "$APP_DIR_BASE" - -declare -a ACTIONS=( - "Mole Clean|$MO_BIN clean|Run full clean with Mole" - "Mole Clean (Dry Run)|$MO_BIN clean --dry-run|Preview cleanup targets" - "Mole Uninstall Apps|$MO_BIN uninstall|Interactive app uninstaller" -) - -create_launcher() { - local name="$1" - local command="$2" - local description="$3" - local app_path="$APP_DIR_BASE/$name.app" - local tmp_scpt - - tmp_scpt="$(mktemp)" - # Escape backslashes and quotes for AppleScript literal - local escaped_cmd="${command//\\/\\\\}" - escaped_cmd="${escaped_cmd//\"/\\\"}" - - cat > "$tmp_scpt" </dev/null || true - /usr/bin/plutil -replace CFBundleDisplayName -string "$name" "$app_path/Contents/Info.plist" 2>/dev/null || true - log_success "Created ${name} → ${app_path}" - log_step "You can now launch it from Spotlight or add to macOS Shortcuts." - echo " ${description}" -} - -echo "" -echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -echo " Mole macOS Launcher Creator" -echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" - -log_step "Installing launchers into: $APP_DIR_BASE" -for entry in "${ACTIONS[@]}"; do - IFS="|" read -r name cmd desc <<< "$entry" - create_launcher "$name" "$cmd" "$desc" -done - -echo "" -log_step "Tip: open Shortcuts.app → New Shortcut → Add Action → 'Open App', then pick the launcher." -log_success "Done! Search Spotlight for “Mole Clean” to try it." -echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -echo ""