@keepstateai/cli 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/install.js +43 -0
  2. package/package.json +12 -0
  3. package/run.js +5 -0
package/install.js ADDED
@@ -0,0 +1,43 @@
1
+ // Downloads the ks release binary for this platform and VERIFIES its SHA256
2
+ // against the release's SHA256SUMS before trusting it. A mismatch aborts the
3
+ // install with nothing kept — the same refusal as the shell installer.
4
+ const { createHash } = require("crypto");
5
+ const fs = require("fs");
6
+ const path = require("path");
7
+ const https = require("https");
8
+
9
+ const REPO = process.env.KS_INSTALL_REPO || "keepstateai/cli";
10
+ const BASE = process.env.KS_INSTALL_BASE || `https://github.com/${REPO}/releases/latest/download`;
11
+ const os = { darwin: "darwin", linux: "linux" }[process.platform];
12
+ const arch = { arm64: "arm64", x64: "amd64" }[process.arch];
13
+ if (!os || !arch) { console.error(`unsupported platform: ${process.platform}/${process.arch}`); process.exit(1); }
14
+ const asset = `ks-${os}-${arch}`;
15
+
16
+ function fetch(url, redirects = 5) {
17
+ return new Promise((resolve, reject) => {
18
+ https.get(url, (res) => {
19
+ if ([301, 302, 307, 308].includes(res.statusCode) && redirects > 0)
20
+ return resolve(fetch(res.headers.location, redirects - 1));
21
+ if (res.statusCode !== 200) return reject(new Error(`GET ${url}: ${res.statusCode}`));
22
+ const chunks = [];
23
+ res.on("data", (c) => chunks.push(c));
24
+ res.on("end", () => resolve(Buffer.concat(chunks)));
25
+ res.on("error", reject);
26
+ }).on("error", reject);
27
+ });
28
+ }
29
+
30
+ (async () => {
31
+ console.log(`downloading ${asset} ...`);
32
+ const [bin, sums] = await Promise.all([fetch(`${BASE}/${asset}`), fetch(`${BASE}/SHA256SUMS`)]);
33
+ const line = sums.toString().split("\n").map(l => l.trim().split(/\s+/)).find(f => f[1] === asset || f[1] === `*${asset}`);
34
+ if (!line) { console.error(`REFUSED: no SHA256SUMS entry for ${asset}`); process.exit(1); }
35
+ const got = createHash("sha256").update(bin).digest("hex");
36
+ if (got !== line[0]) {
37
+ console.error(`REFUSED: checksum mismatch for ${asset}\n expected: ${line[0]}\n got: ${got}\nNothing was installed.`);
38
+ process.exit(1);
39
+ }
40
+ const dest = path.join(__dirname, "ks-bin");
41
+ fs.writeFileSync(dest, bin, { mode: 0o755 });
42
+ console.log(`checksum OK; installed. Next step: ks login`);
43
+ })().catch((e) => { console.error(e.message); process.exit(1); });
package/package.json ADDED
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "@keepstateai/cli",
3
+ "version": "0.1.1",
4
+ "description": "KeepState CLI (ks) — durable agent sessions. Thin shim that downloads the checksum-verified release binary.",
5
+ "license": "MIT",
6
+ "repository": { "type": "git", "url": "https://github.com/keepstateai/cli" },
7
+ "homepage": "https://keepstate.ai",
8
+ "bin": { "ks": "run.js" },
9
+ "scripts": { "postinstall": "node install.js" },
10
+ "os": ["darwin", "linux"],
11
+ "cpu": ["arm64", "x64"]
12
+ }
package/run.js ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ const { spawn } = require("child_process");
3
+ const path = require("path");
4
+ const bin = path.join(__dirname, "ks-bin");
5
+ spawn(bin, process.argv.slice(2), { stdio: "inherit" }).on("exit", (c) => process.exit(c ?? 1));