@kocoro/shanclaw 0.0.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/bin/shan +3 -0
  2. package/install.js +103 -0
  3. package/package.json +33 -0
package/bin/shan ADDED
@@ -0,0 +1,3 @@
1
+ #\!/bin/sh
2
+ echo "shan binary not installed. Run: npm rebuild shan-cli"
3
+ exit 1
package/install.js ADDED
@@ -0,0 +1,103 @@
1
+ const { execFileSync } = require("child_process");
2
+ const fs = require("fs");
3
+ const path = require("path");
4
+ const https = require("https");
5
+ const crypto = require("crypto");
6
+
7
+ const REPO = "Kocoro-lab/ShanClaw";
8
+ const BIN_DIR = path.join(__dirname, "bin");
9
+
10
+ function getPlatform() {
11
+ const p = process.platform;
12
+ if (p !== "darwin" && p !== "linux") {
13
+ throw new Error("Unsupported platform: " + p + ". shan supports macOS and Linux.");
14
+ }
15
+ return p;
16
+ }
17
+
18
+ function getArch() {
19
+ const map = { x64: "amd64", arm64: "arm64" };
20
+ const a = map[process.arch];
21
+ if (!a) {
22
+ throw new Error("Unsupported architecture: " + process.arch);
23
+ }
24
+ return a;
25
+ }
26
+
27
+ function fetch(url) {
28
+ return new Promise((resolve, reject) => {
29
+ https.get(url, { headers: { "User-Agent": "shan-cli-npm" } }, (res) => {
30
+ if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
31
+ return fetch(res.headers.location).then(resolve, reject);
32
+ }
33
+ if (res.statusCode !== 200) {
34
+ return reject(new Error("HTTP " + res.statusCode + " for " + url));
35
+ }
36
+ const chunks = [];
37
+ res.on("data", (c) => chunks.push(c));
38
+ res.on("end", () => resolve(Buffer.concat(chunks)));
39
+ res.on("error", reject);
40
+ }).on("error", reject);
41
+ });
42
+ }
43
+
44
+ async function main() {
45
+ const platform = getPlatform();
46
+ const arch = getArch();
47
+ console.log("shan: detecting platform " + platform + "/" + arch);
48
+
49
+ // Get latest release
50
+ const releaseData = await fetch(
51
+ "https://api.github.com/repos/" + REPO + "/releases/latest"
52
+ );
53
+ const release = JSON.parse(releaseData.toString());
54
+ const version = release.tag_name.replace(/^v/, "");
55
+ console.log("shan: installing v" + version + "...");
56
+
57
+ const filename = "shan_" + version + "_" + platform + "_" + arch + ".tar.gz";
58
+ const asset = release.assets.find((a) => a.name === filename);
59
+ if (!asset) {
60
+ throw new Error("No release asset found for " + filename);
61
+ }
62
+
63
+ // Download binary
64
+ const tarball = await fetch(asset.browser_download_url);
65
+
66
+ // Verify checksum
67
+ const checksumAsset = release.assets.find((a) => a.name === "checksums.txt");
68
+ if (checksumAsset) {
69
+ const checksumData = await fetch(checksumAsset.browser_download_url);
70
+ const line = checksumData.toString().split("\n").find((l) => l.includes(filename));
71
+ if (line) {
72
+ const expected = line.split(/\s+/)[0];
73
+ const actual = crypto.createHash("sha256").update(tarball).digest("hex");
74
+ if (actual !== expected) {
75
+ throw new Error("Checksum mismatch for " + filename);
76
+ }
77
+ console.log("shan: checksum verified");
78
+ }
79
+ }
80
+
81
+ // Extract with system tar
82
+ fs.mkdirSync(BIN_DIR, { recursive: true });
83
+ const tmpTar = path.join(BIN_DIR, "_shan.tar.gz");
84
+ fs.writeFileSync(tmpTar, tarball);
85
+ try {
86
+ execFileSync("tar", ["-xzf", "_shan.tar.gz", "shan"], { cwd: BIN_DIR });
87
+ // ax_server is only present in darwin archives — not an error on linux
88
+ try {
89
+ execFileSync("tar", ["-xzf", "_shan.tar.gz", "ax_server"], { cwd: BIN_DIR });
90
+ fs.chmodSync(path.join(BIN_DIR, "ax_server"), 0o755);
91
+ } catch (_) {}
92
+ } finally {
93
+ fs.unlinkSync(tmpTar);
94
+ }
95
+
96
+ fs.chmodSync(path.join(BIN_DIR, "shan"), 0o755);
97
+ console.log("shan: v" + version + " installed successfully");
98
+ }
99
+
100
+ main().catch((err) => {
101
+ console.error("shan install failed: " + err.message);
102
+ process.exit(1);
103
+ });
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@kocoro/shanclaw",
3
+ "version": "0.0.1",
4
+ "description": "AI-powered CLI agent with local tools, permissions, and session management",
5
+ "bin": {
6
+ "shan": "bin/shan"
7
+ },
8
+ "scripts": {
9
+ "postinstall": "node install.js"
10
+ },
11
+ "os": [
12
+ "darwin",
13
+ "linux"
14
+ ],
15
+ "cpu": [
16
+ "x64",
17
+ "arm64"
18
+ ],
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "https://github.com/Kocoro-lab/ShanClaw"
22
+ },
23
+ "homepage": "https://github.com/Kocoro-lab/ShanClaw",
24
+ "keywords": [
25
+ "cli",
26
+ "ai",
27
+ "agent",
28
+ "shannon",
29
+ "llm"
30
+ ],
31
+ "license": "Apache-2.0",
32
+ "author": "Kocoro-lab"
33
+ }