@curdx/flow 7.1.1 → 7.1.2
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/CHANGELOG.md +9 -0
- package/dist/index.mjs +201 -116
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `@curdx/flow` are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/) and the project follows [Semantic Versioning](https://semver.org/).
|
|
4
4
|
|
|
5
|
+
## 7.1.2 — 2026-05-04
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- **Auto-detect-and-install Bun when installing `claude-mem`.** The `claude-mem` plugin's runtime hooks shell out to `node scripts/bun-runner.js` which requires Bun on `PATH` or `~/.bun/bin/bun(.exe)` — Windows users without Bun previously hit `Error: Bun not found` at every Claude Code session start. The installer now runs `ensureBun()` as a `prereqCheck` before installing `claude-mem`: detects Bun via `which`/`where` plus the standard fallback paths (mirrors `bun-runner.js`'s discovery order), and if missing prompts `Auto-install Bun now? (default: No)`. On accept, runs the official installer (`curl -fsSL https://bun.sh/install | bash` on macOS/Linux, `powershell -c "irm bun.sh/install.ps1 | iex"` on Windows). On decline, the installer surfaces a `skip` row for `claude-mem` and continues with the rest of the bundle — other packages are unaffected. Existing users with Bun already installed (e.g. all macOS users who manually ran the installer earlier) see zero behavior change.
|
|
10
|
+
- New module: `src/runner/ensureBun.ts` (~75 LoC) — exports `findBun()` and `ensureBun(t)`.
|
|
11
|
+
- `src/registry/plugins/claude-mem.ts` declares `prereqCheck: (t) => ensureBun(t)` (one-line wire-in via the existing `Pkg.prereqCheck` contract that `chrome-devtools-mcp` already uses).
|
|
12
|
+
- i18n: 9 new `bun.*` keys in `src/i18n/{zh,en}.ts`.
|
|
13
|
+
|
|
5
14
|
## 7.1.1 — 2026-05-04
|
|
6
15
|
|
|
7
16
|
### Fixed
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import * as
|
|
4
|
+
import * as p10 from "@clack/prompts";
|
|
5
5
|
import { defineCommand, runMain } from "citty";
|
|
6
6
|
|
|
7
7
|
// src/ui/language.ts
|
|
@@ -66,6 +66,15 @@ var messages = {
|
|
|
66
66
|
"context7.dashboardHint": "\u53EF\u5728 https://context7.com/dashboard \u521B\u5EFA API Key",
|
|
67
67
|
"chrome.prereqNode": "\u9700\u8981 Node.js >= 20.19\uFF0C\u5F53\u524D\u7248\u672C {current}",
|
|
68
68
|
"chrome.prereqChrome": "\u9700\u8981\u672C\u673A\u5DF2\u5B89\u88C5 Chrome\uFF08chrome-devtools-mcp \u4F1A\u8C03\u7528\u672C\u5730\u6D4F\u89C8\u5668\uFF09",
|
|
69
|
+
"bun.missing": "\u672A\u68C0\u6D4B\u5230 Bun\uFF0Cclaude-mem \u7684\u540E\u53F0 worker \u4F9D\u8D56 Bun \u8FD0\u884C\u3002",
|
|
70
|
+
"bun.installerSource": "Bun \u5B89\u88C5\u811A\u672C\u6765\u6E90\uFF1Ahttps://bun.sh\uFF08macOS/Linux \u7528 curl\uFF0CWindows \u7528 powershell irm\uFF09\u3002",
|
|
71
|
+
"bun.confirmInstall": "\u662F\u5426\u73B0\u5728\u81EA\u52A8\u5B89\u88C5 Bun\uFF1F\uFF08\u9ED8\u8BA4\u5426\u2014\u2014\u9009\u5426\u5C06\u8DF3\u8FC7 claude-mem\uFF0C\u5176\u4ED6\u63D2\u4EF6\u7EE7\u7EED\u5B89\u88C5\uFF09",
|
|
72
|
+
"bun.declined": "\u5DF2\u8DF3\u8FC7 Bun \u5B89\u88C5\uFF1Bclaude-mem \u9700\u8981 Bun\uFF0C\u672C\u6B21\u4E0D\u5B89\u88C5\u3002\u624B\u52A8\u88C5\u597D Bun \u540E\u53EF\u91CD\u8DD1 install\u3002",
|
|
73
|
+
"bun.installing": "\u6B63\u5728\u4E0B\u8F7D\u5E76\u5B89\u88C5 Bun\uFF08\u9996\u6B21\u7EA6 60MB\uFF09\u2026",
|
|
74
|
+
"bun.installed": "Bun \u5B89\u88C5\u5B8C\u6210\u3002",
|
|
75
|
+
"bun.installFailedTitle": "Bun \u5B89\u88C5\u5931\u8D25",
|
|
76
|
+
"bun.installFailedReason": "Bun \u5B89\u88C5\u5931\u8D25\uFF1A{error}",
|
|
77
|
+
"bun.installedButNotFound": "Bun \u5B89\u88C5\u811A\u672C\u58F0\u660E\u6210\u529F\uFF0C\u4F46\u672A\u5728\u5DF2\u77E5\u8DEF\u5F84\u627E\u5230 bun \u53EF\u6267\u884C\u6587\u4EF6\u2014\u2014\u8BF7\u624B\u52A8\u786E\u8BA4\u540E\u91CD\u8DD1\u3002",
|
|
69
78
|
"reinstall.uninstalling": "\u5148\u5378\u8F7D\u65E7\u7248\u672C\u2026",
|
|
70
79
|
"reinstall.installing": "\u5B89\u88C5\u65B0\u7248\u672C\u2026",
|
|
71
80
|
"state.checking": "\u68C0\u67E5\u5DF2\u5B89\u88C5\u72B6\u6001\u2026\uFF08claude plugin list / mcp list\uFF09",
|
|
@@ -138,6 +147,15 @@ var messages2 = {
|
|
|
138
147
|
"context7.dashboardHint": "Get a key at https://context7.com/dashboard",
|
|
139
148
|
"chrome.prereqNode": "Requires Node.js >= 20.19 (current: {current})",
|
|
140
149
|
"chrome.prereqChrome": "Requires Chrome installed locally (chrome-devtools-mcp drives the local browser)",
|
|
150
|
+
"bun.missing": "Bun runtime not found \u2014 claude-mem's background worker requires Bun.",
|
|
151
|
+
"bun.installerSource": "Bun installer source: https://bun.sh (curl on macOS/Linux, PowerShell irm on Windows).",
|
|
152
|
+
"bun.confirmInstall": "Auto-install Bun now? (default: No \u2014 declining will skip claude-mem; other packages continue)",
|
|
153
|
+
"bun.declined": "Bun install declined; claude-mem requires Bun and will be skipped this run. Install Bun manually and re-run install.",
|
|
154
|
+
"bun.installing": "Downloading and installing Bun (~60 MB on first run)\u2026",
|
|
155
|
+
"bun.installed": "Bun installed.",
|
|
156
|
+
"bun.installFailedTitle": "Bun install failed",
|
|
157
|
+
"bun.installFailedReason": "Bun install failed: {error}",
|
|
158
|
+
"bun.installedButNotFound": "Bun installer reported success but bun was not found at any known path \u2014 verify manually and re-run.",
|
|
141
159
|
"reinstall.uninstalling": "Uninstalling old version\u2026",
|
|
142
160
|
"reinstall.installing": "Installing new version\u2026",
|
|
143
161
|
"state.checking": "Checking installed state\u2026 (claude plugin list / mcp list)",
|
|
@@ -196,10 +214,10 @@ async function initLanguage(override) {
|
|
|
196
214
|
}
|
|
197
215
|
|
|
198
216
|
// src/ui/menu.ts
|
|
199
|
-
import * as
|
|
217
|
+
import * as p9 from "@clack/prompts";
|
|
200
218
|
|
|
201
219
|
// src/flows/install.ts
|
|
202
|
-
import * as
|
|
220
|
+
import * as p5 from "@clack/prompts";
|
|
203
221
|
import pc from "picocolors";
|
|
204
222
|
|
|
205
223
|
// src/runner/state.ts
|
|
@@ -218,15 +236,15 @@ async function run(cmd, args) {
|
|
|
218
236
|
stderr: result.stderr
|
|
219
237
|
};
|
|
220
238
|
}
|
|
221
|
-
async function runStreaming(cmd, args,
|
|
222
|
-
|
|
239
|
+
async function runStreaming(cmd, args, log6) {
|
|
240
|
+
log6.message(`$ ${cmd} ${args.join(" ")}`);
|
|
223
241
|
const proc = x(cmd, args, { throwOnError: false });
|
|
224
242
|
let stdout = "";
|
|
225
243
|
for await (const line of proc) {
|
|
226
244
|
const trimmed = line.replace(/\r?\n$/, "");
|
|
227
245
|
if (trimmed.length > 0) {
|
|
228
246
|
stdout += trimmed + "\n";
|
|
229
|
-
|
|
247
|
+
log6.message(trimmed);
|
|
230
248
|
}
|
|
231
249
|
}
|
|
232
250
|
const finished = await proc;
|
|
@@ -269,15 +287,15 @@ async function listPlugins(force = false) {
|
|
|
269
287
|
}
|
|
270
288
|
try {
|
|
271
289
|
const arr = JSON.parse(res.stdout);
|
|
272
|
-
pluginCache = arr.map((
|
|
273
|
-
const [name =
|
|
290
|
+
pluginCache = arr.map((p11) => {
|
|
291
|
+
const [name = p11.id, marketplace = ""] = p11.id.split("@");
|
|
274
292
|
return {
|
|
275
|
-
id:
|
|
293
|
+
id: p11.id,
|
|
276
294
|
name,
|
|
277
295
|
marketplace,
|
|
278
|
-
version:
|
|
279
|
-
scope:
|
|
280
|
-
enabled:
|
|
296
|
+
version: p11.version,
|
|
297
|
+
scope: p11.scope,
|
|
298
|
+
enabled: p11.enabled
|
|
281
299
|
};
|
|
282
300
|
});
|
|
283
301
|
} catch {
|
|
@@ -323,7 +341,7 @@ async function listMcp(force = false) {
|
|
|
323
341
|
}
|
|
324
342
|
async function isPluginInstalled(id) {
|
|
325
343
|
const list = await listPlugins();
|
|
326
|
-
return list.some((
|
|
344
|
+
return list.some((p11) => p11.id === id);
|
|
327
345
|
}
|
|
328
346
|
async function isMarketplaceAdded(name) {
|
|
329
347
|
const list = await listMarketplaces();
|
|
@@ -335,7 +353,7 @@ async function isMcpInstalled(name) {
|
|
|
335
353
|
}
|
|
336
354
|
async function findPlugin(id) {
|
|
337
355
|
const list = await listPlugins();
|
|
338
|
-
return list.find((
|
|
356
|
+
return list.find((p11) => p11.id === id);
|
|
339
357
|
}
|
|
340
358
|
var marketplaceJsonCache = /* @__PURE__ */ new Map();
|
|
341
359
|
function marketplaceDir(name) {
|
|
@@ -357,7 +375,7 @@ async function readMarketplaceJson(name) {
|
|
|
357
375
|
async function getMarketplacePluginVersion(marketplaceName, pluginName) {
|
|
358
376
|
const m = await readMarketplaceJson(marketplaceName);
|
|
359
377
|
if (!m?.plugins) return null;
|
|
360
|
-
const entry = m.plugins.find((
|
|
378
|
+
const entry = m.plugins.find((p11) => p11.name === pluginName);
|
|
361
379
|
return entry?.version ?? null;
|
|
362
380
|
}
|
|
363
381
|
var REFRESH_TTL_MS = 60 * 60 * 1e3;
|
|
@@ -478,8 +496,8 @@ var pua = {
|
|
|
478
496
|
marketplaces: () => [MARKETPLACE_NAME],
|
|
479
497
|
isInstalled: () => isPluginInstalled(PLUGIN_ID),
|
|
480
498
|
installedVersion: async () => {
|
|
481
|
-
const
|
|
482
|
-
const v =
|
|
499
|
+
const p11 = await findPlugin(PLUGIN_ID);
|
|
500
|
+
const v = p11?.version;
|
|
483
501
|
return v && v !== "unknown" ? v : null;
|
|
484
502
|
},
|
|
485
503
|
latestVersion: () => getMarketplacePluginVersion(MARKETPLACE_NAME, PLUGIN_NAME),
|
|
@@ -492,6 +510,72 @@ var pua = {
|
|
|
492
510
|
};
|
|
493
511
|
var pua_default = pua;
|
|
494
512
|
|
|
513
|
+
// src/runner/ensureBun.ts
|
|
514
|
+
import { existsSync } from "fs";
|
|
515
|
+
import { homedir } from "os";
|
|
516
|
+
import path2 from "path";
|
|
517
|
+
import * as p2 from "@clack/prompts";
|
|
518
|
+
var IS_WINDOWS = process.platform === "win32";
|
|
519
|
+
function fallbackPaths() {
|
|
520
|
+
const home = homedir();
|
|
521
|
+
if (IS_WINDOWS) return [path2.join(home, ".bun", "bin", "bun.exe")];
|
|
522
|
+
return [
|
|
523
|
+
path2.join(home, ".bun", "bin", "bun"),
|
|
524
|
+
"/usr/local/bin/bun",
|
|
525
|
+
"/opt/homebrew/bin/bun",
|
|
526
|
+
"/home/linuxbrew/.linuxbrew/bin/bun"
|
|
527
|
+
];
|
|
528
|
+
}
|
|
529
|
+
async function findBun() {
|
|
530
|
+
const probe = IS_WINDOWS ? await run("where", ["bun"]) : await run("which", ["bun"]);
|
|
531
|
+
if (probe.exitCode === 0 && probe.stdout.trim()) {
|
|
532
|
+
const lines = probe.stdout.split(/\r?\n/).map((l) => l.trim()).filter(Boolean);
|
|
533
|
+
if (IS_WINDOWS) {
|
|
534
|
+
const cmd = lines.find((l) => l.toLowerCase().endsWith("bun.cmd") || l.toLowerCase().endsWith("bun.exe"));
|
|
535
|
+
if (cmd) return cmd;
|
|
536
|
+
}
|
|
537
|
+
if (lines[0]) return lines[0];
|
|
538
|
+
}
|
|
539
|
+
for (const candidate of fallbackPaths()) {
|
|
540
|
+
if (existsSync(candidate)) return candidate;
|
|
541
|
+
}
|
|
542
|
+
return null;
|
|
543
|
+
}
|
|
544
|
+
async function runInstaller() {
|
|
545
|
+
const result = IS_WINDOWS ? await run("powershell", ["-NoProfile", "-Command", "irm bun.sh/install.ps1 | iex"]) : await run("bash", ["-lc", "curl -fsSL https://bun.sh/install | bash"]);
|
|
546
|
+
if (result.exitCode !== 0) {
|
|
547
|
+
const detail = (result.stderr || result.stdout || "").trim().slice(0, 500);
|
|
548
|
+
return { ok: false, error: detail || `exit ${result.exitCode}` };
|
|
549
|
+
}
|
|
550
|
+
return { ok: true };
|
|
551
|
+
}
|
|
552
|
+
async function ensureBun(t2) {
|
|
553
|
+
const found = await findBun();
|
|
554
|
+
if (found) return { ok: true };
|
|
555
|
+
p2.log.warn(t2("bun.missing"));
|
|
556
|
+
p2.log.info(t2("bun.installerSource"));
|
|
557
|
+
const ans = await p2.confirm({
|
|
558
|
+
message: t2("bun.confirmInstall"),
|
|
559
|
+
initialValue: false
|
|
560
|
+
});
|
|
561
|
+
if (p2.isCancel(ans) || ans === false) {
|
|
562
|
+
return { ok: false, reason: t2("bun.declined") };
|
|
563
|
+
}
|
|
564
|
+
const sp = p2.spinner();
|
|
565
|
+
sp.start(t2("bun.installing"));
|
|
566
|
+
const result = await runInstaller();
|
|
567
|
+
if (!result.ok) {
|
|
568
|
+
sp.stop(t2("bun.installFailedTitle"));
|
|
569
|
+
return { ok: false, reason: t2("bun.installFailedReason", { error: result.error }) };
|
|
570
|
+
}
|
|
571
|
+
sp.stop(t2("bun.installed"));
|
|
572
|
+
const reFound = await findBun();
|
|
573
|
+
if (!reFound) {
|
|
574
|
+
return { ok: false, reason: t2("bun.installedButNotFound") };
|
|
575
|
+
}
|
|
576
|
+
return { ok: true };
|
|
577
|
+
}
|
|
578
|
+
|
|
495
579
|
// src/registry/plugins/claude-mem.ts
|
|
496
580
|
var PLUGIN_ID2 = "claude-mem@thedotmack";
|
|
497
581
|
var PLUGIN_NAME2 = "claude-mem";
|
|
@@ -505,10 +589,11 @@ var claudeMem = {
|
|
|
505
589
|
slashNamespace: "/claude-mem:*",
|
|
506
590
|
whenToUse: 'for cross-session memory search ("did we solve this before?"), phased planning (`make-plan`), or phased execution (`do`).',
|
|
507
591
|
marketplaces: () => [MARKETPLACE_NAME2],
|
|
592
|
+
prereqCheck: (t2) => ensureBun(t2),
|
|
508
593
|
isInstalled: () => isPluginInstalled(PLUGIN_ID2),
|
|
509
594
|
installedVersion: async () => {
|
|
510
|
-
const
|
|
511
|
-
const v =
|
|
595
|
+
const p11 = await findPlugin(PLUGIN_ID2);
|
|
596
|
+
const v = p11?.version;
|
|
512
597
|
return v && v !== "unknown" ? v : null;
|
|
513
598
|
},
|
|
514
599
|
latestVersion: () => getMarketplacePluginVersion(MARKETPLACE_NAME2, PLUGIN_NAME2),
|
|
@@ -522,32 +607,32 @@ var claudeMem = {
|
|
|
522
607
|
var claude_mem_default = claudeMem;
|
|
523
608
|
|
|
524
609
|
// src/registry/plugins/chrome-devtools-mcp.ts
|
|
525
|
-
import { existsSync } from "fs";
|
|
526
|
-
import
|
|
610
|
+
import { existsSync as existsSync2 } from "fs";
|
|
611
|
+
import path3 from "path";
|
|
527
612
|
var PLUGIN_ID3 = "chrome-devtools-mcp@chrome-devtools-plugins";
|
|
528
613
|
var MARKETPLACE_NAME3 = "chrome-devtools-plugins";
|
|
529
614
|
var MARKETPLACE_SOURCE3 = "ChromeDevTools/chrome-devtools-mcp";
|
|
530
615
|
async function checkChrome() {
|
|
531
|
-
if (process.env.CHROME_PATH &&
|
|
616
|
+
if (process.env.CHROME_PATH && existsSync2(process.env.CHROME_PATH)) return true;
|
|
532
617
|
if (process.platform === "win32") {
|
|
533
618
|
const suffixes = [
|
|
534
|
-
|
|
535
|
-
|
|
619
|
+
path3.join("Google", "Chrome SxS", "Application", "chrome.exe"),
|
|
620
|
+
path3.join("Google", "Chrome", "Application", "chrome.exe")
|
|
536
621
|
];
|
|
537
622
|
const prefixes = [
|
|
538
623
|
process.env.LOCALAPPDATA,
|
|
539
624
|
process.env.PROGRAMFILES,
|
|
540
625
|
process.env["PROGRAMFILES(X86)"]
|
|
541
|
-
].filter((
|
|
626
|
+
].filter((p11) => Boolean(p11));
|
|
542
627
|
for (const prefix of prefixes) {
|
|
543
628
|
for (const suffix of suffixes) {
|
|
544
|
-
if (
|
|
629
|
+
if (existsSync2(path3.join(prefix, suffix))) return true;
|
|
545
630
|
}
|
|
546
631
|
}
|
|
547
632
|
return false;
|
|
548
633
|
}
|
|
549
634
|
if (process.platform === "darwin") {
|
|
550
|
-
return
|
|
635
|
+
return existsSync2("/Applications/Google Chrome.app/Contents/MacOS/Google Chrome");
|
|
551
636
|
}
|
|
552
637
|
const [viaPath, viaPathChromium] = await Promise.all([
|
|
553
638
|
run("which", ["google-chrome"]),
|
|
@@ -613,8 +698,8 @@ var curdxFlow = {
|
|
|
613
698
|
marketplaces: () => [MARKETPLACE_NAME4],
|
|
614
699
|
isInstalled: () => isPluginInstalled(PLUGIN_ID5),
|
|
615
700
|
installedVersion: async () => {
|
|
616
|
-
const
|
|
617
|
-
const v =
|
|
701
|
+
const p11 = await findPlugin(PLUGIN_ID5);
|
|
702
|
+
const v = p11?.version;
|
|
618
703
|
return v && v !== "unknown" ? v : null;
|
|
619
704
|
},
|
|
620
705
|
latestVersion: () => getMarketplacePluginVersion(MARKETPLACE_NAME4, PLUGIN_NAME3),
|
|
@@ -667,7 +752,7 @@ var sequentialThinking = {
|
|
|
667
752
|
var sequential_thinking_default = sequentialThinking;
|
|
668
753
|
|
|
669
754
|
// src/registry/mcps/context7.ts
|
|
670
|
-
import * as
|
|
755
|
+
import * as p3 from "@clack/prompts";
|
|
671
756
|
var MCP_NAME2 = "context7";
|
|
672
757
|
var URL = "https://mcp.context7.com/mcp";
|
|
673
758
|
var context7 = {
|
|
@@ -678,14 +763,14 @@ var context7 = {
|
|
|
678
763
|
whenToUse: "for any library / SDK / framework / API / Claude Code docs lookup. Use instead of web search.",
|
|
679
764
|
isInstalled: () => isMcpInstalled(MCP_NAME2),
|
|
680
765
|
configPrompts: async ({ t: t2 }) => {
|
|
681
|
-
|
|
766
|
+
p3.note(`${t2("context7.dashboardHint")}
|
|
682
767
|
${t2("context7.keyWarning")}`, "context7");
|
|
683
|
-
const key = await
|
|
768
|
+
const key = await p3.text({
|
|
684
769
|
message: t2("context7.askKey"),
|
|
685
770
|
placeholder: t2("context7.keyPlaceholder"),
|
|
686
771
|
defaultValue: ""
|
|
687
772
|
});
|
|
688
|
-
if (
|
|
773
|
+
if (p3.isCancel(key)) return null;
|
|
689
774
|
const trimmed = String(key ?? "").trim();
|
|
690
775
|
const out = {};
|
|
691
776
|
if (trimmed) out["CONTEXT7_API_KEY"] = trimmed;
|
|
@@ -729,19 +814,19 @@ var PKGS = [
|
|
|
729
814
|
context7_default
|
|
730
815
|
];
|
|
731
816
|
function findPkg(id) {
|
|
732
|
-
return PKGS.find((
|
|
817
|
+
return PKGS.find((p11) => p11.id === id);
|
|
733
818
|
}
|
|
734
819
|
|
|
735
820
|
// src/runner/claudeMd.ts
|
|
736
821
|
import { promises as fs2 } from "fs";
|
|
737
|
-
import
|
|
822
|
+
import path4 from "path";
|
|
738
823
|
import os2 from "os";
|
|
739
|
-
import * as
|
|
824
|
+
import * as p4 from "@clack/prompts";
|
|
740
825
|
var BEGIN_MARKER = "<!-- BEGIN @curdx/flow v1 -->";
|
|
741
826
|
var END_MARKER = "<!-- END @curdx/flow v1 -->";
|
|
742
827
|
var BLOCK_RE = /<!-- BEGIN @curdx\/flow v\d+[^>]*-->[\s\S]*?<!-- END @curdx\/flow v\d+ -->/;
|
|
743
828
|
function claudeMdPath() {
|
|
744
|
-
return
|
|
829
|
+
return path4.join(os2.homedir(), ".claude", "CLAUDE.md");
|
|
745
830
|
}
|
|
746
831
|
function buildCombinationPatterns(ids) {
|
|
747
832
|
const has = (k) => ids.has(k);
|
|
@@ -917,7 +1002,7 @@ async function syncClaudeMd(opts) {
|
|
|
917
1002
|
if (next === existing) {
|
|
918
1003
|
return { status: "unchanged", path: file };
|
|
919
1004
|
}
|
|
920
|
-
await fs2.mkdir(
|
|
1005
|
+
await fs2.mkdir(path4.dirname(file), { recursive: true });
|
|
921
1006
|
const tmp = `${file}.tmp.${process.pid}`;
|
|
922
1007
|
await fs2.writeFile(tmp, next, "utf8");
|
|
923
1008
|
await fs2.rename(tmp, file);
|
|
@@ -931,10 +1016,10 @@ async function syncClaudeMd(opts) {
|
|
|
931
1016
|
}
|
|
932
1017
|
async function syncFromState(opts) {
|
|
933
1018
|
if (opts?.skip) {
|
|
934
|
-
|
|
1019
|
+
p4.log.info(t("claudeMd.skipped"));
|
|
935
1020
|
return;
|
|
936
1021
|
}
|
|
937
|
-
const sp =
|
|
1022
|
+
const sp = p4.spinner();
|
|
938
1023
|
sp.start(t("claudeMd.syncing"));
|
|
939
1024
|
const r = await syncClaudeMd();
|
|
940
1025
|
switch (r.status) {
|
|
@@ -989,7 +1074,7 @@ async function selectInteractive(states) {
|
|
|
989
1074
|
const optionalPkgs = PKGS.filter((pkg) => !pkg.required);
|
|
990
1075
|
if (requiredPkgs.length > 0) {
|
|
991
1076
|
const lines = requiredPkgs.map((pkg) => ` ${stateLabel(pkg, states.get(pkg.id))}`);
|
|
992
|
-
|
|
1077
|
+
p5.note(lines.join("\n"), t("install.requiredHeader"));
|
|
993
1078
|
}
|
|
994
1079
|
const options = optionalPkgs.map((pkg) => {
|
|
995
1080
|
const s = states.get(pkg.id);
|
|
@@ -999,13 +1084,13 @@ async function selectInteractive(states) {
|
|
|
999
1084
|
const s = states.get(pkg.id);
|
|
1000
1085
|
return s.kind === "not_installed" || s.kind === "update_available";
|
|
1001
1086
|
}).map((pkg) => pkg.id);
|
|
1002
|
-
const picked = await
|
|
1087
|
+
const picked = await p5.multiselect({
|
|
1003
1088
|
message: t("install.selectPrompt"),
|
|
1004
1089
|
options,
|
|
1005
1090
|
initialValues,
|
|
1006
1091
|
required: false
|
|
1007
1092
|
});
|
|
1008
|
-
if (
|
|
1093
|
+
if (p5.isCancel(picked)) return null;
|
|
1009
1094
|
const userPicked = picked.map((id) => findPkg(id)).filter((x2) => Boolean(x2));
|
|
1010
1095
|
const requiredAuto = requiredPkgs.filter((pkg) => states.get(pkg.id)?.kind !== "up_to_date");
|
|
1011
1096
|
return [...requiredAuto, ...userPicked];
|
|
@@ -1017,7 +1102,7 @@ function selectFromIds(opts) {
|
|
|
1017
1102
|
for (const id of opts.ids) {
|
|
1018
1103
|
const pkg = findPkg(id);
|
|
1019
1104
|
if (pkg) found.push(pkg);
|
|
1020
|
-
else
|
|
1105
|
+
else p5.log.warn(`Unknown id: ${id}`);
|
|
1021
1106
|
}
|
|
1022
1107
|
return found;
|
|
1023
1108
|
}
|
|
@@ -1029,11 +1114,11 @@ async function runOne(pkg, state, opts) {
|
|
|
1029
1114
|
mode = "update";
|
|
1030
1115
|
} else {
|
|
1031
1116
|
if (!opts.yes) {
|
|
1032
|
-
const ans = await
|
|
1117
|
+
const ans = await p5.confirm({
|
|
1033
1118
|
message: t("install.confirmReinstall", { name: pkg.name }),
|
|
1034
1119
|
initialValue: false
|
|
1035
1120
|
});
|
|
1036
|
-
if (
|
|
1121
|
+
if (p5.isCancel(ans) || ans === false) {
|
|
1037
1122
|
return { id: pkg.id, status: "skip", message: t("install.skippedReinstall", { name: pkg.name }) };
|
|
1038
1123
|
}
|
|
1039
1124
|
}
|
|
@@ -1042,7 +1127,7 @@ async function runOne(pkg, state, opts) {
|
|
|
1042
1127
|
if (pkg.prereqCheck) {
|
|
1043
1128
|
const r = await pkg.prereqCheck(t);
|
|
1044
1129
|
if (!r.ok) {
|
|
1045
|
-
|
|
1130
|
+
p5.log.warn(t("install.prereqFail", { name: pkg.name, reason: r.reason }));
|
|
1046
1131
|
return { id: pkg.id, status: "skip", message: r.reason };
|
|
1047
1132
|
}
|
|
1048
1133
|
}
|
|
@@ -1057,30 +1142,30 @@ async function runOne(pkg, state, opts) {
|
|
|
1057
1142
|
if (mode === "update" && state.kind === "update_available") {
|
|
1058
1143
|
titleVars["version"] = state.latest;
|
|
1059
1144
|
}
|
|
1060
|
-
const
|
|
1145
|
+
const log6 = p5.taskLog({ title: t(titleKey, titleVars) });
|
|
1061
1146
|
try {
|
|
1062
1147
|
if (mode === "reinstall") {
|
|
1063
|
-
|
|
1064
|
-
await pkg.uninstall({ log:
|
|
1065
|
-
|
|
1066
|
-
await pkg.install({ log:
|
|
1148
|
+
log6.message(t("reinstall.uninstalling"));
|
|
1149
|
+
await pkg.uninstall({ log: log6, config, t });
|
|
1150
|
+
log6.message(t("reinstall.installing"));
|
|
1151
|
+
await pkg.install({ log: log6, config, t });
|
|
1067
1152
|
} else if (mode === "update") {
|
|
1068
1153
|
if (pkg.update) {
|
|
1069
|
-
await pkg.update({ log:
|
|
1154
|
+
await pkg.update({ log: log6, config, t });
|
|
1070
1155
|
} else {
|
|
1071
|
-
|
|
1072
|
-
await pkg.uninstall({ log:
|
|
1073
|
-
|
|
1074
|
-
await pkg.install({ log:
|
|
1156
|
+
log6.message(t("reinstall.uninstalling"));
|
|
1157
|
+
await pkg.uninstall({ log: log6, config, t });
|
|
1158
|
+
log6.message(t("reinstall.installing"));
|
|
1159
|
+
await pkg.install({ log: log6, config, t });
|
|
1075
1160
|
}
|
|
1076
1161
|
} else {
|
|
1077
|
-
await pkg.install({ log:
|
|
1162
|
+
await pkg.install({ log: log6, config, t });
|
|
1078
1163
|
}
|
|
1079
|
-
|
|
1164
|
+
log6.success(t("install.success", { name: pkg.name }));
|
|
1080
1165
|
return { id: pkg.id, status: "ok" };
|
|
1081
1166
|
} catch (err) {
|
|
1082
1167
|
const msg = err instanceof Error ? err.message : String(err);
|
|
1083
|
-
|
|
1168
|
+
log6.error(`${t("install.failed", { name: pkg.name })}
|
|
1084
1169
|
${msg}`);
|
|
1085
1170
|
return { id: pkg.id, status: "fail", message: msg };
|
|
1086
1171
|
}
|
|
@@ -1098,7 +1183,7 @@ function summarize(results) {
|
|
|
1098
1183
|
...skip.map((r) => ` ${pc.yellow("-")} ${r.id}${r.message ? pc.dim(` (${r.message})`) : ""}`),
|
|
1099
1184
|
...fail.map((r) => ` ${pc.red("\u2717")} ${r.id}${r.message ? pc.dim(` (${r.message.split("\n")[0]})`) : ""}`)
|
|
1100
1185
|
];
|
|
1101
|
-
|
|
1186
|
+
p5.note(lines.join("\n"), t("install.summaryTitle"));
|
|
1102
1187
|
}
|
|
1103
1188
|
async function maybeRefreshMarketplaces(opts) {
|
|
1104
1189
|
if (opts.noRefresh) return;
|
|
@@ -1107,7 +1192,7 @@ async function maybeRefreshMarketplaces(opts) {
|
|
|
1107
1192
|
if (pkg.marketplaces) for (const n of pkg.marketplaces()) names.add(n);
|
|
1108
1193
|
}
|
|
1109
1194
|
if (names.size === 0) return;
|
|
1110
|
-
const sp =
|
|
1195
|
+
const sp = p5.spinner();
|
|
1111
1196
|
sp.start(t("marketplace.refreshing"));
|
|
1112
1197
|
const refreshed = await refreshMarketplaces([...names]);
|
|
1113
1198
|
sp.stop(
|
|
@@ -1121,7 +1206,7 @@ async function installFlow(opts = {}) {
|
|
|
1121
1206
|
const explicit = opts.all || opts.ids && opts.ids.length > 0;
|
|
1122
1207
|
const candidates = explicit ? selectFromIds(opts) : [...PKGS];
|
|
1123
1208
|
if (candidates.length === 0) {
|
|
1124
|
-
|
|
1209
|
+
p5.log.info(t("install.nothingSelected"));
|
|
1125
1210
|
return;
|
|
1126
1211
|
}
|
|
1127
1212
|
if (opts.ids && opts.ids.length > 0) {
|
|
@@ -1132,7 +1217,7 @@ async function installFlow(opts = {}) {
|
|
|
1132
1217
|
}
|
|
1133
1218
|
}
|
|
1134
1219
|
const stateMap = /* @__PURE__ */ new Map();
|
|
1135
|
-
const sp =
|
|
1220
|
+
const sp = p5.spinner();
|
|
1136
1221
|
sp.start(t("state.checking"));
|
|
1137
1222
|
try {
|
|
1138
1223
|
await Promise.all([listPlugins(), listMcp()]);
|
|
@@ -1160,13 +1245,13 @@ async function installFlow(opts = {}) {
|
|
|
1160
1245
|
const picked = await selectInteractive(stateMap);
|
|
1161
1246
|
if (picked === null) {
|
|
1162
1247
|
userCancelled = true;
|
|
1163
|
-
|
|
1248
|
+
p5.cancel(t("app.cancelled"));
|
|
1164
1249
|
return;
|
|
1165
1250
|
}
|
|
1166
1251
|
targets = picked;
|
|
1167
1252
|
}
|
|
1168
1253
|
if (targets.length === 0) {
|
|
1169
|
-
|
|
1254
|
+
p5.log.info(t("install.nothingSelected"));
|
|
1170
1255
|
return;
|
|
1171
1256
|
}
|
|
1172
1257
|
const results = [];
|
|
@@ -1183,14 +1268,14 @@ async function installFlow(opts = {}) {
|
|
|
1183
1268
|
}
|
|
1184
1269
|
|
|
1185
1270
|
// src/flows/uninstall.ts
|
|
1186
|
-
import * as
|
|
1271
|
+
import * as p6 from "@clack/prompts";
|
|
1187
1272
|
import pc2 from "picocolors";
|
|
1188
1273
|
async function getInstalled() {
|
|
1189
1274
|
const states = await Promise.all(PKGS.map(async (pkg) => ({ pkg, installed: await pkg.isInstalled() })));
|
|
1190
1275
|
return states.filter((s) => s.installed).map((s) => s.pkg);
|
|
1191
1276
|
}
|
|
1192
1277
|
async function probeInstalled() {
|
|
1193
|
-
const sp =
|
|
1278
|
+
const sp = p6.spinner();
|
|
1194
1279
|
sp.start(t("state.checking"));
|
|
1195
1280
|
try {
|
|
1196
1281
|
await Promise.all([listPlugins(), listMcp()]);
|
|
@@ -1212,21 +1297,21 @@ async function uninstallFlow(opts = {}) {
|
|
|
1212
1297
|
for (const id of opts.ids) {
|
|
1213
1298
|
const pkg = findPkg(id);
|
|
1214
1299
|
if (!pkg) {
|
|
1215
|
-
|
|
1300
|
+
p6.log.warn(`Unknown id: ${id}`);
|
|
1216
1301
|
continue;
|
|
1217
1302
|
}
|
|
1218
1303
|
if (!installed.some((x2) => x2.id === pkg.id)) {
|
|
1219
|
-
|
|
1304
|
+
p6.log.warn(`${pkg.name}: ${t("pkg.notInstalled")}`);
|
|
1220
1305
|
continue;
|
|
1221
1306
|
}
|
|
1222
1307
|
targets.push(pkg);
|
|
1223
1308
|
}
|
|
1224
1309
|
} else {
|
|
1225
1310
|
if (installed.length === 0) {
|
|
1226
|
-
|
|
1311
|
+
p6.log.info(t("uninstall.noneInstalled"));
|
|
1227
1312
|
return;
|
|
1228
1313
|
}
|
|
1229
|
-
const picked = await
|
|
1314
|
+
const picked = await p6.multiselect({
|
|
1230
1315
|
message: t("uninstall.selectPrompt"),
|
|
1231
1316
|
options: installed.map((pkg) => ({
|
|
1232
1317
|
value: pkg.id,
|
|
@@ -1235,45 +1320,45 @@ async function uninstallFlow(opts = {}) {
|
|
|
1235
1320
|
})),
|
|
1236
1321
|
required: false
|
|
1237
1322
|
});
|
|
1238
|
-
if (
|
|
1323
|
+
if (p6.isCancel(picked)) {
|
|
1239
1324
|
userCancelled = true;
|
|
1240
|
-
|
|
1325
|
+
p6.cancel(t("app.cancelled"));
|
|
1241
1326
|
return;
|
|
1242
1327
|
}
|
|
1243
1328
|
targets = picked.map((id) => findPkg(id)).filter((x2) => Boolean(x2));
|
|
1244
1329
|
}
|
|
1245
1330
|
if (targets.length === 0) {
|
|
1246
|
-
|
|
1331
|
+
p6.log.info(t("install.nothingSelected"));
|
|
1247
1332
|
return;
|
|
1248
1333
|
}
|
|
1249
1334
|
if (!opts.yes) {
|
|
1250
|
-
const ok2 = await
|
|
1335
|
+
const ok2 = await p6.confirm({
|
|
1251
1336
|
message: t("uninstall.confirm", { count: targets.length }),
|
|
1252
1337
|
initialValue: false
|
|
1253
1338
|
});
|
|
1254
|
-
if (
|
|
1339
|
+
if (p6.isCancel(ok2) || ok2 === false) {
|
|
1255
1340
|
userCancelled = true;
|
|
1256
|
-
|
|
1341
|
+
p6.cancel(t("app.cancelled"));
|
|
1257
1342
|
return;
|
|
1258
1343
|
}
|
|
1259
1344
|
}
|
|
1260
1345
|
const results = [];
|
|
1261
1346
|
for (const pkg of targets) {
|
|
1262
|
-
const
|
|
1347
|
+
const log6 = p6.taskLog({ title: t("uninstall.starting", { name: pkg.name }) });
|
|
1263
1348
|
try {
|
|
1264
|
-
await pkg.uninstall({ log:
|
|
1265
|
-
|
|
1349
|
+
await pkg.uninstall({ log: log6, config: {}, t });
|
|
1350
|
+
log6.success(t("uninstall.success", { name: pkg.name }));
|
|
1266
1351
|
results.push({ id: pkg.id, status: "ok" });
|
|
1267
1352
|
} catch (err) {
|
|
1268
1353
|
const msg = err instanceof Error ? err.message : String(err);
|
|
1269
|
-
|
|
1354
|
+
log6.error(`${t("uninstall.failed", { name: pkg.name })}
|
|
1270
1355
|
${msg}`);
|
|
1271
1356
|
results.push({ id: pkg.id, status: "fail", message: msg });
|
|
1272
1357
|
}
|
|
1273
1358
|
}
|
|
1274
1359
|
const ok = results.filter((r) => r.status === "ok").length;
|
|
1275
1360
|
const fail = results.filter((r) => r.status === "fail").length;
|
|
1276
|
-
|
|
1361
|
+
p6.note(
|
|
1277
1362
|
[
|
|
1278
1363
|
pc2.green(t("install.summaryOk", { count: ok })),
|
|
1279
1364
|
pc2.red(t("install.summaryFail", { count: fail }))
|
|
@@ -1288,14 +1373,14 @@ ${msg}`);
|
|
|
1288
1373
|
}
|
|
1289
1374
|
|
|
1290
1375
|
// src/flows/update.ts
|
|
1291
|
-
import * as
|
|
1376
|
+
import * as p7 from "@clack/prompts";
|
|
1292
1377
|
import pc3 from "picocolors";
|
|
1293
1378
|
async function getInstalled2() {
|
|
1294
1379
|
const states = await Promise.all(PKGS.map(async (pkg) => ({ pkg, installed: await pkg.isInstalled() })));
|
|
1295
1380
|
return states.filter((s) => s.installed).map((s) => s.pkg);
|
|
1296
1381
|
}
|
|
1297
1382
|
async function probeInstalled2() {
|
|
1298
|
-
const sp =
|
|
1383
|
+
const sp = p7.spinner();
|
|
1299
1384
|
sp.start(t("state.checking"));
|
|
1300
1385
|
try {
|
|
1301
1386
|
await Promise.all([listPlugins(), listMcp()]);
|
|
@@ -1312,7 +1397,7 @@ async function updateFlow(opts = {}) {
|
|
|
1312
1397
|
try {
|
|
1313
1398
|
const installed = await probeInstalled2();
|
|
1314
1399
|
if (installed.length === 0) {
|
|
1315
|
-
|
|
1400
|
+
p7.log.info(t("update.noneInstalled"));
|
|
1316
1401
|
return;
|
|
1317
1402
|
}
|
|
1318
1403
|
let targets;
|
|
@@ -1323,17 +1408,17 @@ async function updateFlow(opts = {}) {
|
|
|
1323
1408
|
for (const id of opts.ids) {
|
|
1324
1409
|
const pkg = findPkg(id);
|
|
1325
1410
|
if (!pkg) {
|
|
1326
|
-
|
|
1411
|
+
p7.log.warn(`Unknown id: ${id}`);
|
|
1327
1412
|
continue;
|
|
1328
1413
|
}
|
|
1329
1414
|
if (!installed.some((x2) => x2.id === pkg.id)) {
|
|
1330
|
-
|
|
1415
|
+
p7.log.warn(`${pkg.name}: ${t("pkg.notInstalled")}`);
|
|
1331
1416
|
continue;
|
|
1332
1417
|
}
|
|
1333
1418
|
targets.push(pkg);
|
|
1334
1419
|
}
|
|
1335
1420
|
} else {
|
|
1336
|
-
const picked = await
|
|
1421
|
+
const picked = await p7.multiselect({
|
|
1337
1422
|
message: t("update.selectPrompt"),
|
|
1338
1423
|
options: installed.map((pkg) => ({
|
|
1339
1424
|
value: pkg.id,
|
|
@@ -1342,42 +1427,42 @@ async function updateFlow(opts = {}) {
|
|
|
1342
1427
|
})),
|
|
1343
1428
|
required: false
|
|
1344
1429
|
});
|
|
1345
|
-
if (
|
|
1430
|
+
if (p7.isCancel(picked)) {
|
|
1346
1431
|
userCancelled = true;
|
|
1347
|
-
|
|
1432
|
+
p7.cancel(t("app.cancelled"));
|
|
1348
1433
|
return;
|
|
1349
1434
|
}
|
|
1350
1435
|
targets = picked.map((id) => findPkg(id)).filter((x2) => Boolean(x2));
|
|
1351
1436
|
}
|
|
1352
1437
|
if (targets.length === 0) {
|
|
1353
|
-
|
|
1438
|
+
p7.log.info(t("install.nothingSelected"));
|
|
1354
1439
|
return;
|
|
1355
1440
|
}
|
|
1356
1441
|
const results = [];
|
|
1357
1442
|
for (const pkg of targets) {
|
|
1358
1443
|
if (pkg.id === "sequential-thinking") {
|
|
1359
|
-
|
|
1444
|
+
p7.log.info(t("update.mcpAutoNote", { name: pkg.name }));
|
|
1360
1445
|
results.push({ id: pkg.id, status: "noop" });
|
|
1361
1446
|
continue;
|
|
1362
1447
|
}
|
|
1363
1448
|
if (pkg.id === "context7") {
|
|
1364
|
-
|
|
1449
|
+
p7.log.info(t("update.context7Note"));
|
|
1365
1450
|
results.push({ id: pkg.id, status: "noop" });
|
|
1366
1451
|
continue;
|
|
1367
1452
|
}
|
|
1368
|
-
const
|
|
1453
|
+
const log6 = p7.taskLog({ title: t("update.starting", { name: pkg.name }) });
|
|
1369
1454
|
try {
|
|
1370
1455
|
if (pkg.update) {
|
|
1371
|
-
await pkg.update({ log:
|
|
1456
|
+
await pkg.update({ log: log6, config: {}, t });
|
|
1372
1457
|
} else {
|
|
1373
|
-
await pkg.uninstall({ log:
|
|
1374
|
-
await pkg.install({ log:
|
|
1458
|
+
await pkg.uninstall({ log: log6, config: {}, t });
|
|
1459
|
+
await pkg.install({ log: log6, config: {}, t });
|
|
1375
1460
|
}
|
|
1376
|
-
|
|
1461
|
+
log6.success(t("update.success", { name: pkg.name }));
|
|
1377
1462
|
results.push({ id: pkg.id, status: "ok" });
|
|
1378
1463
|
} catch (err) {
|
|
1379
1464
|
const msg = err instanceof Error ? err.message : String(err);
|
|
1380
|
-
|
|
1465
|
+
log6.error(`${t("update.failed", { name: pkg.name })}
|
|
1381
1466
|
${msg}`);
|
|
1382
1467
|
results.push({ id: pkg.id, status: "fail", message: msg });
|
|
1383
1468
|
}
|
|
@@ -1385,7 +1470,7 @@ ${msg}`);
|
|
|
1385
1470
|
const ok = results.filter((r) => r.status === "ok").length;
|
|
1386
1471
|
const fail = results.filter((r) => r.status === "fail").length;
|
|
1387
1472
|
const noop = results.filter((r) => r.status === "noop").length;
|
|
1388
|
-
|
|
1473
|
+
p7.note(
|
|
1389
1474
|
[
|
|
1390
1475
|
pc3.green(t("install.summaryOk", { count: ok })),
|
|
1391
1476
|
pc3.red(t("install.summaryFail", { count: fail })),
|
|
@@ -1401,7 +1486,7 @@ ${msg}`);
|
|
|
1401
1486
|
}
|
|
1402
1487
|
|
|
1403
1488
|
// src/flows/status.ts
|
|
1404
|
-
import * as
|
|
1489
|
+
import * as p8 from "@clack/prompts";
|
|
1405
1490
|
import pc4 from "picocolors";
|
|
1406
1491
|
async function statusFlow(opts = {}) {
|
|
1407
1492
|
const states = await Promise.all(
|
|
@@ -1434,12 +1519,12 @@ async function statusFlow(opts = {}) {
|
|
|
1434
1519
|
const rows = states.map(
|
|
1435
1520
|
(s) => `${s.name.padEnd(nameW)} ${s.type.padEnd(typeW)} ${s.installed ? pc4.green(`\u2713 ${t("pkg.installed")}`) : pc4.yellow(`\u2717 ${t("pkg.notInstalled")}`)}`
|
|
1436
1521
|
);
|
|
1437
|
-
|
|
1522
|
+
p8.note([header, sep, ...rows].join("\n"), t("status.title"));
|
|
1438
1523
|
}
|
|
1439
1524
|
|
|
1440
1525
|
// src/ui/menu.ts
|
|
1441
1526
|
async function mainMenu() {
|
|
1442
|
-
const action = await
|
|
1527
|
+
const action = await p9.select({
|
|
1443
1528
|
message: t("menu.title"),
|
|
1444
1529
|
options: [
|
|
1445
1530
|
{ value: "install", label: t("menu.install") },
|
|
@@ -1449,8 +1534,8 @@ async function mainMenu() {
|
|
|
1449
1534
|
{ value: "exit", label: t("menu.exit") }
|
|
1450
1535
|
]
|
|
1451
1536
|
});
|
|
1452
|
-
if (
|
|
1453
|
-
|
|
1537
|
+
if (p9.isCancel(action) || action === "exit") {
|
|
1538
|
+
p9.cancel(t("app.cancelled"));
|
|
1454
1539
|
return;
|
|
1455
1540
|
}
|
|
1456
1541
|
switch (action) {
|
|
@@ -1495,7 +1580,7 @@ var installCmd = defineCommand({
|
|
|
1495
1580
|
},
|
|
1496
1581
|
async run({ args }) {
|
|
1497
1582
|
await initLanguage(parseLang(args.lang));
|
|
1498
|
-
|
|
1583
|
+
p10.intro(t("app.intro"));
|
|
1499
1584
|
const ids = collectPositional(args);
|
|
1500
1585
|
await installFlow({
|
|
1501
1586
|
ids,
|
|
@@ -1504,7 +1589,7 @@ var installCmd = defineCommand({
|
|
|
1504
1589
|
noRefresh: Boolean(args["no-refresh"]),
|
|
1505
1590
|
noClaudeMd: noClaudeMdFromArgs(args)
|
|
1506
1591
|
});
|
|
1507
|
-
|
|
1592
|
+
p10.outro(t("app.outro"));
|
|
1508
1593
|
}
|
|
1509
1594
|
});
|
|
1510
1595
|
var uninstallCmd = defineCommand({
|
|
@@ -1516,14 +1601,14 @@ var uninstallCmd = defineCommand({
|
|
|
1516
1601
|
},
|
|
1517
1602
|
async run({ args }) {
|
|
1518
1603
|
await initLanguage(parseLang(args.lang));
|
|
1519
|
-
|
|
1604
|
+
p10.intro(t("app.intro"));
|
|
1520
1605
|
const ids = collectPositional(args);
|
|
1521
1606
|
await uninstallFlow({
|
|
1522
1607
|
ids,
|
|
1523
1608
|
yes: Boolean(args.yes),
|
|
1524
1609
|
noClaudeMd: noClaudeMdFromArgs(args)
|
|
1525
1610
|
});
|
|
1526
|
-
|
|
1611
|
+
p10.outro(t("app.outro"));
|
|
1527
1612
|
}
|
|
1528
1613
|
});
|
|
1529
1614
|
var updateCmd = defineCommand({
|
|
@@ -1535,14 +1620,14 @@ var updateCmd = defineCommand({
|
|
|
1535
1620
|
},
|
|
1536
1621
|
async run({ args }) {
|
|
1537
1622
|
await initLanguage(parseLang(args.lang));
|
|
1538
|
-
|
|
1623
|
+
p10.intro(t("app.intro"));
|
|
1539
1624
|
const ids = collectPositional(args);
|
|
1540
1625
|
await updateFlow({
|
|
1541
1626
|
ids,
|
|
1542
1627
|
all: Boolean(args.all),
|
|
1543
1628
|
noClaudeMd: noClaudeMdFromArgs(args)
|
|
1544
1629
|
});
|
|
1545
|
-
|
|
1630
|
+
p10.outro(t("app.outro"));
|
|
1546
1631
|
}
|
|
1547
1632
|
});
|
|
1548
1633
|
var statusCmd = defineCommand({
|
|
@@ -1553,9 +1638,9 @@ var statusCmd = defineCommand({
|
|
|
1553
1638
|
},
|
|
1554
1639
|
async run({ args }) {
|
|
1555
1640
|
await initLanguage(parseLang(args.lang));
|
|
1556
|
-
if (!args.json)
|
|
1641
|
+
if (!args.json) p10.intro(t("app.intro"));
|
|
1557
1642
|
await statusFlow({ json: Boolean(args.json) });
|
|
1558
|
-
if (!args.json)
|
|
1643
|
+
if (!args.json) p10.outro(t("app.outro"));
|
|
1559
1644
|
}
|
|
1560
1645
|
});
|
|
1561
1646
|
var SUBCOMMANDS = /* @__PURE__ */ new Set(["install", "uninstall", "update", "status"]);
|
|
@@ -1597,9 +1682,9 @@ async function runInteractive(argv2) {
|
|
|
1597
1682
|
else if (argv2[i]?.startsWith("--lang=")) lang = parseLang(argv2[i].slice("--lang=".length));
|
|
1598
1683
|
}
|
|
1599
1684
|
await initLanguage(lang);
|
|
1600
|
-
|
|
1685
|
+
p10.intro(t("app.intro"));
|
|
1601
1686
|
await mainMenu();
|
|
1602
|
-
|
|
1687
|
+
p10.outro(t("app.outro"));
|
|
1603
1688
|
}
|
|
1604
1689
|
var argv = process.argv.slice(2);
|
|
1605
1690
|
var first = firstNonFlag(argv);
|