claude-smart 0.1.15 → 0.1.17
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 +1 -1
- package/bin/claude-smart.js +87 -25
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
<img src="https://img.shields.io/badge/License-Apache%202.0-blue.svg" alt="License">
|
|
14
14
|
</a>
|
|
15
15
|
<a href="plugin/pyproject.toml">
|
|
16
|
-
<img src="https://img.shields.io/badge/version-0.1.
|
|
16
|
+
<img src="https://img.shields.io/badge/version-0.1.17-green.svg" alt="Version">
|
|
17
17
|
</a>
|
|
18
18
|
<a href="plugin/pyproject.toml">
|
|
19
19
|
<img src="https://img.shields.io/badge/python-%3E%3D3.12-brightgreen.svg" alt="Python">
|
package/bin/claude-smart.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
"use strict";
|
|
11
11
|
|
|
12
|
-
const { execFileSync, execSync } = require("child_process");
|
|
12
|
+
const { execFileSync, execSync, spawn } = require("child_process");
|
|
13
13
|
const { appendFileSync, existsSync, mkdirSync, readFileSync } = require("fs");
|
|
14
14
|
const { homedir } = require("os");
|
|
15
15
|
const { dirname, join } = require("path");
|
|
@@ -18,6 +18,67 @@ const DEFAULT_MARKETPLACE_SOURCE = "ReflexioAI/claude-smart";
|
|
|
18
18
|
const PLUGIN_SPEC = "claude-smart@reflexioai";
|
|
19
19
|
const REFLEXIO_ENV_PATH = join(homedir(), ".reflexio", ".env");
|
|
20
20
|
|
|
21
|
+
function runClaude(args, { spinnerLabel } = {}) {
|
|
22
|
+
const useSpinner = Boolean(spinnerLabel) && process.stdout.isTTY && !process.env.CI;
|
|
23
|
+
return new Promise((resolve) => {
|
|
24
|
+
const child = spawn("claude", args, {
|
|
25
|
+
stdio: useSpinner ? ["inherit", "pipe", "pipe"] : "inherit",
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
if (useSpinner) {
|
|
29
|
+
const frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
30
|
+
let i = 0;
|
|
31
|
+
let spinTimer = null;
|
|
32
|
+
let rearmTimer = null;
|
|
33
|
+
let exited = false;
|
|
34
|
+
|
|
35
|
+
const draw = () => {
|
|
36
|
+
process.stdout.write(`\r⠿ ${spinnerLabel}`.replace("⠿", frames[i = (i + 1) % frames.length]));
|
|
37
|
+
};
|
|
38
|
+
const clearLine = () => process.stdout.write("\r\x1b[2K");
|
|
39
|
+
const startSpin = () => {
|
|
40
|
+
if (spinTimer || exited) return;
|
|
41
|
+
draw();
|
|
42
|
+
spinTimer = setInterval(draw, 80);
|
|
43
|
+
};
|
|
44
|
+
const stopSpin = () => {
|
|
45
|
+
if (!spinTimer) return;
|
|
46
|
+
clearInterval(spinTimer);
|
|
47
|
+
spinTimer = null;
|
|
48
|
+
clearLine();
|
|
49
|
+
};
|
|
50
|
+
const armRearm = () => {
|
|
51
|
+
if (rearmTimer) clearTimeout(rearmTimer);
|
|
52
|
+
rearmTimer = setTimeout(() => {
|
|
53
|
+
rearmTimer = null;
|
|
54
|
+
startSpin();
|
|
55
|
+
}, 200);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
startSpin();
|
|
59
|
+
|
|
60
|
+
const passthrough = (stream) => (chunk) => {
|
|
61
|
+
stopSpin();
|
|
62
|
+
stream.write(chunk);
|
|
63
|
+
armRearm();
|
|
64
|
+
};
|
|
65
|
+
child.stdout.on("data", passthrough(process.stdout));
|
|
66
|
+
child.stderr.on("data", passthrough(process.stderr));
|
|
67
|
+
child.on("exit", () => {
|
|
68
|
+
exited = true;
|
|
69
|
+
if (rearmTimer) {
|
|
70
|
+
clearTimeout(rearmTimer);
|
|
71
|
+
rearmTimer = null;
|
|
72
|
+
}
|
|
73
|
+
stopSpin();
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
child.on("exit", (code) => resolve(typeof code === "number" ? code : 1));
|
|
78
|
+
child.on("error", () => resolve(1));
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
21
82
|
function hasClaudeCli() {
|
|
22
83
|
const probe = process.platform === "win32" ? "where claude" : "command -v claude";
|
|
23
84
|
try {
|
|
@@ -79,7 +140,7 @@ function parseSource(args) {
|
|
|
79
140
|
return value;
|
|
80
141
|
}
|
|
81
142
|
|
|
82
|
-
function runUpdate() {
|
|
143
|
+
async function runUpdate() {
|
|
83
144
|
if (!hasClaudeCli()) {
|
|
84
145
|
process.stderr.write(
|
|
85
146
|
"error: 'claude' CLI not found on PATH. " +
|
|
@@ -88,10 +149,10 @@ function runUpdate() {
|
|
|
88
149
|
process.exit(1);
|
|
89
150
|
}
|
|
90
151
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
|
|
152
|
+
const code = await runClaude(["plugin", "update", PLUGIN_SPEC], {
|
|
153
|
+
spinnerLabel: "Checking for claude-smart updates…",
|
|
154
|
+
});
|
|
155
|
+
if (code !== 0) {
|
|
95
156
|
process.stderr.write(`error: \`claude plugin update ${PLUGIN_SPEC}\` failed (exit ${code})\n`);
|
|
96
157
|
process.exit(code);
|
|
97
158
|
}
|
|
@@ -99,7 +160,7 @@ function runUpdate() {
|
|
|
99
160
|
process.stdout.write("\nclaude-smart updated. Restart Claude Code to apply.\n");
|
|
100
161
|
}
|
|
101
162
|
|
|
102
|
-
function runUninstall() {
|
|
163
|
+
async function runUninstall() {
|
|
103
164
|
if (!hasClaudeCli()) {
|
|
104
165
|
process.stderr.write(
|
|
105
166
|
"error: 'claude' CLI not found on PATH. " +
|
|
@@ -108,10 +169,10 @@ function runUninstall() {
|
|
|
108
169
|
process.exit(1);
|
|
109
170
|
}
|
|
110
171
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
}
|
|
114
|
-
|
|
172
|
+
const code = await runClaude(["plugin", "uninstall", PLUGIN_SPEC], {
|
|
173
|
+
spinnerLabel: "Uninstalling claude-smart…",
|
|
174
|
+
});
|
|
175
|
+
if (code !== 0) {
|
|
115
176
|
process.stderr.write(
|
|
116
177
|
`error: \`claude plugin uninstall ${PLUGIN_SPEC}\` failed (exit ${code})\n`,
|
|
117
178
|
);
|
|
@@ -128,7 +189,7 @@ function runUninstall() {
|
|
|
128
189
|
);
|
|
129
190
|
}
|
|
130
191
|
|
|
131
|
-
function runInstall(args) {
|
|
192
|
+
async function runInstall(args) {
|
|
132
193
|
if (!hasClaudeCli()) {
|
|
133
194
|
process.stderr.write(
|
|
134
195
|
"error: 'claude' CLI not found on PATH. " +
|
|
@@ -139,17 +200,15 @@ function runInstall(args) {
|
|
|
139
200
|
|
|
140
201
|
const source = parseSource(args);
|
|
141
202
|
const steps = [
|
|
142
|
-
["plugin", "marketplace", "add", source],
|
|
143
|
-
["plugin", "install", PLUGIN_SPEC],
|
|
203
|
+
{ args: ["plugin", "marketplace", "add", source], label: "Adding marketplace…" },
|
|
204
|
+
{ args: ["plugin", "install", PLUGIN_SPEC], label: "Installing claude-smart…" },
|
|
144
205
|
];
|
|
145
206
|
|
|
146
|
-
for (const
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
} catch (err) {
|
|
150
|
-
const code = typeof err.status === "number" ? err.status : 1;
|
|
207
|
+
for (const step of steps) {
|
|
208
|
+
const code = await runClaude(step.args, { spinnerLabel: step.label });
|
|
209
|
+
if (code !== 0) {
|
|
151
210
|
process.stderr.write(
|
|
152
|
-
`error: \`claude ${
|
|
211
|
+
`error: \`claude ${step.args.join(" ")}\` failed (exit ${code})\n`,
|
|
153
212
|
);
|
|
154
213
|
process.exit(code);
|
|
155
214
|
}
|
|
@@ -173,7 +232,7 @@ function runInstall(args) {
|
|
|
173
232
|
);
|
|
174
233
|
}
|
|
175
234
|
|
|
176
|
-
function main() {
|
|
235
|
+
async function main() {
|
|
177
236
|
const args = process.argv.slice(2);
|
|
178
237
|
const cmd = args[0] || "install";
|
|
179
238
|
|
|
@@ -183,17 +242,17 @@ function main() {
|
|
|
183
242
|
}
|
|
184
243
|
|
|
185
244
|
if (cmd === "install") {
|
|
186
|
-
runInstall(args.slice(1));
|
|
245
|
+
await runInstall(args.slice(1));
|
|
187
246
|
return;
|
|
188
247
|
}
|
|
189
248
|
|
|
190
249
|
if (cmd === "update") {
|
|
191
|
-
runUpdate();
|
|
250
|
+
await runUpdate();
|
|
192
251
|
return;
|
|
193
252
|
}
|
|
194
253
|
|
|
195
254
|
if (cmd === "uninstall") {
|
|
196
|
-
runUninstall();
|
|
255
|
+
await runUninstall();
|
|
197
256
|
return;
|
|
198
257
|
}
|
|
199
258
|
|
|
@@ -203,4 +262,7 @@ function main() {
|
|
|
203
262
|
process.exit(1);
|
|
204
263
|
}
|
|
205
264
|
|
|
206
|
-
main()
|
|
265
|
+
main().catch((err) => {
|
|
266
|
+
process.stderr.write(`claude-smart: ${err && err.message ? err.message : err}\n`);
|
|
267
|
+
process.exit(1);
|
|
268
|
+
});
|