Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 29 additions & 5 deletions bin/lib/resolve-openshell.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,46 @@ const fs = require("fs");
* @param {string} [opts.home] HOME override
* @returns {string|null} Absolute path to openshell, or null if not found
*/
/**
* Verify if the binary is the OpenShell Rust CLI (and not a shadowing NPM package).
* @param {string} path Absolute path to binary
* @returns {boolean}
*/
function isRustCli(path) {
try {
const output = execSync(`${path} -V`, {
encoding: "utf-8",
stdio: ["ignore", "pipe", "pipe"],
timeout: 2000,
}).trim();
// Rust version string: "openshell 0.1.0"
return /^openshell\s+[0-9]+\.[0-9]+\.[0-9]+/i.test(output);
} catch {
return false;
}
}

function resolveOpenshell(opts = {}) {
const home = opts.home ?? process.env.HOME;

// Step 1: command -v
// Step 1: command -v (check if it is the Rust CLI)
if (opts.commandVResult === undefined) {
try {
const found = execSync("command -v openshell", { encoding: "utf-8" }).trim();
if (found.startsWith("/")) return found;
if (found.startsWith("/") && isRustCli(found)) return found;
} catch { /* ignored */ }
} else if (opts.commandVResult && opts.commandVResult.startsWith("/")) {
} else if (opts.commandVResult && opts.commandVResult.startsWith("/") && isRustCli(opts.commandVResult)) {
return opts.commandVResult;
}

// Step 2: fallback candidates
// Step 2: fallback candidates (verify they are the Rust CLI)
const checkExecutable = opts.checkExecutable || ((p) => {
try { fs.accessSync(p, fs.constants.X_OK); return true; } catch { return false; }
try {
fs.accessSync(p, fs.constants.X_OK);
return isRustCli(p);
} catch {
return false;
}
});

const candidates = [
Expand Down
17 changes: 12 additions & 5 deletions scripts/install-openshell.sh
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,20 @@ version_gte() {
return 0
}

# Use -V (capital V) as it is specific to the Rust CLI version strings
if command -v openshell >/dev/null 2>&1; then
INSTALLED_VERSION="$(openshell --version 2>&1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || echo '0.0.0')"
if version_gte "$INSTALLED_VERSION" "$MIN_VERSION"; then
info "openshell already installed: $INSTALLED_VERSION (>= $MIN_VERSION)"
exit 0
# Verify if it's the Rust CLI, not a shadowing NPM package
VERSION_OUT="$(openshell -V 2>&1 || echo "")"
if echo "$VERSION_OUT" | grep -qi "^openshell [0-9]"; then
INSTALLED_VERSION="$(echo "$VERSION_OUT" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || echo '0.0.0')"
if version_gte "$INSTALLED_VERSION" "$MIN_VERSION"; then
info "openshell already installed: $INSTALLED_VERSION (>= $MIN_VERSION)"
exit 0
fi
warn "openshell $INSTALLED_VERSION is below minimum $MIN_VERSION — upgrading..."
else
warn "The 'openshell' command on PATH is not the OpenShell CLI binary (possibly shadowed by NPM). Reinstalling CLI..."
fi
warn "openshell $INSTALLED_VERSION is below minimum $MIN_VERSION — upgrading..."
fi

info "Installing openshell CLI..."
Expand Down