clawreform 0.3.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.
package/README.md ADDED
@@ -0,0 +1,20 @@
1
+ # clawreform (npm CLI launcher)
2
+
3
+ Installs the native `clawreform` CLI from GitHub Releases and exposes it on your npm global PATH.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install -g clawreform
9
+ ```
10
+
11
+ ## Verify
12
+
13
+ ```bash
14
+ clawreform --version
15
+ ```
16
+
17
+ ## Notes
18
+
19
+ - This package downloads the matching binary for Linux, macOS, and Windows.
20
+ - No third-party runtime dependencies are used in this npm package.
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { spawnSync } = require("node:child_process");
4
+ const { ensureBinaryInstalled } = require("../lib/install");
5
+
6
+ async function main() {
7
+ let binaryPath;
8
+ try {
9
+ binaryPath = await ensureBinaryInstalled();
10
+ } catch (error) {
11
+ const message = error instanceof Error ? error.message : String(error);
12
+ console.error(`clawreform npm launcher failed to install runtime binary: ${message}`);
13
+ process.exit(1);
14
+ }
15
+
16
+ const result = spawnSync(binaryPath, process.argv.slice(2), {
17
+ stdio: "inherit",
18
+ env: process.env
19
+ });
20
+
21
+ if (result.error) {
22
+ console.error(`Failed to run clawreform binary: ${result.error.message}`);
23
+ process.exit(1);
24
+ }
25
+
26
+ process.exit(result.status ?? 1);
27
+ }
28
+
29
+ main();
package/lib/install.js ADDED
@@ -0,0 +1,169 @@
1
+ const fs = require("node:fs");
2
+ const os = require("node:os");
3
+ const path = require("node:path");
4
+ const { spawnSync } = require("node:child_process");
5
+
6
+ const REPO = process.env.CLAWREFORM_NPM_REPO || "aegntic/clawreform";
7
+
8
+ function normalizeVersion(version) {
9
+ if (!version) {
10
+ throw new Error("Missing package version.");
11
+ }
12
+ return version.startsWith("v") ? version : `v${version}`;
13
+ }
14
+
15
+ function resolveTargetFor(platform, arch) {
16
+ if (platform === "linux" && arch === "x64") {
17
+ return { target: "x86_64-unknown-linux-gnu", ext: "tar.gz", binName: "clawreform" };
18
+ }
19
+ if (platform === "linux" && arch === "arm64") {
20
+ return { target: "aarch64-unknown-linux-gnu", ext: "tar.gz", binName: "clawreform" };
21
+ }
22
+ if (platform === "darwin" && arch === "x64") {
23
+ return { target: "x86_64-apple-darwin", ext: "tar.gz", binName: "clawreform" };
24
+ }
25
+ if (platform === "darwin" && arch === "arm64") {
26
+ return { target: "aarch64-apple-darwin", ext: "tar.gz", binName: "clawreform" };
27
+ }
28
+ if (platform === "win32" && arch === "x64") {
29
+ return { target: "x86_64-pc-windows-msvc", ext: "zip", binName: "clawreform.exe" };
30
+ }
31
+ if (platform === "win32" && arch === "arm64") {
32
+ return { target: "aarch64-pc-windows-msvc", ext: "zip", binName: "clawreform.exe" };
33
+ }
34
+
35
+ throw new Error(`Unsupported platform/arch: ${platform}/${arch}`);
36
+ }
37
+
38
+ function resolveTarget() {
39
+ return resolveTargetFor(process.platform, process.arch);
40
+ }
41
+
42
+ function assetUrl(version, target, ext) {
43
+ const file = `clawreform-${target}.${ext}`;
44
+ return `https://github.com/${REPO}/releases/download/${version}/${file}`;
45
+ }
46
+
47
+ async function downloadToFile(url, destination) {
48
+ const response = await fetch(url, {
49
+ headers: {
50
+ "User-Agent": "clawreform-npm-installer"
51
+ }
52
+ });
53
+
54
+ if (!response.ok) {
55
+ throw new Error(`Download failed (${response.status}): ${url}`);
56
+ }
57
+
58
+ const arrayBuffer = await response.arrayBuffer();
59
+ fs.writeFileSync(destination, Buffer.from(arrayBuffer));
60
+ }
61
+
62
+ function extractArchive(archivePath, destinationPath, ext) {
63
+ if (ext === "tar.gz") {
64
+ const result = spawnSync("tar", ["-xzf", archivePath, "-C", destinationPath], {
65
+ stdio: "pipe"
66
+ });
67
+ if (result.status !== 0) {
68
+ throw new Error(`tar extraction failed: ${result.stderr?.toString() || "unknown error"}`);
69
+ }
70
+ return;
71
+ }
72
+
73
+ if (ext === "zip") {
74
+ const psArchive = archivePath.replace(/'/g, "''");
75
+ const psDest = destinationPath.replace(/'/g, "''");
76
+ const psScript = `$ErrorActionPreference='Stop'; Expand-Archive -Path '${psArchive}' -DestinationPath '${psDest}' -Force`;
77
+ const result = spawnSync("powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", psScript], {
78
+ stdio: "pipe"
79
+ });
80
+
81
+ if (result.status === 0) {
82
+ return;
83
+ }
84
+
85
+ const tarResult = spawnSync("tar", ["-xf", archivePath, "-C", destinationPath], {
86
+ stdio: "pipe"
87
+ });
88
+ if (tarResult.status !== 0) {
89
+ const powerShellError = result.stderr?.toString() || "unknown powershell error";
90
+ const tarError = tarResult.stderr?.toString() || "unknown tar error";
91
+ throw new Error(`zip extraction failed. powershell: ${powerShellError}; tar: ${tarError}`);
92
+ }
93
+ return;
94
+ }
95
+
96
+ throw new Error(`Unsupported archive extension: ${ext}`);
97
+ }
98
+
99
+ function findFileRecursively(rootDir, fileName) {
100
+ const entries = fs.readdirSync(rootDir, { withFileTypes: true });
101
+ for (const entry of entries) {
102
+ const fullPath = path.join(rootDir, entry.name);
103
+ if (entry.isFile() && entry.name === fileName) {
104
+ return fullPath;
105
+ }
106
+ if (entry.isDirectory()) {
107
+ const nested = findFileRecursively(fullPath, fileName);
108
+ if (nested) {
109
+ return nested;
110
+ }
111
+ }
112
+ }
113
+ return null;
114
+ }
115
+
116
+ function installedBinaryPath() {
117
+ const binName = process.platform === "win32" ? "clawreform.exe" : "clawreform";
118
+ return path.join(__dirname, "bin", binName);
119
+ }
120
+
121
+ async function installBinary(options = {}) {
122
+ const log = typeof options.log === "function" ? options.log : console.log;
123
+ const version = normalizeVersion(options.version || process.env.CLAWREFORM_VERSION || require("../package.json").version);
124
+ const { target, ext, binName } = resolveTarget();
125
+ const downloadUrl = assetUrl(version, target, ext);
126
+
127
+ const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), "clawreform-npm-"));
128
+ const archivePath = path.join(tmpRoot, `clawreform.${ext}`);
129
+ const extractPath = path.join(tmpRoot, "extract");
130
+ fs.mkdirSync(extractPath, { recursive: true });
131
+
132
+ try {
133
+ log(`clawreform npm: downloading ${version} (${target})`);
134
+ await downloadToFile(downloadUrl, archivePath);
135
+ extractArchive(archivePath, extractPath, ext);
136
+
137
+ const sourceBinary = findFileRecursively(extractPath, binName);
138
+ if (!sourceBinary) {
139
+ throw new Error(`Could not find ${binName} in downloaded archive.`);
140
+ }
141
+
142
+ const destination = installedBinaryPath();
143
+ fs.mkdirSync(path.dirname(destination), { recursive: true });
144
+ fs.copyFileSync(sourceBinary, destination);
145
+ if (process.platform !== "win32") {
146
+ fs.chmodSync(destination, 0o755);
147
+ }
148
+
149
+ return destination;
150
+ } finally {
151
+ fs.rmSync(tmpRoot, { recursive: true, force: true });
152
+ }
153
+ }
154
+
155
+ async function ensureBinaryInstalled() {
156
+ const destination = installedBinaryPath();
157
+ if (fs.existsSync(destination)) {
158
+ return destination;
159
+ }
160
+ return installBinary();
161
+ }
162
+
163
+ module.exports = {
164
+ ensureBinaryInstalled,
165
+ installBinary,
166
+ installedBinaryPath,
167
+ resolveTargetFor,
168
+ resolveTarget
169
+ };
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "clawreform",
3
+ "version": "0.3.1",
4
+ "description": "Cross-platform npm launcher for clawREFORM by aegntic.ai CLI",
5
+ "license": "MIT",
6
+ "author": "clawREFORM by aegntic.ai Team",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/aegntic/clawreform"
10
+ },
11
+ "bugs": {
12
+ "url": "https://github.com/aegntic/clawreform/issues"
13
+ },
14
+ "homepage": "https://clawreform.com",
15
+ "keywords": [
16
+ "clawreform",
17
+ "agent",
18
+ "ai",
19
+ "cli",
20
+ "agent-os"
21
+ ],
22
+ "engines": {
23
+ "node": ">=18.0.0"
24
+ },
25
+ "bin": {
26
+ "clawreform": "./bin/clawreform.js"
27
+ },
28
+ "scripts": {
29
+ "postinstall": "node ./scripts/postinstall.js"
30
+ },
31
+ "files": [
32
+ "README.md",
33
+ "bin",
34
+ "lib/install.js",
35
+ "scripts"
36
+ ],
37
+ "publishConfig": {
38
+ "access": "public"
39
+ }
40
+ }
@@ -0,0 +1,43 @@
1
+ #!/usr/bin/env node
2
+
3
+ const path = require("node:path");
4
+ const { installBinary } = require("../lib/install");
5
+
6
+ function globalBinDir() {
7
+ const prefix = process.env.npm_config_prefix;
8
+ if (!prefix) {
9
+ return null;
10
+ }
11
+ return process.platform === "win32" ? prefix : path.join(prefix, "bin");
12
+ }
13
+
14
+ function pathContains(targetDir) {
15
+ if (!targetDir) {
16
+ return false;
17
+ }
18
+ const pathValue = process.env.PATH || "";
19
+ const entries = pathValue.split(path.delimiter).filter(Boolean);
20
+ return entries.includes(targetDir);
21
+ }
22
+
23
+ async function main() {
24
+ try {
25
+ await installBinary();
26
+ const binDir = globalBinDir();
27
+ if (binDir && !pathContains(binDir)) {
28
+ if (process.platform === "win32") {
29
+ console.warn(`clawreform npm: global npm bin is not on PATH: ${binDir}`);
30
+ console.warn("Open a new terminal or add it to your user PATH in System Settings.");
31
+ } else {
32
+ console.warn(`clawreform npm: global npm bin is not on PATH: ${binDir}`);
33
+ console.warn(`Add it with: export PATH="${binDir}:$PATH"`);
34
+ }
35
+ }
36
+ } catch (error) {
37
+ const message = error instanceof Error ? error.message : String(error);
38
+ console.error(`clawreform npm postinstall failed: ${message}`);
39
+ process.exit(1);
40
+ }
41
+ }
42
+
43
+ main();