Declaw.me
macOS Non-interactive No downloads

Remove Clawbot, Moltbot, aka OpenClaw from your Mac.

One script. Copy. Paste. Run. It deletes shims, launch agents, state folders, and the sneaky shell hook that triggers OpenClaw on every terminal start.

Heads up: This targets user-space installs. It will not prompt for sudo. If you installed OpenClaw system-wide, you can still remove the leftovers manually after.
Cleans the root cause
Removes the .zshrc auto-run completion hook.
Stops shim resurrection
Deletes nodenv version binaries before nodenv rehash.
Gets rid of the residue
Removes state/config/cache folders commonly used by OpenClaw.
declaw.sh Β· OpenClaw removal script
#!/usr/bin/env zsh
set -euo pipefail

# ==========================================
# declaw.sh β€” 🦞 OpenClaw Nuke (non-interactive)
# Colourful logs + in-place progress bar + emojis
# Steps include official uninstall guide:
# https://docs.openclaw.ai/install/uninstall
# ==========================================

autoload -Uz colors && colors

LOG="${HOME}/.openclaw_nuke_$(date +%Y%m%d_%H%M%S).log"
exec > >(tee -a "$LOG") 2>&1

# ---------- Pretty log helpers ----------
ok()   { print -P "%F{green}βœ…%f $*"; }
info() { print -P "%F{cyan}ℹ️%f  $*"; }
warn() { print -P "%F{yellow}⚠️%f  $*"; }
err()  { print -P "%F{red}πŸ›‘%f  $*"; }

# ---------- In-place progress bar ----------
PROGRESS_TOTAL=1
PROGRESS_CURRENT=0
PROGRESS_WIDTH=32

progress_init() {
  PROGRESS_TOTAL="$1"
  PROGRESS_CURRENT=0
  print -n $'\e[?25l'
}

progress_step() {
  local label="$1"
  PROGRESS_CURRENT=$((PROGRESS_CURRENT + 1))

  local filled=$(( PROGRESS_CURRENT * PROGRESS_WIDTH / PROGRESS_TOTAL ))
  local empty=$(( PROGRESS_WIDTH - filled ))
  local percent=$(( PROGRESS_CURRENT * 100 / PROGRESS_TOTAL ))

  local bar_filled bar_empty
  bar_filled=$(printf "%${filled}s" "" | tr " " "β–ˆ")
  bar_empty=$(printf "%${empty}s" "" | tr " " "β–‘")

  print -Pn "\r%F{magenta}🦞%f [%F{green}${bar_filled}%f%F{white}${bar_empty}%f] %F{cyan}${percent}%%%f %F{white}${label}%f"
}

progress_done() {
  print -n "\n"
  print -n $'\e[?25h'
}

cleanup() {
  print -n $'\e[?25h' >/dev/null 2>&1 || true
}
trap cleanup EXIT

backup_file() {
  local f="$1"
  if [[ -f "$f" ]]; then
    local b="${f}.bak.$(date +%Y%m%d_%H%M%S)"
    cp -p "$f" "$b"
    ok "Backed up $f -> $b 🧷"
  fi
}

safe_rm() {
  local target="$1"
  if [[ -e "$target" || -L "$target" ]]; then
    rm -rf -- "$target"
    ok "Removed: $target 🧨"
  else
    info "Not found: $target"
  fi
}

