Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
7 changes: 3 additions & 4 deletions npm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@ npx clawdchan@latest setup
Installation pulls the prebuilt binary matching your platform from GitHub
Releases and drops it into `~/.clawdchan/bin/` — a stable location that
survives `npm uninstall`, matches the shell installer, and keeps the
launchd/systemd service pointing at a path that doesn't move across
npm upgrades. Supported: macOS (x64, arm64) and Linux (x64, arm64).
Windows users: grab the zip from the
[releases page](https://github.com/agents-first/clawdchan/releases).
launchd/systemd/Scheduled Task service pointing at a path that doesn't move
across npm upgrades. Supported: macOS (x64, arm64), Linux (x64, arm64), and
Windows (x64).
Comment on lines +21 to +23

Environment variables:

Expand Down
7 changes: 4 additions & 3 deletions npm/bin/_run.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ const VENDOR = path.join(__dirname, "..", "vendor");

module.exports = function run(name) {
const override = process.env.CLAWDCHAN_INSTALL_DIR;
const exe = process.platform === "win32" ? `${name}.exe` : name;
const candidates = [
override && path.join(expandHome(override), name),
path.join(STABLE, name),
path.join(VENDOR, name),
override && path.join(expandHome(override), exe),
path.join(STABLE, exe),
path.join(VENDOR, exe),
].filter(Boolean);

const bin = candidates.find((p) => fs.existsSync(p));
Expand Down
3 changes: 2 additions & 1 deletion npm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
],
"os": [
"darwin",
"linux"
"linux",
"win32"
],
Comment on lines 18 to 22
"cpu": [
"x64",
Expand Down
37 changes: 32 additions & 5 deletions npm/scripts/install.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,10 @@ const REPO = "agents-first/clawdchan";
const PKG = require("../package.json");
const VERSION = process.env.CLAWDCHAN_VERSION || `v${PKG.version}`;
const VENDOR = path.join(__dirname, "..", "vendor");
const BINS = ["clawdchan", "clawdchan-mcp", "clawdchan-relay"];
const BIN_EXT = process.platform === "win32" ? ".exe" : "";
const BINS = ["clawdchan", "clawdchan-mcp", "clawdchan-relay"].map((b) => `${b}${BIN_EXT}`);

const OS_MAP = { darwin: "macOS", linux: "Linux" };
const OS_MAP = { darwin: "macOS", linux: "Linux", win32: "Windows" };
const ARCH_MAP = { x64: "x86_64", arm64: "arm64" };

const osName = OS_MAP[process.platform];
Expand All @@ -48,6 +49,11 @@ if (!osName || !archName) {
process.exit(0);
}

if (process.platform === "win32" && process.arch !== "x64") {
log(`unsupported platform ${process.platform}/${process.arch} — install from source: https://github.com/${REPO}`);
process.exit(0);
}

main().catch((err) => {
log(`install failed: ${err.message}`);
log(`fetch manually from https://github.com/${REPO}/releases and place binaries in ${VENDOR}`);
Expand All @@ -57,7 +63,8 @@ main().catch((err) => {
async function main() {
const tag = await resolveTag(VERSION);
const version = tag.replace(/^v/, "");
const archive = `clawdchan_${version}_${osName}_${archName}.tar.gz`;
const archiveExt = process.platform === "win32" ? "zip" : "tar.gz";
const archive = `clawdchan_${version}_${osName}_${archName}.${archiveExt}`;
const base = `https://github.com/${REPO}/releases/download/${tag}`;

log(`downloading clawdchan ${tag} (${osName}_${archName})`);
Expand All @@ -78,14 +85,14 @@ async function main() {

const installDir = chooseInstallDir();
fs.mkdirSync(installDir, { recursive: true });
execFileSync("tar", ["-xzf", archivePath, "-C", tmp], { stdio: "ignore" });
extractArchive(archivePath, tmp);

for (const b of BINS) {
const src = path.join(tmp, b);
if (!fs.existsSync(src)) throw new Error(`missing ${b} in archive`);
const dst = path.join(installDir, b);
fs.renameSync(src, dst);
fs.chmodSync(dst, 0o755);
if (process.platform !== "win32") fs.chmodSync(dst, 0o755);
}
log(`installed binaries to ${installDir}`);

Expand All @@ -97,6 +104,26 @@ async function main() {
}
}

function extractArchive(archivePath, dest) {
if (process.platform === "win32") {
execFileSync(
"powershell",
[
"-NoProfile",
"-ExecutionPolicy",
"Bypass",
"-Command",
"& { param($zip, $dest) Expand-Archive -LiteralPath $zip -DestinationPath $dest -Force }",
archivePath,
dest,
],
{ stdio: "ignore" }
);
return;
}
execFileSync("tar", ["-xzf", archivePath, "-C", dest], { stdio: "ignore" });
Comment on lines +113 to +124
}

function chooseInstallDir() {
const override = process.env.CLAWDCHAN_INSTALL_DIR;
if (override) return expandHome(override);
Expand Down
Loading