Skip to content

Commit 56fe64e

Browse files
committed
fix: print resolved installer follow-up command
Signed-off-by: sallyom <[email protected]>
1 parent 6a8b4e4 commit 56fe64e

3 files changed

Lines changed: 63 additions & 5 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ Docs: https://docs.openclaw.ai
154154
### Fixes
155155

156156
- Docs/Docker: document a local Compose override for Docker Desktop DNS failures in the shared-network `openclaw-cli` sidecar, keeping the default compose setup hardened while unblocking `openclaw plugins install` when users opt in. Fixes #79018. Thanks @Jason-Vaughan.
157+
- Installer: when npm installs `openclaw` outside the parent shell PATH, print follow-up commands with the resolved binary path instead of telling users to run `openclaw` from a shell that will report `command not found`. Fixes #72382. Thanks @jbob762.
157158
- Compute plugin callback authorization dynamically [AI]. (#78866) Thanks @pgondhi987.
158159
- fix(active-memory): require admin scope for global toggles [AI]. (#78863) Thanks @pgondhi987.
159160
- Honor owner enforcement for native commands [AI]. (#78864) Thanks @pgondhi987.

scripts/install.sh

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2006,6 +2006,24 @@ warn_shell_path_missing_dir() {
20062006
echo " export PATH=\"${dir}:\$PATH\""
20072007
}
20082008

2009+
openclaw_command_for_user() {
2010+
local claw="${1:-}"
2011+
if [[ -z "$claw" ]]; then
2012+
echo "openclaw"
2013+
return 0
2014+
fi
2015+
2016+
local claw_dir="${claw%/*}"
2017+
if [[ "$claw_dir" != "$claw" ]] && path_has_dir "$ORIGINAL_PATH" "$claw_dir"; then
2018+
echo "openclaw"
2019+
return 0
2020+
fi
2021+
2022+
local quoted_claw=""
2023+
printf -v quoted_claw '%q' "$claw"
2024+
echo "$quoted_claw"
2025+
}
2026+
20092027
ensure_npm_global_bin_on_path() {
20102028
local bin_dir=""
20112029
bin_dir="$(npm_global_bin_dir || true)"
@@ -2300,7 +2318,9 @@ run_bootstrap_onboarding_if_needed() {
23002318
fi
23012319

23022320
if [[ ! -r /dev/tty || ! -w /dev/tty ]]; then
2303-
ui_info "BOOTSTRAP.md found but no TTY; run openclaw onboard to finish setup"
2321+
local user_claw
2322+
user_claw="$(openclaw_command_for_user "${OPENCLAW_BIN:-}")"
2323+
ui_info "BOOTSTRAP.md found but no TTY; run ${user_claw} onboard to finish setup"
23042324
return
23052325
fi
23062326

@@ -2316,7 +2336,9 @@ run_bootstrap_onboarding_if_needed() {
23162336
fi
23172337

23182338
"$claw" onboard || {
2319-
ui_error "Onboarding failed; run openclaw onboard to retry"
2339+
local user_claw
2340+
user_claw="$(openclaw_command_for_user "$claw")"
2341+
ui_error "Onboarding failed; run ${user_claw} onboard to retry"
23202342
return
23212343
}
23222344
}
@@ -2702,11 +2724,15 @@ main() {
27022724
ui_warn "Doctor failed; skipping plugin updates"
27032725
fi
27042726
else
2705-
ui_info "No TTY; run openclaw doctor and openclaw plugins update --all manually"
2727+
local user_claw
2728+
user_claw="$(openclaw_command_for_user "${OPENCLAW_BIN:-}")"
2729+
ui_info "No TTY; run ${user_claw} doctor and ${user_claw} plugins update --all manually"
27062730
fi
27072731
else
27082732
if [[ "$NO_ONBOARD" == "1" || "$skip_onboard" == "true" ]]; then
2709-
ui_info "Skipping onboard (requested); run openclaw onboard later"
2733+
local user_claw
2734+
user_claw="$(openclaw_command_for_user "${OPENCLAW_BIN:-}")"
2735+
ui_info "Skipping onboard (requested); run ${user_claw} onboard later"
27102736
else
27112737
local config_path="${OPENCLAW_CONFIG_PATH:-$HOME/.openclaw/openclaw.json}"
27122738
if [[ -f "${config_path}" || -f "$HOME/.clawdbot/clawdbot.json" ]]; then
@@ -2731,7 +2757,9 @@ main() {
27312757
exec </dev/tty
27322758
exec "$claw" onboard
27332759
fi
2734-
ui_info "No TTY; run openclaw onboard to finish setup"
2760+
local user_claw
2761+
user_claw="$(openclaw_command_for_user "${OPENCLAW_BIN:-}")"
2762+
ui_info "No TTY; run ${user_claw} onboard to finish setup"
27352763
return 0
27362764
fi
27372765
fi

test/scripts/install-sh.test.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,35 @@ describe("install.sh", () => {
161161
expect(result?.stdout).toContain("using this user prefix");
162162
expect(result?.stdout).not.toContain("has been saved");
163163
});
164+
165+
it("uses a quoted absolute openclaw path in follow-up commands when npm bin is not on the original PATH", () => {
166+
const tmp = mkdtempSync(join(tmpdir(), "openclaw-install-command-"));
167+
const npmBin = join(tmp, "npm bin");
168+
const visibleBin = join(tmp, "visible-bin");
169+
mkdirSync(npmBin, { recursive: true });
170+
mkdirSync(visibleBin, { recursive: true });
171+
const openclawBin = join(npmBin, "openclaw");
172+
writeFileSync(openclawBin, "#!/bin/sh\nexit 0\n");
173+
chmodSync(openclawBin, 0o755);
174+
175+
let result: ReturnType<typeof runInstallShell> | undefined;
176+
try {
177+
result = runInstallShell(`
178+
set -euo pipefail
179+
source "${SCRIPT_PATH}"
180+
ORIGINAL_PATH=${JSON.stringify(`${visibleBin}:/usr/bin:/bin`)}
181+
printf 'missing=%s\\n' "$(openclaw_command_for_user "${openclawBin}")"
182+
ORIGINAL_PATH=${JSON.stringify(`${npmBin}:${visibleBin}:/usr/bin:/bin`)}
183+
printf 'present=%s\\n' "$(openclaw_command_for_user "${openclawBin}")"
184+
`);
185+
} finally {
186+
rmSync(tmp, { recursive: true, force: true });
187+
}
188+
189+
expect(result?.status).toBe(0);
190+
expect(result?.stdout).toContain(`missing=${openclawBin.replace(/ /g, "\\ ")}`);
191+
expect(result?.stdout).toContain("present=openclaw");
192+
});
164193
});
165194

166195
describe("install.sh macOS Homebrew Node behavior", () => {

0 commit comments

Comments
 (0)