atlascloud-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.
package/README.md ADDED
@@ -0,0 +1,27 @@
1
+ # @atlascloud/cli
2
+
3
+ AtlasCloud CLI — call LLM, image, and video models from your terminal.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install -g @atlascloud/cli
9
+ ```
10
+
11
+ The postinstall step downloads the prebuilt `atlas` and `atlas-mcp` binaries for your platform from the public GitHub release and verifies the archive against `checksums.txt`.
12
+
13
+ Supported npm platforms: macOS and Linux on x64 or arm64. Windows package-manager support will be added separately.
14
+
15
+ ## Usage
16
+
17
+ ```bash
18
+ atlas auth login
19
+ atlas chat "explain UUID v7"
20
+ atlas generate image google/nano-banana-2/text-to-image -p "a cat"
21
+ atlas --help
22
+ ```
23
+
24
+ ## Links
25
+
26
+ - Releases: https://github.com/AtlasCloudAI/cli/releases
27
+ - AtlasCloud: https://atlascloud.ai
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require("./run.js")("atlas-mcp");
package/bin/atlas.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require("./run.js")("atlas");
package/bin/run.js ADDED
@@ -0,0 +1,56 @@
1
+ const fs = require("fs");
2
+ const path = require("path");
3
+ const { spawn } = require("child_process");
4
+
5
+ function detectPackageManager() {
6
+ const ua = process.env.npm_config_user_agent || "";
7
+ if (ua.startsWith("pnpm/")) return "pnpm";
8
+ if (ua.startsWith("yarn/")) return "yarn";
9
+ if (ua.startsWith("bun/")) return "bun";
10
+ if (ua.startsWith("npm/")) return "npm";
11
+ return "";
12
+ }
13
+
14
+ function readInstallMetadata(vendorDir) {
15
+ const metadataPath = path.join(vendorDir, "install.json");
16
+ if (!fs.existsSync(metadataPath)) {
17
+ return {};
18
+ }
19
+ return JSON.parse(fs.readFileSync(metadataPath, "utf8"));
20
+ }
21
+
22
+ module.exports = function run(binaryName) {
23
+ const vendorDir = path.join(__dirname, "..", "vendor");
24
+ const bin = path.join(vendorDir, binaryName);
25
+
26
+ if (!fs.existsSync(bin)) {
27
+ console.error(
28
+ `@atlascloud/cli: binary not found at ${bin}. Reinstall: npm i -g @atlascloud/cli`
29
+ );
30
+ process.exit(1);
31
+ }
32
+
33
+ const metadata = readInstallMetadata(vendorDir);
34
+ const child = spawn(bin, process.argv.slice(2), {
35
+ stdio: "inherit",
36
+ env: {
37
+ ...process.env,
38
+ ATLAS_INSTALL_METHOD: "npm",
39
+ ATLAS_PACKAGE_MANAGER:
40
+ metadata.package_manager || detectPackageManager() || "npm"
41
+ }
42
+ });
43
+
44
+ child.on("exit", (code, signal) => {
45
+ if (signal) {
46
+ process.kill(process.pid, signal);
47
+ return;
48
+ }
49
+ process.exit(code == null ? 0 : code);
50
+ });
51
+
52
+ child.on("error", (err) => {
53
+ console.error("@atlascloud/cli: failed to exec:", err.message);
54
+ process.exit(1);
55
+ });
56
+ };
package/install.js ADDED
@@ -0,0 +1,162 @@
1
+ #!/usr/bin/env node
2
+ const crypto = require("crypto");
3
+ const fs = require("fs");
4
+ const https = require("https");
5
+ const path = require("path");
6
+ const { execFileSync } = require("child_process");
7
+
8
+ const pkg = require("./package.json");
9
+
10
+ const REPO = process.env.ATLAS_RELEASE_REPO || "AtlasCloudAI/cli";
11
+ const VERSION = process.env.ATLAS_CLI_VERSION || pkg.version;
12
+
13
+ const PLATFORM_MAP = {
14
+ darwin: "darwin",
15
+ linux: "linux"
16
+ };
17
+ const ARCH_MAP = {
18
+ x64: "amd64",
19
+ arm64: "arm64"
20
+ };
21
+
22
+ const platform = PLATFORM_MAP[process.platform];
23
+ const arch = ARCH_MAP[process.arch];
24
+
25
+ if (!platform || !arch) {
26
+ console.error(
27
+ `@atlascloud/cli: unsupported platform ${process.platform}/${process.arch}`
28
+ );
29
+ console.error("Supported: darwin|linux x x64|arm64");
30
+ process.exit(1);
31
+ }
32
+
33
+ if (VERSION === "0.0.0") {
34
+ console.error(
35
+ "@atlascloud/cli: package version is 0.0.0; publish with the release tag version"
36
+ );
37
+ process.exit(1);
38
+ }
39
+
40
+ const tag = `v${VERSION}`;
41
+ const archiveName = `cli_${VERSION}_${platform}_${arch}.tar.gz`;
42
+ const releaseBase = `https://github.com/${REPO}/releases/download/${tag}`;
43
+ const archiveURL = `${releaseBase}/${archiveName}`;
44
+ const checksumsURL = `${releaseBase}/checksums.txt`;
45
+
46
+ const vendorDir = path.join(__dirname, "vendor");
47
+ const archivePath = path.join(vendorDir, archiveName);
48
+ const checksumsPath = path.join(vendorDir, "checksums.txt");
49
+ const metadataPath = path.join(vendorDir, "install.json");
50
+
51
+ function detectPackageManager() {
52
+ const ua = process.env.npm_config_user_agent || "";
53
+ if (ua.startsWith("pnpm/")) return "pnpm";
54
+ if (ua.startsWith("yarn/")) return "yarn";
55
+ if (ua.startsWith("bun/")) return "bun";
56
+ if (ua.startsWith("npm/")) return "npm";
57
+ return "npm";
58
+ }
59
+
60
+ function download(url, dest, redirects = 0) {
61
+ return new Promise((resolve, reject) => {
62
+ if (redirects > 5) {
63
+ reject(new Error("too many redirects"));
64
+ return;
65
+ }
66
+
67
+ const file = fs.createWriteStream(dest);
68
+ https
69
+ .get(url, (res) => {
70
+ if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
71
+ file.close(() => {
72
+ fs.rmSync(dest, { force: true });
73
+ download(res.headers.location, dest, redirects + 1)
74
+ .then(resolve)
75
+ .catch(reject);
76
+ });
77
+ return;
78
+ }
79
+
80
+ if (res.statusCode !== 200) {
81
+ file.close(() => {
82
+ fs.rmSync(dest, { force: true });
83
+ reject(new Error(`HTTP ${res.statusCode} for ${url}`));
84
+ });
85
+ return;
86
+ }
87
+
88
+ res.pipe(file);
89
+ file.on("finish", () => file.close(resolve));
90
+ })
91
+ .on("error", (err) => {
92
+ file.close(() => {
93
+ fs.rmSync(dest, { force: true });
94
+ reject(err);
95
+ });
96
+ });
97
+ });
98
+ }
99
+
100
+ function expectedChecksum(checksumsText, fileName) {
101
+ const line = checksumsText
102
+ .split(/\r?\n/)
103
+ .find((entry) => entry.trim().split(/\s+/).slice(-1)[0] === fileName);
104
+
105
+ if (!line) {
106
+ throw new Error(`checksum for ${fileName} not found`);
107
+ }
108
+ return line.trim().split(/\s+/)[0];
109
+ }
110
+
111
+ function actualChecksum(filePath) {
112
+ return crypto
113
+ .createHash("sha256")
114
+ .update(fs.readFileSync(filePath))
115
+ .digest("hex");
116
+ }
117
+
118
+ function verifyChecksum() {
119
+ const expected = expectedChecksum(fs.readFileSync(checksumsPath, "utf8"), archiveName);
120
+ const actual = actualChecksum(archivePath);
121
+ if (actual !== expected) {
122
+ throw new Error(
123
+ `checksum mismatch for ${archiveName}: expected ${expected}, got ${actual}`
124
+ );
125
+ }
126
+ }
127
+
128
+ (async () => {
129
+ fs.mkdirSync(vendorDir, { recursive: true });
130
+
131
+ console.log(`@atlascloud/cli: downloading ${archiveURL}`);
132
+ await download(archiveURL, archivePath);
133
+ await download(checksumsURL, checksumsPath);
134
+ verifyChecksum();
135
+
136
+ execFileSync("tar", ["-xzf", archivePath, "-C", vendorDir], {
137
+ stdio: "inherit"
138
+ });
139
+ fs.chmodSync(path.join(vendorDir, "atlas"), 0o755);
140
+ fs.chmodSync(path.join(vendorDir, "atlas-mcp"), 0o755);
141
+
142
+ fs.writeFileSync(
143
+ metadataPath,
144
+ JSON.stringify(
145
+ {
146
+ install_method: "npm",
147
+ package_manager: detectPackageManager(),
148
+ package_name: pkg.name,
149
+ release_repo: REPO,
150
+ version: VERSION
151
+ },
152
+ null,
153
+ 2
154
+ ) + "\n"
155
+ );
156
+ fs.rmSync(archivePath, { force: true });
157
+ fs.rmSync(checksumsPath, { force: true });
158
+ console.log("@atlascloud/cli: installed atlas and atlas-mcp");
159
+ })().catch((err) => {
160
+ console.error("@atlascloud/cli: install failed:", err.message);
161
+ process.exit(1);
162
+ });
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "atlascloud-cli",
3
+ "version": "0.1.1",
4
+ "description": "AtlasCloud CLI — call LLM, image, and video models from your terminal.",
5
+ "bin": {
6
+ "atlas": "bin/atlas.js",
7
+ "atlas-mcp": "bin/atlas-mcp.js"
8
+ },
9
+ "scripts": {
10
+ "postinstall": "node install.js"
11
+ },
12
+ "files": [
13
+ "bin/",
14
+ "install.js",
15
+ "README.md"
16
+ ],
17
+ "engines": {
18
+ "node": ">=14"
19
+ },
20
+ "os": [
21
+ "darwin",
22
+ "linux"
23
+ ],
24
+ "cpu": [
25
+ "x64",
26
+ "arm64"
27
+ ],
28
+ "license": "MIT",
29
+ "homepage": "https://atlascloud.ai",
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "git+https://github.com/AtlasCloudAI/cli.git"
33
+ },
34
+ "publishConfig": {
35
+ "access": "public"
36
+ }
37
+ }