The first E2E run of the migration found that the new runtime cannot install its gateway service while the old package's gateway, still running from deleted files, holds the state directory, so that service is stopped first. Removal also takes the unit backups `openclaw update` leaves behind. Codex's review found the rest: upstream's installer takes over any loaded gateway service, so a gateway running another OpenClaw, a foreign command on PATH or an openclaw shadowing it are refused before anything is set up; root is refused before --check runs the user's wrapper; --check needs the package, since --now would otherwise run pacman where no terminal can ask for a password; and moving a service clears the selectors that would aim the install at another unit. Co-Authored-By: Codex XHigh <noreply@openai.com>
94 lines
4.3 KiB
Bash
Executable File
94 lines
4.3 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# omarchy:summary=Remove the OpenClaw agent platform along with its gateway service and web app.
|
|
# omarchy:requires-sudo=true
|
|
|
|
# -u so an unset HOME is an error rather than a set of rm -rf paths rooted at /.
|
|
set -euo pipefail
|
|
|
|
unit_dir="$HOME/.config/systemd/user"
|
|
|
|
# Only systemd's own word counts as "stopped": a non-zero exit from is-active
|
|
# also covers an unreachable user manager, which says nothing about whether
|
|
# the process is alive.
|
|
unit_stopped() {
|
|
local state
|
|
state=$(systemctl --user is-active "$1" 2>/dev/null) || true
|
|
[[ $state == inactive || $state == failed ]]
|
|
}
|
|
|
|
# The user services OpenClaw installs for itself: the gateway through
|
|
# onboarding, and the node host if the user ever paired this machine to
|
|
# another gateway. OpenClaw writes them to $HOME/.config regardless of
|
|
# XDG_CONFIG_HOME, so look exactly there; no unit means nothing registered.
|
|
# Upstream's own teardown knows every piece its install wrote (unit file, the
|
|
# default.target.wants enablement symlink, the reload), so prefer it while the
|
|
# binary is still installed and fall back to doing the same by hand. A service
|
|
# that will not stop aborts the removal: dropping the package would strand the
|
|
# live process on deleted code with no way to restart it cleanly.
|
|
for unit_file in "$unit_dir"/openclaw-gateway.service "$unit_dir"/openclaw-node.service; do
|
|
[[ -f $unit_file ]] || continue
|
|
unit=${unit_file##*/}
|
|
role=${unit#openclaw-}
|
|
role=${role%.service}
|
|
if openclaw "$role" uninstall >/dev/null 2>&1 ||
|
|
systemctl --user disable --now "$unit" 2>/dev/null ||
|
|
unit_stopped "$unit"; then
|
|
# .bak is what `gateway install --force` leaves behind when it rewrites a
|
|
# unit, and .reconcile-*.bak what `openclaw update` leaves when it
|
|
# refreshes one, so they go with the unit.
|
|
rm -f "$unit_file" "$unit_file.bak" "$unit_file".reconcile-*.bak "$unit_dir/default.target.wants/$unit"
|
|
systemctl --user daemon-reload 2>/dev/null || true
|
|
# A unit that had been failing stays listed as "not-found failed" after
|
|
# its file is gone until its failed state is reset.
|
|
systemctl --user reset-failed "$unit" 2>/dev/null || true
|
|
else
|
|
echo "Could not stop $unit; OpenClaw was not removed." >&2
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
omarchy-pkg-drop openclaw
|
|
|
|
# The runtime omarchy-install-openclaw-cli set up lives beside the user's state
|
|
# in ~/.openclaw: the command upstream's installer wrote, and the Node and
|
|
# package under tools/. Only a command that execs into those tools is the
|
|
# installer's; the link on PATH goes only when it points at that command.
|
|
if [[ -f $HOME/.openclaw/bin/openclaw ]] && grep -qF "\"$HOME/.openclaw/tools/" "$HOME/.openclaw/bin/openclaw"; then
|
|
rm -rf "$HOME/.openclaw/tools"
|
|
rm -f "$HOME/.openclaw/bin/openclaw"
|
|
rmdir "$HOME/.openclaw/bin" 2>/dev/null || true
|
|
fi
|
|
if [[ -L $HOME/.local/bin/openclaw && $(readlink -- "$HOME/.local/bin/openclaw") == "$HOME/.openclaw/bin/openclaw" ]]; then
|
|
rm -f "$HOME/.local/bin/openclaw"
|
|
fi
|
|
|
|
# The web app launcher and icon omarchy-install-ai-openclaw created.
|
|
rm -f "$HOME/.local/share/applications/OpenClaw.desktop"
|
|
rm -f "$HOME/.local/share/icons/hicolor/256x256/apps/openclaw.png"
|
|
gtk-update-icon-cache "$HOME/.local/share/icons/hicolor" &>/dev/null || true
|
|
|
|
# ~/.openclaw stays unless asked: the chats, memories, and credentials in
|
|
# there are the user's agent, and finding them intact after a reinstall is the
|
|
# better surprise. But it also holds the plugin runtimes and caches OpenClaw
|
|
# downloads for itself, easily hundreds of megabytes, so the choice is put in
|
|
# front of the user with the size rather than left silent. Without a terminal
|
|
# to ask in, keeping it is the answer. The snapshots `openclaw update` takes
|
|
# of that state sit beside it and go with it.
|
|
state_removed=false
|
|
if [[ -d $HOME/.openclaw && -t 0 ]]; then
|
|
size=$(du -sh "$HOME/.openclaw" 2>/dev/null | cut -f1)
|
|
if gum confirm --default=false "Also delete ~/.openclaw ($size: chats, memories, credentials, and downloaded plugins)?"; then
|
|
rm -rf "$HOME/.openclaw" "$HOME/.openclaw.update-captures"
|
|
state_removed=true
|
|
fi
|
|
fi
|
|
|
|
echo ""
|
|
echo "OpenClaw has been removed."
|
|
if [[ $state_removed == true ]]; then
|
|
echo "Its chats, memories, and settings in ~/.openclaw are gone too."
|
|
elif [[ -d $HOME/.openclaw ]]; then
|
|
echo "Your agent's chats, memories, and settings are still in ~/.openclaw."
|
|
fi
|