remove_zshrc_hook() {
  local zshrc="${HOME}/.zshrc"
  [[ -f "$zshrc" ]] || { info "No ~/.zshrc found (skipping)"; return 0; }

  backup_file "$zshrc"
  local tmp="${zshrc}.tmp.$$"

  awk '
    BEGIN { IGNORECASE=1 }
    {
      line=$0
      if (line ~ /openclaw[[:space:]]+completion/) next
      if (line ~ /source[[:space:]]*<\([[:space:]]*openclaw[[:space:]]+completion/) next
      if (line ~ /^[[:space:]]*#[[:space:]]*openclaw[[:space:]]+completion/) next
      print $0
    }
  ' "$zshrc" > "$tmp" && mv "$tmp" "$zshrc"

  ok "Cleaned OpenClaw hooks from ~/.zshrc 🧽"
}

try_official_uninstall() {
  if command -v openclaw >/dev/null 2>&1; then
    info "Trying official uninstall 🧹"
    openclaw uninstall --all --yes --non-interactive >/dev/null 2>&1 || \
      warn "Official uninstall failed/skipped (likely Node mismatch). Continuing with manual nuke πŸͺ“"
  else
    info "openclaw not on PATH (skipping official uninstall)"
  fi
}

remove_launchd_services_macos() {
  local uid="${UID:-$(id -u)}"
  local la="${HOME}/Library/LaunchAgents"
  local labels=("bot.molt.gateway")

  if [[ -d "$la" ]]; then
    local f base
    for f in "$la"/*.plist(N); do
      base="${f:t:r}"
      if [[ "$base" == bot.molt.* || "$base" == com.openclaw.* || "$base" == *openclaw* || "$base" == *molt* ]]; then
        labels+=("$base")
      fi
    done
  fi

  labels=("${(@u)labels}")

  local lbl
  for lbl in "${labels[@]}"; do
    info "Stopping launchd job: $lbl πŸ›‘"
    launchctl bootout "gui/$uid/$lbl" >/dev/null 2>&1 || true
  done

  safe_rm "${HOME}/Library/LaunchAgents/bot.molt.gateway.plist"
  if [[ -d "$la" ]]; then
    local p
    for p in "$la"/(com.openclaw.*|bot.molt.*|*openclaw*|*molt*).plist(N); do
      safe_rm "$p"
    done
  fi

  ok "launchd cleanup done 🧯"
}

remove_npm_global() {
  if command -v npm >/dev/null 2>&1; then
    info "Removing npm global OpenClaw πŸ“¦"
    npm uninstall -g openclaw >/dev/null 2>&1 || true
    ok "npm uninstall attempted βœ…"
  else
    warn "npm not found; skipping npm uninstall"
  fi
}

remove_nodenv_version_binaries() {
  local root="${HOME}/.nodenv"
  [[ -d "$root" ]] || { info "nodenv not present (skipping)"; return 0; }

  local verbin
  for verbin in "$root"/versions/*/bin/openclaw(N); do
    if [[ -w "$verbin" ]]; then
      safe_rm "$verbin"
    else
      warn "Found but not writable: $verbin πŸ”’"
    fi
  done

  local pkgdir
  for pkgdir in "$root"/versions/*/lib/node_modules/openclaw(N); do
    if [[ -w "$pkgdir" ]]; then
      safe_rm "$pkgdir"
    else
      warn "Found but not writable: $pkgdir πŸ”’"
    fi
  done

  ok "nodenv version binaries cleaned 🧼"
}

remove_nodenv_shims_and_rehash() {
  local shims="${HOME}/.nodenv/shims"
  [[ -d "$shims" ]] || { info "nodenv shims dir missing (skipping)"; return 0; }

  safe_rm "$shims/openclaw"
  safe_rm "$shims/clawhub"
  safe_rm "$shims/clawdhub"

  if command -v nodenv >/dev/null 2>&1; then
    nodenv rehash >/dev/null 2>&1 || true
    ok "nodenv rehash complete πŸ”"
  else
    warn "nodenv command not found on PATH; skipped rehash"
  fi

  hash -r 2>/dev/null || true
}

remove_user_bins() {
  safe_rm "${HOME}/.local/bin/openclaw"
  safe_rm "${HOME}/.local/bin/clawhub"
  safe_rm "${HOME}/.local/bin/clawdhub"

  local b
  for b in "/opt/homebrew/bin/openclaw" "/usr/local/bin/openclaw"; do
    if [[ -e "$b" || -L "$b" ]]; then
      if [[ -w "$b" ]]; then
        safe_rm "$b"
      else
        warn "Found $b but not writable (no sudo in this script) πŸ”’"
      fi
    fi
  done
}

remove_state_and_config() {
  local state="${OPENCLAW_STATE_DIR:-$HOME/.openclaw}"
  safe_rm "$state"
  safe_rm "${HOME}/.config/openclaw"
  safe_rm "${HOME}/.cache/openclaw"
  safe_rm "${HOME}/.openclaw/workspace"
}

final_checks() {
  hash -r 2>/dev/null || true
  info "Final checks πŸ”"

  if command -v openclaw >/dev/null 2>&1; then
    warn "openclaw STILL resolves to: $(command -v openclaw) 😀"
    info "type -a openclaw:"
    type -a openclaw || true

    if [[ -d "${HOME}/.nodenv/versions" ]]; then
      info "nodenv versions still providing openclaw (if any):"
      ls -la "${HOME}/.nodenv/versions/"*/bin/openclaw 2>/dev/null || true
    fi
    return 1
  else
    ok "openclaw is gone from PATH πŸŽ‰"
  fi

  info "Searching shell files for 'openclaw' 🧡"
  grep -n "openclaw" "${HOME}/.zshrc" "${HOME}/.zprofile" "${HOME}/.zlogin" "${HOME}/.bashrc" "${HOME}/.profile" 2>/dev/null \
    && warn "Found remaining references above πŸ‘†" \
    || ok "No shell references found βœ…"

  ok "Done. Log saved to: $LOG πŸ“"
}

main() {
  local TOTAL_STEPS=9

  info "🦞 Starting OpenClaw nuke (non-interactive). Log: $LOG"
  progress_init "$TOTAL_STEPS"

  progress_step "1/9 🧽 Removing .zshrc auto-run hooks"
  remove_zshrc_hook

  progress_step "2/9 🧹 Trying official uninstaller (if runnable)"
  try_official_uninstall

  progress_step "3/9 πŸ›‘ Removing launchd services (macOS)"
  remove_launchd_services_macos

  progress_step "4/9 πŸ“¦ Removing npm global install"
  remove_npm_global

  progress_step "5/9 🧼 Removing nodenv version binaries (prevents shim regen)"
  remove_nodenv_version_binaries

  progress_step "6/9 πŸ” Removing nodenv shims + rehash"
  remove_nodenv_shims_and_rehash

  progress_step "7/9 🧨 Removing leftover binaries"
  remove_user_bins

  progress_step "8/9 πŸ—‘οΈ Removing state/config/cache"
  remove_state_and_config

  progress_step "9/9 πŸ” Final verification"
  if ! final_checks; then
    progress_done
    err "Declaw finished but openclaw still resolves on PATH. See log: $LOG"
    exit 1
  fi

  progress_done
  ok "🏁 All done. OpenClaw should be fully declawed."
}

main "$@"
chmod +x declaw.sh then ./declaw.sh
Runs in zsh, no prompts, no downloads, no sudo.
What it removes
  • nodenv shims and version binaries
  • launch agents that keep bots alive
  • state + config + cache folders
  • the .zshrc auto-run hook
What it does not do
  • does not prompt for sudo
  • does not download package managers
  • does not touch unrelated tools

How it works

1

Stops the auto-run

Many installs add source <(openclaw completion ...) into ~/.zshrc. That line runs OpenClaw every time you open a terminal, which causes the β€œNode >= 22” nag. Declaw deletes the hook.

2

Prevents shim resurrection

With nodenv, nodenv rehash recreates shims if a binary exists in any Node version. Declaw deletes ~/.nodenv/versions/*/bin/openclaw first, then rehashes.

3

Removes the bot service

On macOS, bots often run under launchd. Declaw attempts to boot out matching launch agents and removes related plist files from ~/Library/LaunchAgents.

4

Deletes state and cache

Clears default state directories like ~/.openclaw and common config/cache locations, so you are not left with ghost workspaces.

FAQ

Will this ask for passwords or sudo?

No. It only removes user-space files and will skip anything that needs sudo.

I still see openclaw after running it. Why?

Usually because a binary still exists inside ~/.nodenv/versions/* or you installed a system-wide OpenClaw binary in a root-owned directory. Remove that last binary (or run a sudo variant).

Does this break Node, nodenv, or npm?

It should not. It only removes the OpenClaw-related shims/binaries and leaves the rest intact. It also avoids pnpm/yarn so it does not trigger Corepack downloads.

Can I trust a script from the internet?

Treat it like any script. Read it. Save it locally. Run it from a terminal you trust. The whole point of this page is that it is a single file you can audit.