claudeup 3.7.0 → 3.7.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/package.json
CHANGED
package/src/prerunner/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import os from "node:os";
|
|
|
4
4
|
import { UpdateCache } from "../services/update-cache.js";
|
|
5
5
|
import { getAvailablePlugins, clearMarketplaceCache, } from "../services/plugin-manager.js";
|
|
6
6
|
import { runClaude } from "../services/claude-runner.js";
|
|
7
|
-
import { recoverMarketplaceSettings, migrateMarketplaceRename, getGlobalEnabledPlugins, getEnabledPlugins, getLocalEnabledPlugins, } from "../services/claude-settings.js";
|
|
7
|
+
import { recoverMarketplaceSettings, migrateMarketplaceRename, getGlobalEnabledPlugins, getEnabledPlugins, getLocalEnabledPlugins, saveGlobalInstalledPluginVersion, } from "../services/claude-settings.js";
|
|
8
8
|
import { parsePluginId } from "../utils/string-utils.js";
|
|
9
9
|
import { defaultMarketplaces } from "../data/marketplaces.js";
|
|
10
10
|
import { updatePlugin, addMarketplace, isClaudeAvailable, } from "../services/claude-cli.js";
|
|
@@ -133,6 +133,7 @@ export async function prerunClaude(claudeArgs, options = {}) {
|
|
|
133
133
|
if (cliAvailable) {
|
|
134
134
|
await updatePlugin(plugin.id, "user");
|
|
135
135
|
}
|
|
136
|
+
await saveGlobalInstalledPluginVersion(plugin.id, plugin.version);
|
|
136
137
|
autoUpdatedPlugins.push({
|
|
137
138
|
pluginId: plugin.id,
|
|
138
139
|
oldVersion: plugin.installedVersion,
|
package/src/prerunner/index.ts
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
getGlobalEnabledPlugins,
|
|
14
14
|
getEnabledPlugins,
|
|
15
15
|
getLocalEnabledPlugins,
|
|
16
|
+
saveGlobalInstalledPluginVersion,
|
|
16
17
|
} from "../services/claude-settings.js";
|
|
17
18
|
import { parsePluginId } from "../utils/string-utils.js";
|
|
18
19
|
import { defaultMarketplaces } from "../data/marketplaces.js";
|
|
@@ -192,6 +193,7 @@ export async function prerunClaude(
|
|
|
192
193
|
if (cliAvailable) {
|
|
193
194
|
await updatePlugin(plugin.id, "user");
|
|
194
195
|
}
|
|
196
|
+
await saveGlobalInstalledPluginVersion(plugin.id, plugin.version);
|
|
195
197
|
|
|
196
198
|
autoUpdatedPlugins.push({
|
|
197
199
|
pluginId: plugin.id,
|
|
@@ -160,13 +160,28 @@ async function installBrewPackages(packages, result) {
|
|
|
160
160
|
}
|
|
161
161
|
}
|
|
162
162
|
/**
|
|
163
|
-
*
|
|
163
|
+
* Detect the best available Node.js package installer for globals
|
|
164
|
+
* Prefers: bun > npm
|
|
164
165
|
*/
|
|
165
|
-
async function
|
|
166
|
+
async function detectNpmCommand() {
|
|
167
|
+
const bunPath = await which("bun");
|
|
168
|
+
if (bunPath) {
|
|
169
|
+
return { cmd: bunPath, args: ["install", "-g"], label: "bun" };
|
|
170
|
+
}
|
|
166
171
|
const npmPath = await which("npm");
|
|
167
|
-
if (
|
|
172
|
+
if (npmPath) {
|
|
173
|
+
return { cmd: npmPath, args: ["install", "-g"], label: "npm" };
|
|
174
|
+
}
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Install global Node.js packages (prefers bun > npm)
|
|
179
|
+
*/
|
|
180
|
+
async function installNpmPackages(packages, result) {
|
|
181
|
+
const installer = await detectNpmCommand();
|
|
182
|
+
if (!installer) {
|
|
168
183
|
for (const pkg of packages) {
|
|
169
|
-
result.failed.push({ pkg: `npm:${pkg}`, error: "npm
|
|
184
|
+
result.failed.push({ pkg: `npm:${pkg}`, error: "No bun or npm found" });
|
|
170
185
|
}
|
|
171
186
|
return;
|
|
172
187
|
}
|
|
@@ -175,12 +190,12 @@ async function installNpmPackages(packages, result) {
|
|
|
175
190
|
result.skipped.push(`npm:${pkg}`);
|
|
176
191
|
continue;
|
|
177
192
|
}
|
|
178
|
-
const { ok, stderr } = await run(
|
|
193
|
+
const { ok, stderr } = await run(installer.cmd, [...installer.args, pkg]);
|
|
179
194
|
if (ok) {
|
|
180
|
-
result.installed.push(
|
|
195
|
+
result.installed.push(`${installer.label}:${pkg}`);
|
|
181
196
|
}
|
|
182
197
|
else {
|
|
183
|
-
result.failed.push({ pkg:
|
|
198
|
+
result.failed.push({ pkg: `${installer.label}:${pkg}`, error: stderr });
|
|
184
199
|
}
|
|
185
200
|
}
|
|
186
201
|
}
|
|
@@ -196,16 +196,36 @@ async function installBrewPackages(
|
|
|
196
196
|
}
|
|
197
197
|
|
|
198
198
|
/**
|
|
199
|
-
*
|
|
199
|
+
* Detect the best available Node.js package installer for globals
|
|
200
|
+
* Prefers: bun > npm
|
|
201
|
+
*/
|
|
202
|
+
async function detectNpmCommand(): Promise<{
|
|
203
|
+
cmd: string;
|
|
204
|
+
args: string[];
|
|
205
|
+
label: string;
|
|
206
|
+
} | null> {
|
|
207
|
+
const bunPath = await which("bun");
|
|
208
|
+
if (bunPath) {
|
|
209
|
+
return { cmd: bunPath, args: ["install", "-g"], label: "bun" };
|
|
210
|
+
}
|
|
211
|
+
const npmPath = await which("npm");
|
|
212
|
+
if (npmPath) {
|
|
213
|
+
return { cmd: npmPath, args: ["install", "-g"], label: "npm" };
|
|
214
|
+
}
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Install global Node.js packages (prefers bun > npm)
|
|
200
220
|
*/
|
|
201
221
|
async function installNpmPackages(
|
|
202
222
|
packages: string[],
|
|
203
223
|
result: SetupResult,
|
|
204
224
|
): Promise<void> {
|
|
205
|
-
const
|
|
206
|
-
if (!
|
|
225
|
+
const installer = await detectNpmCommand();
|
|
226
|
+
if (!installer) {
|
|
207
227
|
for (const pkg of packages) {
|
|
208
|
-
result.failed.push({ pkg: `npm:${pkg}`, error: "npm
|
|
228
|
+
result.failed.push({ pkg: `npm:${pkg}`, error: "No bun or npm found" });
|
|
209
229
|
}
|
|
210
230
|
return;
|
|
211
231
|
}
|
|
@@ -216,11 +236,11 @@ async function installNpmPackages(
|
|
|
216
236
|
continue;
|
|
217
237
|
}
|
|
218
238
|
|
|
219
|
-
const { ok, stderr } = await run(
|
|
239
|
+
const { ok, stderr } = await run(installer.cmd, [...installer.args, pkg]);
|
|
220
240
|
if (ok) {
|
|
221
|
-
result.installed.push(
|
|
241
|
+
result.installed.push(`${installer.label}:${pkg}`);
|
|
222
242
|
} else {
|
|
223
|
-
result.failed.push({ pkg:
|
|
243
|
+
result.failed.push({ pkg: `${installer.label}:${pkg}`, error: stderr });
|
|
224
244
|
}
|
|
225
245
|
}
|
|
226
246
|
}
|
|
@@ -9,7 +9,8 @@ import { ScrollableList } from "../components/ScrollableList.js";
|
|
|
9
9
|
import { fuzzyFilter, highlightMatches } from "../../utils/fuzzy-search.js";
|
|
10
10
|
import { getAllMarketplaces } from "../../data/marketplaces.js";
|
|
11
11
|
import { getAvailablePlugins, refreshAllMarketplaces, clearMarketplaceCache, getLocalMarketplacesInfo, } from "../../services/plugin-manager.js";
|
|
12
|
-
import { setMcpEnvVar, getMcpEnvVars, } from "../../services/claude-settings.js";
|
|
12
|
+
import { setMcpEnvVar, getMcpEnvVars, saveGlobalInstalledPluginVersion, saveLocalInstalledPluginVersion, } from "../../services/claude-settings.js";
|
|
13
|
+
import { saveInstalledPluginVersion, } from "../../services/plugin-manager.js";
|
|
13
14
|
import { installPlugin as cliInstallPlugin, uninstallPlugin as cliUninstallPlugin, updatePlugin as cliUpdatePlugin, } from "../../services/claude-cli.js";
|
|
14
15
|
import { getPluginEnvRequirements, getPluginSourcePath, } from "../../services/plugin-mcp-config.js";
|
|
15
16
|
import { getPluginSetupFromSource, checkMissingDeps, installPluginDeps, } from "../../services/plugin-setup.js";
|
|
@@ -399,6 +400,27 @@ export function PluginsScreen() {
|
|
|
399
400
|
console.error("Error installing plugin deps:", error);
|
|
400
401
|
}
|
|
401
402
|
};
|
|
403
|
+
/**
|
|
404
|
+
* Save the installed version to settings after CLI install/update.
|
|
405
|
+
* Claude CLI doesn't update installedPluginVersions in settings.json,
|
|
406
|
+
* so we do it ourselves to keep the TUI version display accurate.
|
|
407
|
+
*/
|
|
408
|
+
const saveVersionAfterInstall = async (pluginId, version, scope) => {
|
|
409
|
+
try {
|
|
410
|
+
if (scope === "user") {
|
|
411
|
+
await saveGlobalInstalledPluginVersion(pluginId, version);
|
|
412
|
+
}
|
|
413
|
+
else if (scope === "local") {
|
|
414
|
+
await saveLocalInstalledPluginVersion(pluginId, version, state.projectPath);
|
|
415
|
+
}
|
|
416
|
+
else {
|
|
417
|
+
await saveInstalledPluginVersion(pluginId, version, state.projectPath);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
catch {
|
|
421
|
+
// Non-fatal: version display may be stale but plugin still works
|
|
422
|
+
}
|
|
423
|
+
};
|
|
402
424
|
const handleSelect = async () => {
|
|
403
425
|
const item = selectableItems[pluginsState.selectedIndex];
|
|
404
426
|
if (!item)
|
|
@@ -508,9 +530,11 @@ export function PluginsScreen() {
|
|
|
508
530
|
}
|
|
509
531
|
else if (action === "update") {
|
|
510
532
|
await cliUpdatePlugin(plugin.id, scope);
|
|
533
|
+
await saveVersionAfterInstall(plugin.id, latestVersion, scope);
|
|
511
534
|
}
|
|
512
535
|
else {
|
|
513
536
|
await cliInstallPlugin(plugin.id, scope);
|
|
537
|
+
await saveVersionAfterInstall(plugin.id, latestVersion, scope);
|
|
514
538
|
// On fresh install, configure env vars and install system deps
|
|
515
539
|
modal.hideModal();
|
|
516
540
|
await collectPluginEnvVars(plugin.name, plugin.marketplace);
|
|
@@ -536,6 +560,7 @@ export function PluginsScreen() {
|
|
|
536
560
|
modal.loading(`Updating ${plugin.name}...`);
|
|
537
561
|
try {
|
|
538
562
|
await cliUpdatePlugin(plugin.id, scope);
|
|
563
|
+
await saveVersionAfterInstall(plugin.id, plugin.version || "0.0.0", scope);
|
|
539
564
|
modal.hideModal();
|
|
540
565
|
fetchData();
|
|
541
566
|
}
|
|
@@ -555,6 +580,7 @@ export function PluginsScreen() {
|
|
|
555
580
|
try {
|
|
556
581
|
for (const plugin of updatable) {
|
|
557
582
|
await cliUpdatePlugin(plugin.id, scope);
|
|
583
|
+
await saveVersionAfterInstall(plugin.id, plugin.version || "0.0.0", scope);
|
|
558
584
|
}
|
|
559
585
|
modal.hideModal();
|
|
560
586
|
fetchData();
|
|
@@ -608,9 +634,11 @@ export function PluginsScreen() {
|
|
|
608
634
|
}
|
|
609
635
|
else if (action === "update") {
|
|
610
636
|
await cliUpdatePlugin(plugin.id, scope);
|
|
637
|
+
await saveVersionAfterInstall(plugin.id, latestVersion, scope);
|
|
611
638
|
}
|
|
612
639
|
else {
|
|
613
640
|
await cliInstallPlugin(plugin.id, scope);
|
|
641
|
+
await saveVersionAfterInstall(plugin.id, latestVersion, scope);
|
|
614
642
|
// On fresh install, configure env vars and install system deps
|
|
615
643
|
modal.hideModal();
|
|
616
644
|
await collectPluginEnvVars(plugin.name, plugin.marketplace);
|
|
@@ -17,7 +17,12 @@ import {
|
|
|
17
17
|
import {
|
|
18
18
|
setMcpEnvVar,
|
|
19
19
|
getMcpEnvVars,
|
|
20
|
+
saveGlobalInstalledPluginVersion,
|
|
21
|
+
saveLocalInstalledPluginVersion,
|
|
20
22
|
} from "../../services/claude-settings.js";
|
|
23
|
+
import {
|
|
24
|
+
saveInstalledPluginVersion,
|
|
25
|
+
} from "../../services/plugin-manager.js";
|
|
21
26
|
import {
|
|
22
27
|
installPlugin as cliInstallPlugin,
|
|
23
28
|
uninstallPlugin as cliUninstallPlugin,
|
|
@@ -531,6 +536,29 @@ export function PluginsScreen() {
|
|
|
531
536
|
}
|
|
532
537
|
};
|
|
533
538
|
|
|
539
|
+
/**
|
|
540
|
+
* Save the installed version to settings after CLI install/update.
|
|
541
|
+
* Claude CLI doesn't update installedPluginVersions in settings.json,
|
|
542
|
+
* so we do it ourselves to keep the TUI version display accurate.
|
|
543
|
+
*/
|
|
544
|
+
const saveVersionAfterInstall = async (
|
|
545
|
+
pluginId: string,
|
|
546
|
+
version: string,
|
|
547
|
+
scope: PluginScope,
|
|
548
|
+
): Promise<void> => {
|
|
549
|
+
try {
|
|
550
|
+
if (scope === "user") {
|
|
551
|
+
await saveGlobalInstalledPluginVersion(pluginId, version);
|
|
552
|
+
} else if (scope === "local") {
|
|
553
|
+
await saveLocalInstalledPluginVersion(pluginId, version, state.projectPath);
|
|
554
|
+
} else {
|
|
555
|
+
await saveInstalledPluginVersion(pluginId, version, state.projectPath);
|
|
556
|
+
}
|
|
557
|
+
} catch {
|
|
558
|
+
// Non-fatal: version display may be stale but plugin still works
|
|
559
|
+
}
|
|
560
|
+
};
|
|
561
|
+
|
|
534
562
|
const handleSelect = async () => {
|
|
535
563
|
const item = selectableItems[pluginsState.selectedIndex];
|
|
536
564
|
if (!item) return;
|
|
@@ -663,8 +691,10 @@ export function PluginsScreen() {
|
|
|
663
691
|
await cliUninstallPlugin(plugin.id, scope, state.projectPath);
|
|
664
692
|
} else if (action === "update") {
|
|
665
693
|
await cliUpdatePlugin(plugin.id, scope);
|
|
694
|
+
await saveVersionAfterInstall(plugin.id, latestVersion, scope);
|
|
666
695
|
} else {
|
|
667
696
|
await cliInstallPlugin(plugin.id, scope);
|
|
697
|
+
await saveVersionAfterInstall(plugin.id, latestVersion, scope);
|
|
668
698
|
|
|
669
699
|
// On fresh install, configure env vars and install system deps
|
|
670
700
|
modal.hideModal();
|
|
@@ -692,6 +722,7 @@ export function PluginsScreen() {
|
|
|
692
722
|
modal.loading(`Updating ${plugin.name}...`);
|
|
693
723
|
try {
|
|
694
724
|
await cliUpdatePlugin(plugin.id, scope);
|
|
725
|
+
await saveVersionAfterInstall(plugin.id, plugin.version || "0.0.0", scope);
|
|
695
726
|
modal.hideModal();
|
|
696
727
|
fetchData();
|
|
697
728
|
} catch (error) {
|
|
@@ -712,6 +743,7 @@ export function PluginsScreen() {
|
|
|
712
743
|
try {
|
|
713
744
|
for (const plugin of updatable) {
|
|
714
745
|
await cliUpdatePlugin(plugin.id, scope);
|
|
746
|
+
await saveVersionAfterInstall(plugin.id, plugin.version || "0.0.0", scope);
|
|
715
747
|
}
|
|
716
748
|
modal.hideModal();
|
|
717
749
|
fetchData();
|
|
@@ -771,8 +803,10 @@ export function PluginsScreen() {
|
|
|
771
803
|
await cliUninstallPlugin(plugin.id, scope, state.projectPath);
|
|
772
804
|
} else if (action === "update") {
|
|
773
805
|
await cliUpdatePlugin(plugin.id, scope);
|
|
806
|
+
await saveVersionAfterInstall(plugin.id, latestVersion, scope);
|
|
774
807
|
} else {
|
|
775
808
|
await cliInstallPlugin(plugin.id, scope);
|
|
809
|
+
await saveVersionAfterInstall(plugin.id, latestVersion, scope);
|
|
776
810
|
|
|
777
811
|
// On fresh install, configure env vars and install system deps
|
|
778
812
|
modal.hideModal();
|