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.
.zshrc auto-run completion hook.nodenv rehash.#!/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 "$@"
- nodenv shims and version binaries
- launch agents that keep bots alive
- state + config + cache folders
- the
.zshrcauto-run hook
- does not prompt for sudo
- does not download package managers
- does not touch unrelated tools
How it works
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.
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.
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.
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.