pandash-cli 0.2.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/bin/cli.js +65 -0
- package/package.json +23 -0
- package/scripts/install.js +172 -0
package/bin/cli.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const { execSync, spawn } = require("child_process");
|
|
3
|
+
const path = require("path");
|
|
4
|
+
const fs = require("fs");
|
|
5
|
+
|
|
6
|
+
const APP_NAME = "Pandash";
|
|
7
|
+
|
|
8
|
+
function findApp() {
|
|
9
|
+
const platform = process.platform;
|
|
10
|
+
|
|
11
|
+
switch (platform) {
|
|
12
|
+
case "win32": {
|
|
13
|
+
// Check common install locations
|
|
14
|
+
const paths = [
|
|
15
|
+
path.join(process.env.LOCALAPPDATA || "", "Pandash", "pandash.exe"),
|
|
16
|
+
path.join(process.env.PROGRAMFILES || "", "Pandash", "pandash.exe"),
|
|
17
|
+
];
|
|
18
|
+
for (const p of paths) {
|
|
19
|
+
if (fs.existsSync(p)) return p;
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
case "darwin": {
|
|
24
|
+
const appPath = "/Applications/Pandash.app/Contents/MacOS/Pandash";
|
|
25
|
+
return fs.existsSync(appPath) ? appPath : null;
|
|
26
|
+
}
|
|
27
|
+
case "linux": {
|
|
28
|
+
// Check if pandash is in PATH
|
|
29
|
+
try {
|
|
30
|
+
const result = execSync("which pandash 2>/dev/null", { encoding: "utf8" }).trim();
|
|
31
|
+
if (result) return result;
|
|
32
|
+
} catch {}
|
|
33
|
+
// Check common locations
|
|
34
|
+
const paths = [
|
|
35
|
+
"/usr/bin/pandash",
|
|
36
|
+
"/usr/local/bin/pandash",
|
|
37
|
+
path.join(process.env.HOME || "", ".local", "bin", "pandash"),
|
|
38
|
+
];
|
|
39
|
+
for (const p of paths) {
|
|
40
|
+
if (fs.existsSync(p)) return p;
|
|
41
|
+
}
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
default:
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const appPath = findApp();
|
|
50
|
+
|
|
51
|
+
if (!appPath) {
|
|
52
|
+
console.error(`${APP_NAME} is not installed.`);
|
|
53
|
+
console.error("Run: npm install -g pandash");
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Launch the app, passing through all arguments
|
|
58
|
+
const child = spawn(appPath, process.argv.slice(2), {
|
|
59
|
+
stdio: "inherit",
|
|
60
|
+
detached: process.platform !== "win32",
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// Don't wait for the GUI app to exit
|
|
64
|
+
child.unref();
|
|
65
|
+
setTimeout(() => process.exit(0), 500);
|
package/package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "pandash-cli",
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "Multi-Terminal & Claude Code Manager",
|
|
5
|
+
"keywords": ["terminal", "claude", "ai", "dev-tools", "tauri"],
|
|
6
|
+
"homepage": "https://pandash.dev",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/rchernando/pandash"
|
|
10
|
+
},
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"author": "rchernando",
|
|
13
|
+
"bin": {
|
|
14
|
+
"pandash": "./bin/cli.js"
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"postinstall": "node scripts/install.js"
|
|
18
|
+
},
|
|
19
|
+
"os": ["win32", "darwin", "linux"],
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": ">=18"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const https = require("https");
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const { execSync } = require("child_process");
|
|
6
|
+
|
|
7
|
+
const API_URL = "https://pandash.dev/api/downloads";
|
|
8
|
+
const BIN_DIR = path.join(__dirname, "..", "bin");
|
|
9
|
+
|
|
10
|
+
function getPlatformKey() {
|
|
11
|
+
const platform = process.platform;
|
|
12
|
+
const arch = process.arch;
|
|
13
|
+
|
|
14
|
+
switch (platform) {
|
|
15
|
+
case "win32":
|
|
16
|
+
return "win32-x64";
|
|
17
|
+
case "darwin":
|
|
18
|
+
return arch === "arm64" ? "darwin-arm64" : "darwin-x64";
|
|
19
|
+
case "linux":
|
|
20
|
+
return "linux-x64";
|
|
21
|
+
default:
|
|
22
|
+
throw new Error(`Unsupported platform: ${platform}`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function fetchJSON(url) {
|
|
27
|
+
return new Promise((resolve, reject) => {
|
|
28
|
+
const get = (u) => {
|
|
29
|
+
https
|
|
30
|
+
.get(u, { headers: { "User-Agent": "pandash-npm" } }, (res) => {
|
|
31
|
+
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
32
|
+
get(res.headers.location);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
let data = "";
|
|
36
|
+
res.on("data", (chunk) => (data += chunk));
|
|
37
|
+
res.on("end", () => {
|
|
38
|
+
try {
|
|
39
|
+
resolve(JSON.parse(data));
|
|
40
|
+
} catch (e) {
|
|
41
|
+
reject(new Error(`Invalid JSON response from ${u}`));
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
})
|
|
45
|
+
.on("error", reject);
|
|
46
|
+
};
|
|
47
|
+
get(url);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function download(url, dest) {
|
|
52
|
+
return new Promise((resolve, reject) => {
|
|
53
|
+
const get = (u) => {
|
|
54
|
+
const mod = u.startsWith("https") ? https : require("http");
|
|
55
|
+
mod
|
|
56
|
+
.get(u, { headers: { "User-Agent": "pandash-npm" } }, (res) => {
|
|
57
|
+
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
58
|
+
get(res.headers.location);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (res.statusCode !== 200) {
|
|
62
|
+
reject(new Error(`Download failed: HTTP ${res.statusCode}`));
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const file = fs.createWriteStream(dest);
|
|
66
|
+
res.pipe(file);
|
|
67
|
+
file.on("finish", () => file.close(resolve));
|
|
68
|
+
})
|
|
69
|
+
.on("error", reject);
|
|
70
|
+
};
|
|
71
|
+
get(url);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async function main() {
|
|
76
|
+
const platformKey = getPlatformKey();
|
|
77
|
+
console.log(`\n Pandash: installing for ${platformKey}...\n`);
|
|
78
|
+
|
|
79
|
+
// Fetch latest release info from pandash.dev API
|
|
80
|
+
let release;
|
|
81
|
+
try {
|
|
82
|
+
release = await fetchJSON(`${API_URL}/latest`);
|
|
83
|
+
} catch (e) {
|
|
84
|
+
console.log(" Could not reach pandash.dev. Skipping binary download.");
|
|
85
|
+
console.log(" You can download manually from https://pandash.dev/download\n");
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
console.log(` Latest version: ${release.version}`);
|
|
90
|
+
|
|
91
|
+
const platform = release.platforms[platformKey];
|
|
92
|
+
if (!platform) {
|
|
93
|
+
console.log(` No binary available for ${platformKey} yet.`);
|
|
94
|
+
console.log(" Download manually from https://pandash.dev/download\n");
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const dest = path.join(BIN_DIR, platform.name);
|
|
99
|
+
fs.mkdirSync(BIN_DIR, { recursive: true });
|
|
100
|
+
|
|
101
|
+
console.log(` Downloading ${platform.name}...`);
|
|
102
|
+
await download(platform.url, dest);
|
|
103
|
+
console.log(" Download complete");
|
|
104
|
+
|
|
105
|
+
// Platform-specific install
|
|
106
|
+
if (process.platform === "win32") {
|
|
107
|
+
console.log(" Installing...");
|
|
108
|
+
try {
|
|
109
|
+
execSync(`"${dest}" /S`, { stdio: "inherit" });
|
|
110
|
+
// Add to PATH
|
|
111
|
+
const installDir = path.join(process.env.LOCALAPPDATA || "", "Pandash");
|
|
112
|
+
try {
|
|
113
|
+
const currentPath = execSync(
|
|
114
|
+
'powershell -c "[Environment]::GetEnvironmentVariable(\'Path\', \'User\')"',
|
|
115
|
+
{ encoding: "utf8" }
|
|
116
|
+
).trim();
|
|
117
|
+
if (!currentPath.includes(installDir)) {
|
|
118
|
+
execSync(
|
|
119
|
+
`powershell -c "[Environment]::SetEnvironmentVariable('Path', '${currentPath};${installDir}', 'User')"`,
|
|
120
|
+
{ stdio: "inherit" }
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
} catch {}
|
|
124
|
+
console.log("\n Pandash installed successfully!");
|
|
125
|
+
console.log(" Open a new terminal and run: pandash\n");
|
|
126
|
+
} catch {
|
|
127
|
+
console.log(`\n Run the installer manually: ${dest}\n`);
|
|
128
|
+
}
|
|
129
|
+
try { fs.unlinkSync(dest); } catch {}
|
|
130
|
+
} else if (process.platform === "darwin") {
|
|
131
|
+
console.log(" Installing to /Applications...");
|
|
132
|
+
try {
|
|
133
|
+
execSync(`hdiutil attach "${dest}" -quiet`);
|
|
134
|
+
execSync(`cp -R "/Volumes/Pandash/Pandash.app" /Applications/ 2>/dev/null || cp -R "/Volumes/Pandash/"*.app /Applications/`);
|
|
135
|
+
execSync(`hdiutil detach "/Volumes/Pandash" -quiet`);
|
|
136
|
+
console.log("\n Pandash installed to /Applications!\n");
|
|
137
|
+
} catch {
|
|
138
|
+
console.log(`\n Open the DMG manually: open "${dest}"\n`);
|
|
139
|
+
}
|
|
140
|
+
try { fs.unlinkSync(dest); } catch {}
|
|
141
|
+
} else if (process.platform === "linux") {
|
|
142
|
+
if (platform.name.endsWith(".deb")) {
|
|
143
|
+
console.log(" Installing .deb package...");
|
|
144
|
+
try {
|
|
145
|
+
execSync(`sudo dpkg -i "${dest}" 2>/dev/null || sudo apt-get install -f -y`, {
|
|
146
|
+
stdio: "inherit",
|
|
147
|
+
});
|
|
148
|
+
console.log("\n Pandash installed! Run: pandash\n");
|
|
149
|
+
} catch {
|
|
150
|
+
console.log(`\n Install manually: sudo dpkg -i ${dest}\n`);
|
|
151
|
+
}
|
|
152
|
+
try { fs.unlinkSync(dest); } catch {}
|
|
153
|
+
} else {
|
|
154
|
+
// AppImage
|
|
155
|
+
const localBin = path.join(process.env.HOME || "", ".local", "bin");
|
|
156
|
+
fs.mkdirSync(localBin, { recursive: true });
|
|
157
|
+
const appDest = path.join(localBin, "pandash");
|
|
158
|
+
fs.renameSync(dest, appDest);
|
|
159
|
+
fs.chmodSync(appDest, 0o755);
|
|
160
|
+
console.log(`\n Pandash installed to ${appDest}`);
|
|
161
|
+
console.log(" Make sure ~/.local/bin is in your PATH\n");
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Write version file
|
|
166
|
+
fs.writeFileSync(path.join(BIN_DIR, ".version"), release.version);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
main().catch((err) => {
|
|
170
|
+
console.error(" Install error:", err.message);
|
|
171
|
+
console.log(" Download manually from https://pandash.dev/download\n");
|
|
172
|
+
});
|