import fs from "node:fs"; import os from "node:os"; import path from "node:path"; import { resolveBrewPathDirs } from "./brew.js"; import { isTruthyEnvValue } from "./env.js";
const seen = new Set<string>(); const merged: string[] = []; for (const part of [...partsPrepend, ...partsExisting, ...partsAppend]) { if (!seen.has(part)) {
seen.add(part);
merged.push(part);
}
} return merged.join(path.delimiter);
}
// Keep the active runtime directory ahead of PATH hardening so shebang-based // subprocesses keep using the same Node/Bun the current OpenClaw process is on. try { const execDir = path.dirname(execPath); if (isExecutable(execPath)) {
prepend.push(execDir);
}
} catch { // ignore
}
// Bundled macOS app: `openclaw` lives next to the executable (process.execPath). try { const execDir = path.dirname(execPath); const siblingCli = path.join(execDir, "openclaw"); if (isExecutable(siblingCli)) {
prepend.push(execDir);
}
} catch { // ignore
}
// Project-local installs are a common repo-based attack vector (bin hijacking). Keep this // disabled by default; if an operator explicitly enables it, only append (never prepend). const allowProjectLocalBin =
opts.allowProjectLocalBin === true ||
isTruthyEnvValue(process.env.OPENCLAW_ALLOW_PROJECT_LOCAL_BIN); if (allowProjectLocalBin) { const localBinDir = path.join(cwd, "node_modules", ".bin"); if (isExecutable(path.join(localBinDir, "openclaw"))) {
append.push(localBinDir);
}
}
// Only immutable OS directories go in prepend so they take priority over // user-writable locations, preventing PATH hijack of system binaries.
prepend.push("/usr/bin", "/bin");
// User-writable / package-manager directories are appended so they never // shadow trusted OS binaries. // This includes Brew/Homebrew dirs, which are useful for finding `openclaw` // in launchd/minimal environments but must not be treated as trusted.
append.push(...resolveBrewPathDirs({ homeDir })); const miseDataDir = process.env.MISE_DATA_DIR ?? path.join(homeDir, ".local", "share", "mise"); const miseShims = path.join(miseDataDir, "shims"); if (isDirectory(miseShims)) {
append.push(miseShims);
} if (platform === "darwin") {
append.push(path.join(homeDir, "Library", "pnpm"));
} if (process.env.XDG_BIN_HOME) {
append.push(process.env.XDG_BIN_HOME);
}
append.push(path.join(homeDir, ".local", "bin"));
append.push(path.join(homeDir, ".local", "share", "pnpm"));
append.push(path.join(homeDir, ".bun", "bin"));
append.push(path.join(homeDir, ".yarn", "bin"));
/** * Best-effort PATH bootstrap so skills that require the `openclaw` CLI can run * under launchd/minimal environments (and inside the macOS app bundle).
*/
export function ensureOpenClawCliOnPath(opts: EnsureOpenClawPathOpts = {}) { if (isTruthyEnvValue(process.env.OPENCLAW_PATH_BOOTSTRAPPED)) { return;
}
process.env.OPENCLAW_PATH_BOOTSTRAPPED = "1";
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.