From 9f0d4641bd121a9d49a36ef8c9b08e6617f56d21 Mon Sep 17 00:00:00 2001 From: Spencer Bull Date: Mon, 28 Sep 2026 00:52:56 -0500 Subject: [PATCH] Know the runtime's OpenClaw by its own script A service counted as the runtime's, or as a half-moved old one on /usr/bin/node, whenever it ran anything under ~/.openclaw, so a script of the user's in that directory could be stopped and rewritten, and seeding could go ahead beside it. The runtime is now OpenClaw's own script as upstream's installer lays it out, under ~/.openclaw/tools/*/lib/node_modules/openclaw, and both checks use that one definition. Co-Authored-By: Codex XHigh --- bin/omarchy-install-openclaw-cli | 36 ++++++++++++++++++------------- test/shell.d/openclaw-cli-test.sh | 10 +++++++-- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/bin/omarchy-install-openclaw-cli b/bin/omarchy-install-openclaw-cli index e3578d53..aa853bb5 100755 --- a/bin/omarchy-install-openclaw-cli +++ b/bin/omarchy-install-openclaw-cli @@ -70,22 +70,29 @@ installed() { omarchy-pkg-present openclaw && runtime_runs && on_path } -# Whether a unit's ExecStart runs a program from under a path: the program -# itself, or the script it is handed. Later arguments and other lines can name +# A unit's ExecStart, as the program and the script it is handed: the first +# argument that is not an option. Later arguments and other lines can name # ~/.openclaw whichever OpenClaw the unit starts. -unit_runs() { +unit_program() { + local words + read -ra words <<<"$(sed -n 's/^ExecStart=//p' "$1" | head -1)" + echo "${words[0]:-}" +} + +unit_script() { local words word read -ra words <<<"$(sed -n 's/^ExecStart=//p' "$1" | head -1)" - if [[ ${words[0]:-} == "$2"* ]]; then - return 0 - fi for word in "${words[@]:1}"; do if [[ $word != -* ]]; then - [[ $word == "$2"* ]] + echo "$word" return fi done - return 1 +} + +# The runtime's own OpenClaw, as upstream's installer lays it out. +runs_runtime() { + [[ $(unit_script "$1") == "$prefix"/tools/*/lib/node_modules/openclaw/* ]] } # A gateway service already running some other OpenClaw. Upstream's installer @@ -94,7 +101,7 @@ unit_runs() { foreign_gateway() { local unit unit=$(unit_path gateway) - [[ -f $unit ]] && ! unit_runs "$unit" "$prefix/" && ! unit_runs "$unit" "/usr/lib/node_modules/openclaw/" + [[ -f $unit ]] && ! runs_runtime "$unit" && ! on_old_package "$unit" } # A service the openclaw package's own copy installed runs from @@ -124,13 +131,12 @@ stop_legacy_services() { # Still the old package's: its script, or the runtime's script on the old # package's Node. Upstream's installer keeps the Node a service already ran, so -# a moved unit can end up running ~/.openclaw on /usr/bin/node, from the nodejs -# package the seed no longer depends on. Any other Node or Bun is the user's. +# a moved unit can end up running the runtime's OpenClaw on /usr/bin/node, from +# the nodejs package the seed no longer depends on. Any other Node, Bun or +# script is the user's. on_old_package() { - local program - program=$(sed -n 's/^ExecStart=//p' "$1" | head -1) - program=${program%% *} - unit_runs "$1" "/usr/lib/node_modules/openclaw/" || { [[ $program == "/usr/bin/node" ]] && unit_runs "$1" "$prefix/"; } + [[ $(unit_script "$1") == /usr/lib/node_modules/openclaw/* ]] || + { [[ $(unit_program "$1") == "/usr/bin/node" ]] && runs_runtime "$1"; } } # Not moved yet: still on the old package, or running before and not now. diff --git a/test/shell.d/openclaw-cli-test.sh b/test/shell.d/openclaw-cli-test.sh index d629ee27..44693750 100755 --- a/test/shell.d/openclaw-cli-test.sh +++ b/test/shell.d/openclaw-cli-test.sh @@ -255,7 +255,7 @@ new_home half-moved run omarchy-install-openclaw-cli --now || fail "--now sets OpenClaw up" "$(cat "$test_tmp/output")" mkdir -p "$test_home/.config/systemd/user" printf 'ExecStart=/usr/bin/node %s/.openclaw/tools/node-v24.19.0/lib/node_modules/openclaw/dist/index.js gateway --port 18789\n' "$test_home" >"$test_home/.config/systemd/user/openclaw-gateway.service" -printf 'ExecStart=/usr/bin/node /usr/lib/node_modules/openclaw/dist/index.js node run\n' >"$test_home/.config/systemd/user/openclaw-node.service" +printf 'ExecStart=/usr/bin/node %s/.openclaw/tools/node-v24.19.0/lib/node_modules/openclaw/dist/index.js node run\n' "$test_home" >"$test_home/.config/systemd/user/openclaw-node.service" touch "$test_home/active-openclaw-gateway.service" "$test_home/active-openclaw-node.service" : >"$events" run omarchy-install-openclaw-cli --now || fail "--now finishes a half-moved gateway" "$(cat "$test_tmp/output")" @@ -277,7 +277,13 @@ cp "$test_home/.config/systemd/user/openclaw-gateway.service" "$test_tmp/bun-uni run omarchy-install-openclaw-cli --now || fail "--now leaves a Bun gateway alone" "$(cat "$test_tmp/output")" ! grep -q "install --force\|^systemctl" "$events" && cmp -s "$test_tmp/bun-unit" "$test_home/.config/systemd/user/openclaw-gateway.service" || fail "--now leaves a Bun gateway alone" "$(cat "$events")" -pass "a gateway the user runs on Bun is left alone" +printf 'ExecStart=/usr/bin/node %s/.openclaw/custom/bridge.js\n' "$test_home" >"$test_home/.config/systemd/user/openclaw-gateway.service" +cp "$test_home/.config/systemd/user/openclaw-gateway.service" "$test_tmp/own-unit" +: >"$events" +run omarchy-install-openclaw-cli --now || fail "--now leaves a script of the user's alone" "$(cat "$test_tmp/output")" +! grep -q "install --force\|^systemctl" "$events" && cmp -s "$test_tmp/own-unit" "$test_home/.config/systemd/user/openclaw-gateway.service" || + fail "--now leaves a script of the user's alone" "$(cat "$events")" +pass "a gateway the user runs on Bun, or a script of their own on /usr/bin/node, is left alone" # The migration moves only machines that have the package, and waits for the # package that seeds.