claudeup 3.5.0 → 3.6.0
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 +1 -1
- package/src/data/marketplaces.js +1 -0
- package/src/data/marketplaces.ts +1 -0
- package/src/prerunner/index.js +89 -11
- package/src/prerunner/index.ts +118 -11
- package/src/services/claude-cli.js +94 -0
- package/src/services/claude-cli.ts +132 -0
- package/src/services/claude-settings.js +65 -48
- package/src/services/claude-settings.ts +68 -52
- package/src/ui/App.js +1 -1
- package/src/ui/App.tsx +1 -1
- package/src/ui/screens/PluginsScreen.js +27 -95
- package/src/ui/screens/PluginsScreen.tsx +28 -117
|
@@ -414,13 +414,14 @@ export async function getMarketplaceAutoUpdate(marketplaceName) {
|
|
|
414
414
|
return known[marketplaceName]?.autoUpdate;
|
|
415
415
|
}
|
|
416
416
|
// =============================================================================
|
|
417
|
-
// MARKETPLACE RENAME MIGRATION: mag-claude-plugins → magus
|
|
417
|
+
// MARKETPLACE RENAME MIGRATION: mag-claude-plugins / MadAppGang-claude-code → magus
|
|
418
418
|
// =============================================================================
|
|
419
|
-
const
|
|
419
|
+
const OLD_MARKETPLACE_NAMES = ["mag-claude-plugins", "MadAppGang-claude-code"];
|
|
420
420
|
const NEW_MARKETPLACE_NAME = "magus";
|
|
421
421
|
/**
|
|
422
|
-
* Rename plugin keys in a Record from old marketplace to new.
|
|
422
|
+
* Rename plugin keys in a Record from any old marketplace name to new.
|
|
423
423
|
* e.g., "frontend@mag-claude-plugins" → "frontend@magus"
|
|
424
|
+
* "dev@MadAppGang-claude-code" → "dev@magus"
|
|
424
425
|
* Returns [migratedRecord, count] — count=0 means no changes.
|
|
425
426
|
*/
|
|
426
427
|
function migratePluginKeys(record) {
|
|
@@ -429,9 +430,14 @@ function migratePluginKeys(record) {
|
|
|
429
430
|
const migrated = {};
|
|
430
431
|
let count = 0;
|
|
431
432
|
for (const [key, value] of Object.entries(record)) {
|
|
432
|
-
|
|
433
|
+
const oldName = OLD_MARKETPLACE_NAMES.find((n) => key.endsWith(`@${n}`));
|
|
434
|
+
if (oldName) {
|
|
433
435
|
const pluginName = key.slice(0, key.lastIndexOf("@"));
|
|
434
|
-
|
|
436
|
+
const newKey = `${pluginName}@${NEW_MARKETPLACE_NAME}`;
|
|
437
|
+
// Don't overwrite if canonical key already exists
|
|
438
|
+
if (!record[newKey]) {
|
|
439
|
+
migrated[newKey] = value;
|
|
440
|
+
}
|
|
435
441
|
count++;
|
|
436
442
|
}
|
|
437
443
|
else {
|
|
@@ -456,12 +462,16 @@ function migrateSettingsObject(settings) {
|
|
|
456
462
|
settings.installedPluginVersions = iv;
|
|
457
463
|
total += ivCount;
|
|
458
464
|
}
|
|
459
|
-
// Migrate extraKnownMarketplaces
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
+
// Migrate extraKnownMarketplaces keys
|
|
466
|
+
for (const oldName of OLD_MARKETPLACE_NAMES) {
|
|
467
|
+
if (settings.extraKnownMarketplaces?.[oldName]) {
|
|
468
|
+
const entry = settings.extraKnownMarketplaces[oldName];
|
|
469
|
+
delete settings.extraKnownMarketplaces[oldName];
|
|
470
|
+
if (!settings.extraKnownMarketplaces[NEW_MARKETPLACE_NAME]) {
|
|
471
|
+
settings.extraKnownMarketplaces[NEW_MARKETPLACE_NAME] = entry;
|
|
472
|
+
}
|
|
473
|
+
total++;
|
|
474
|
+
}
|
|
465
475
|
}
|
|
466
476
|
return total;
|
|
467
477
|
}
|
|
@@ -519,33 +529,34 @@ export async function migrateMarketplaceRename(projectPath) {
|
|
|
519
529
|
}
|
|
520
530
|
}
|
|
521
531
|
catch { /* skip if unreadable */ }
|
|
522
|
-
// 4. known_marketplaces.json — rename
|
|
532
|
+
// 4. known_marketplaces.json — rename old keys + physical directory cleanup
|
|
523
533
|
const pluginsDir = path.join(os.homedir(), ".claude", "plugins", "marketplaces");
|
|
524
|
-
const oldDir = path.join(pluginsDir, OLD_MARKETPLACE_NAME);
|
|
525
534
|
const newDir = path.join(pluginsDir, NEW_MARKETPLACE_NAME);
|
|
526
535
|
try {
|
|
527
536
|
const known = await readKnownMarketplaces();
|
|
528
537
|
let knownModified = false;
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
known[NEW_MARKETPLACE_NAME]
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
538
|
+
for (const oldName of OLD_MARKETPLACE_NAMES) {
|
|
539
|
+
if (known[oldName]) {
|
|
540
|
+
const oldEntry = known[oldName];
|
|
541
|
+
// If canonical entry doesn't exist yet, create it
|
|
542
|
+
if (!known[NEW_MARKETPLACE_NAME]) {
|
|
543
|
+
known[NEW_MARKETPLACE_NAME] = {
|
|
544
|
+
...oldEntry,
|
|
545
|
+
source: {
|
|
546
|
+
...oldEntry.source,
|
|
547
|
+
repo: "MadAppGang/magus",
|
|
548
|
+
},
|
|
549
|
+
};
|
|
550
|
+
}
|
|
551
|
+
delete known[oldName];
|
|
552
|
+
knownModified = true;
|
|
553
|
+
}
|
|
554
|
+
// Ensure installLocation doesn't reference old directory names
|
|
555
|
+
if (known[NEW_MARKETPLACE_NAME]?.installLocation?.includes(oldName)) {
|
|
556
|
+
known[NEW_MARKETPLACE_NAME].installLocation =
|
|
557
|
+
known[NEW_MARKETPLACE_NAME].installLocation.replace(oldName, NEW_MARKETPLACE_NAME);
|
|
558
|
+
knownModified = true;
|
|
540
559
|
}
|
|
541
|
-
delete known[OLD_MARKETPLACE_NAME];
|
|
542
|
-
knownModified = true;
|
|
543
|
-
}
|
|
544
|
-
// Ensure installLocation points to new directory name
|
|
545
|
-
if (known[NEW_MARKETPLACE_NAME]?.installLocation?.includes(OLD_MARKETPLACE_NAME)) {
|
|
546
|
-
known[NEW_MARKETPLACE_NAME].installLocation =
|
|
547
|
-
known[NEW_MARKETPLACE_NAME].installLocation.replace(OLD_MARKETPLACE_NAME, NEW_MARKETPLACE_NAME);
|
|
548
|
-
knownModified = true;
|
|
549
560
|
}
|
|
550
561
|
if (knownModified) {
|
|
551
562
|
await writeKnownMarketplaces(known);
|
|
@@ -553,31 +564,33 @@ export async function migrateMarketplaceRename(projectPath) {
|
|
|
553
564
|
}
|
|
554
565
|
}
|
|
555
566
|
catch { /* skip if unreadable */ }
|
|
556
|
-
// 4b. Rename/remove
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
567
|
+
// 4b. Rename/remove old physical directories (runs even if keys were already migrated)
|
|
568
|
+
for (const oldName of OLD_MARKETPLACE_NAMES) {
|
|
569
|
+
const oldDir = path.join(pluginsDir, oldName);
|
|
570
|
+
try {
|
|
571
|
+
if (await fs.pathExists(oldDir)) {
|
|
572
|
+
if (!(await fs.pathExists(newDir))) {
|
|
573
|
+
await fs.rename(oldDir, newDir);
|
|
574
|
+
}
|
|
575
|
+
else {
|
|
576
|
+
// Both exist — remove the old one (magus dir is canonical)
|
|
577
|
+
await fs.remove(oldDir);
|
|
578
|
+
}
|
|
565
579
|
}
|
|
566
580
|
}
|
|
581
|
+
catch { /* non-fatal: directory cleanup is best-effort */ }
|
|
567
582
|
}
|
|
568
|
-
catch { /* non-fatal: directory cleanup is best-effort */ }
|
|
569
583
|
// 4c. Update git remote URL in the marketplace clone (old → new repo)
|
|
570
584
|
try {
|
|
571
|
-
|
|
572
|
-
if (await fs.pathExists(path.join(marketplaceDir, ".git"))) {
|
|
585
|
+
if (await fs.pathExists(path.join(newDir, ".git"))) {
|
|
573
586
|
const { execSync } = await import("node:child_process");
|
|
574
587
|
const remote = execSync("git remote get-url origin", {
|
|
575
|
-
cwd:
|
|
588
|
+
cwd: newDir, encoding: "utf-8", timeout: 5000,
|
|
576
589
|
}).trim();
|
|
577
590
|
if (remote.includes("claude-code") && remote.includes("MadAppGang")) {
|
|
578
591
|
const newRemote = remote.replace("claude-code", NEW_MARKETPLACE_NAME);
|
|
579
592
|
execSync(`git remote set-url origin "${newRemote}"`, {
|
|
580
|
-
cwd:
|
|
593
|
+
cwd: newDir, encoding: "utf-8", timeout: 5000,
|
|
581
594
|
});
|
|
582
595
|
}
|
|
583
596
|
}
|
|
@@ -589,9 +602,13 @@ export async function migrateMarketplaceRename(projectPath) {
|
|
|
589
602
|
let regCount = 0;
|
|
590
603
|
const newPlugins = {};
|
|
591
604
|
for (const [pluginId, entries] of Object.entries(registry.plugins)) {
|
|
592
|
-
|
|
605
|
+
const oldName = OLD_MARKETPLACE_NAMES.find((n) => pluginId.endsWith(`@${n}`));
|
|
606
|
+
if (oldName) {
|
|
593
607
|
const pluginName = pluginId.slice(0, pluginId.lastIndexOf("@"));
|
|
594
|
-
|
|
608
|
+
const newKey = `${pluginName}@${NEW_MARKETPLACE_NAME}`;
|
|
609
|
+
if (!newPlugins[newKey]) {
|
|
610
|
+
newPlugins[newKey] = entries;
|
|
611
|
+
}
|
|
595
612
|
regCount++;
|
|
596
613
|
}
|
|
597
614
|
else {
|
|
@@ -630,15 +630,16 @@ export interface MarketplaceRecoveryResult {
|
|
|
630
630
|
}
|
|
631
631
|
|
|
632
632
|
// =============================================================================
|
|
633
|
-
// MARKETPLACE RENAME MIGRATION: mag-claude-plugins → magus
|
|
633
|
+
// MARKETPLACE RENAME MIGRATION: mag-claude-plugins / MadAppGang-claude-code → magus
|
|
634
634
|
// =============================================================================
|
|
635
635
|
|
|
636
|
-
const
|
|
636
|
+
const OLD_MARKETPLACE_NAMES = ["mag-claude-plugins", "MadAppGang-claude-code"];
|
|
637
637
|
const NEW_MARKETPLACE_NAME = "magus";
|
|
638
638
|
|
|
639
639
|
/**
|
|
640
|
-
* Rename plugin keys in a Record from old marketplace to new.
|
|
640
|
+
* Rename plugin keys in a Record from any old marketplace name to new.
|
|
641
641
|
* e.g., "frontend@mag-claude-plugins" → "frontend@magus"
|
|
642
|
+
* "dev@MadAppGang-claude-code" → "dev@magus"
|
|
642
643
|
* Returns [migratedRecord, count] — count=0 means no changes.
|
|
643
644
|
*/
|
|
644
645
|
function migratePluginKeys<T>(
|
|
@@ -648,9 +649,14 @@ function migratePluginKeys<T>(
|
|
|
648
649
|
const migrated: Record<string, T> = {};
|
|
649
650
|
let count = 0;
|
|
650
651
|
for (const [key, value] of Object.entries(record)) {
|
|
651
|
-
|
|
652
|
+
const oldName = OLD_MARKETPLACE_NAMES.find((n) => key.endsWith(`@${n}`));
|
|
653
|
+
if (oldName) {
|
|
652
654
|
const pluginName = key.slice(0, key.lastIndexOf("@"));
|
|
653
|
-
|
|
655
|
+
const newKey = `${pluginName}@${NEW_MARKETPLACE_NAME}`;
|
|
656
|
+
// Don't overwrite if canonical key already exists
|
|
657
|
+
if (!record[newKey]) {
|
|
658
|
+
migrated[newKey] = value;
|
|
659
|
+
}
|
|
654
660
|
count++;
|
|
655
661
|
} else {
|
|
656
662
|
migrated[key] = value;
|
|
@@ -678,12 +684,16 @@ function migrateSettingsObject(settings: ClaudeSettings): number {
|
|
|
678
684
|
total += ivCount;
|
|
679
685
|
}
|
|
680
686
|
|
|
681
|
-
// Migrate extraKnownMarketplaces
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
+
// Migrate extraKnownMarketplaces keys
|
|
688
|
+
for (const oldName of OLD_MARKETPLACE_NAMES) {
|
|
689
|
+
if (settings.extraKnownMarketplaces?.[oldName]) {
|
|
690
|
+
const entry = settings.extraKnownMarketplaces[oldName];
|
|
691
|
+
delete settings.extraKnownMarketplaces[oldName];
|
|
692
|
+
if (!settings.extraKnownMarketplaces[NEW_MARKETPLACE_NAME]) {
|
|
693
|
+
settings.extraKnownMarketplaces[NEW_MARKETPLACE_NAME] = entry;
|
|
694
|
+
}
|
|
695
|
+
total++;
|
|
696
|
+
}
|
|
687
697
|
}
|
|
688
698
|
|
|
689
699
|
return total;
|
|
@@ -748,40 +758,40 @@ export async function migrateMarketplaceRename(
|
|
|
748
758
|
}
|
|
749
759
|
} catch { /* skip if unreadable */ }
|
|
750
760
|
|
|
751
|
-
// 4. known_marketplaces.json — rename
|
|
761
|
+
// 4. known_marketplaces.json — rename old keys + physical directory cleanup
|
|
752
762
|
const pluginsDir = path.join(os.homedir(), ".claude", "plugins", "marketplaces");
|
|
753
|
-
const oldDir = path.join(pluginsDir, OLD_MARKETPLACE_NAME);
|
|
754
763
|
const newDir = path.join(pluginsDir, NEW_MARKETPLACE_NAME);
|
|
755
764
|
|
|
756
765
|
try {
|
|
757
766
|
const known = await readKnownMarketplaces();
|
|
758
767
|
let knownModified = false;
|
|
759
768
|
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
769
|
+
for (const oldName of OLD_MARKETPLACE_NAMES) {
|
|
770
|
+
if (known[oldName]) {
|
|
771
|
+
const oldEntry = known[oldName];
|
|
772
|
+
// If canonical entry doesn't exist yet, create it
|
|
773
|
+
if (!known[NEW_MARKETPLACE_NAME]) {
|
|
774
|
+
known[NEW_MARKETPLACE_NAME] = {
|
|
775
|
+
...oldEntry,
|
|
776
|
+
source: {
|
|
777
|
+
...oldEntry.source,
|
|
778
|
+
repo: "MadAppGang/magus",
|
|
779
|
+
},
|
|
780
|
+
};
|
|
781
|
+
}
|
|
782
|
+
delete known[oldName];
|
|
783
|
+
knownModified = true;
|
|
772
784
|
}
|
|
773
|
-
delete known[OLD_MARKETPLACE_NAME];
|
|
774
|
-
knownModified = true;
|
|
775
|
-
}
|
|
776
785
|
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
786
|
+
// Ensure installLocation doesn't reference old directory names
|
|
787
|
+
if (known[NEW_MARKETPLACE_NAME]?.installLocation?.includes(oldName)) {
|
|
788
|
+
known[NEW_MARKETPLACE_NAME].installLocation =
|
|
789
|
+
known[NEW_MARKETPLACE_NAME].installLocation.replace(
|
|
790
|
+
oldName,
|
|
791
|
+
NEW_MARKETPLACE_NAME,
|
|
792
|
+
);
|
|
793
|
+
knownModified = true;
|
|
794
|
+
}
|
|
785
795
|
}
|
|
786
796
|
|
|
787
797
|
if (knownModified) {
|
|
@@ -790,30 +800,32 @@ export async function migrateMarketplaceRename(
|
|
|
790
800
|
}
|
|
791
801
|
} catch { /* skip if unreadable */ }
|
|
792
802
|
|
|
793
|
-
// 4b. Rename/remove
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
803
|
+
// 4b. Rename/remove old physical directories (runs even if keys were already migrated)
|
|
804
|
+
for (const oldName of OLD_MARKETPLACE_NAMES) {
|
|
805
|
+
const oldDir = path.join(pluginsDir, oldName);
|
|
806
|
+
try {
|
|
807
|
+
if (await fs.pathExists(oldDir)) {
|
|
808
|
+
if (!(await fs.pathExists(newDir))) {
|
|
809
|
+
await fs.rename(oldDir, newDir);
|
|
810
|
+
} else {
|
|
811
|
+
// Both exist — remove the old one (magus dir is canonical)
|
|
812
|
+
await fs.remove(oldDir);
|
|
813
|
+
}
|
|
801
814
|
}
|
|
802
|
-
}
|
|
803
|
-
}
|
|
815
|
+
} catch { /* non-fatal: directory cleanup is best-effort */ }
|
|
816
|
+
}
|
|
804
817
|
|
|
805
818
|
// 4c. Update git remote URL in the marketplace clone (old → new repo)
|
|
806
819
|
try {
|
|
807
|
-
|
|
808
|
-
if (await fs.pathExists(path.join(marketplaceDir, ".git"))) {
|
|
820
|
+
if (await fs.pathExists(path.join(newDir, ".git"))) {
|
|
809
821
|
const { execSync } = await import("node:child_process");
|
|
810
822
|
const remote = execSync("git remote get-url origin", {
|
|
811
|
-
cwd:
|
|
823
|
+
cwd: newDir, encoding: "utf-8", timeout: 5000,
|
|
812
824
|
}).trim();
|
|
813
825
|
if (remote.includes("claude-code") && remote.includes("MadAppGang")) {
|
|
814
826
|
const newRemote = remote.replace("claude-code", NEW_MARKETPLACE_NAME);
|
|
815
827
|
execSync(`git remote set-url origin "${newRemote}"`, {
|
|
816
|
-
cwd:
|
|
828
|
+
cwd: newDir, encoding: "utf-8", timeout: 5000,
|
|
817
829
|
});
|
|
818
830
|
}
|
|
819
831
|
}
|
|
@@ -825,9 +837,13 @@ export async function migrateMarketplaceRename(
|
|
|
825
837
|
let regCount = 0;
|
|
826
838
|
const newPlugins: typeof registry.plugins = {};
|
|
827
839
|
for (const [pluginId, entries] of Object.entries(registry.plugins)) {
|
|
828
|
-
|
|
840
|
+
const oldName = OLD_MARKETPLACE_NAMES.find((n) => pluginId.endsWith(`@${n}`));
|
|
841
|
+
if (oldName) {
|
|
829
842
|
const pluginName = pluginId.slice(0, pluginId.lastIndexOf("@"));
|
|
830
|
-
|
|
843
|
+
const newKey = `${pluginName}@${NEW_MARKETPLACE_NAME}`;
|
|
844
|
+
if (!newPlugins[newKey]) {
|
|
845
|
+
newPlugins[newKey] = entries;
|
|
846
|
+
}
|
|
831
847
|
regCount++;
|
|
832
848
|
} else {
|
|
833
849
|
newPlugins[pluginId] = entries;
|
package/src/ui/App.js
CHANGED
|
@@ -182,7 +182,7 @@ function AppContentInner({ showDebug, onDebugToggle, updateInfo, onExit, }) {
|
|
|
182
182
|
type: "SHOW_PROGRESS",
|
|
183
183
|
state: { message: "Scanning marketplaces..." },
|
|
184
184
|
});
|
|
185
|
-
// Migrate
|
|
185
|
+
// Migrate old marketplace names → magus (idempotent), then repair plugin.json files
|
|
186
186
|
migrateMarketplaceRename()
|
|
187
187
|
.catch(() => { }); // non-blocking, best-effort
|
|
188
188
|
repairAllMarketplaces()
|
package/src/ui/App.tsx
CHANGED
|
@@ -265,7 +265,7 @@ function AppContentInner({
|
|
|
265
265
|
state: { message: "Scanning marketplaces..." },
|
|
266
266
|
});
|
|
267
267
|
|
|
268
|
-
// Migrate
|
|
268
|
+
// Migrate old marketplace names → magus (idempotent), then repair plugin.json files
|
|
269
269
|
migrateMarketplaceRename()
|
|
270
270
|
.catch(() => {}); // non-blocking, best-effort
|
|
271
271
|
|
|
@@ -8,8 +8,9 @@ import { CategoryHeader } from "../components/CategoryHeader.js";
|
|
|
8
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
|
-
import { getAvailablePlugins, refreshAllMarketplaces, clearMarketplaceCache,
|
|
12
|
-
import {
|
|
11
|
+
import { getAvailablePlugins, refreshAllMarketplaces, clearMarketplaceCache, getLocalMarketplacesInfo, } from "../../services/plugin-manager.js";
|
|
12
|
+
import { setMcpEnvVar, getMcpEnvVars, } from "../../services/claude-settings.js";
|
|
13
|
+
import { installPlugin as cliInstallPlugin, uninstallPlugin as cliUninstallPlugin, updatePlugin as cliUpdatePlugin, } from "../../services/claude-cli.js";
|
|
13
14
|
import { getPluginEnvRequirements, getPluginSourcePath, } from "../../services/plugin-mcp-config.js";
|
|
14
15
|
export function PluginsScreen() {
|
|
15
16
|
const { state, dispatch } = useApp();
|
|
@@ -263,10 +264,10 @@ export function PluginsScreen() {
|
|
|
263
264
|
};
|
|
264
265
|
const handleShowAddMarketplaceInstructions = async () => {
|
|
265
266
|
await modal.message("Add Marketplace", "To add a marketplace, run this command in your terminal:\n\n" +
|
|
266
|
-
" claude marketplace add owner/repo\n\n" +
|
|
267
|
+
" claude plugin marketplace add owner/repo\n\n" +
|
|
267
268
|
"Examples:\n" +
|
|
268
|
-
" claude marketplace add MadAppGang/magus\n" +
|
|
269
|
-
" claude marketplace add anthropics/claude-plugins-official\n\n" +
|
|
269
|
+
" claude plugin marketplace add MadAppGang/magus\n" +
|
|
270
|
+
" claude plugin marketplace add anthropics/claude-plugins-official\n\n" +
|
|
270
271
|
"Auto-update is enabled by default for new marketplaces.\n\n" +
|
|
271
272
|
"After adding, refresh claudeup with 'r' to see the new marketplace.", "info");
|
|
272
273
|
};
|
|
@@ -377,7 +378,7 @@ export function PluginsScreen() {
|
|
|
377
378
|
else {
|
|
378
379
|
// Show add marketplace instructions
|
|
379
380
|
await modal.message(`Add ${mp.displayName}?`, `To add this marketplace, run in your terminal:\n\n` +
|
|
380
|
-
` claude marketplace add ${mp.source.repo || mp.name}\n\n` +
|
|
381
|
+
` claude plugin marketplace add ${mp.source.repo || mp.name}\n\n` +
|
|
381
382
|
`Auto-update is enabled by default.\n\n` +
|
|
382
383
|
`After adding, refresh claudeup with 'r' to see it.`, "info");
|
|
383
384
|
}
|
|
@@ -454,40 +455,18 @@ export function PluginsScreen() {
|
|
|
454
455
|
: `Uninstalling from ${scopeLabel}`;
|
|
455
456
|
modal.loading(`${actionLabel}...`);
|
|
456
457
|
try {
|
|
458
|
+
const scope = scopeValue;
|
|
457
459
|
if (action === "uninstall") {
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
}
|
|
463
|
-
else if (scopeValue === "project") {
|
|
464
|
-
await enablePlugin(plugin.id, false, state.projectPath);
|
|
465
|
-
await removeInstalledPluginVersion(plugin.id, state.projectPath);
|
|
466
|
-
}
|
|
467
|
-
else {
|
|
468
|
-
await enableLocalPlugin(plugin.id, false, state.projectPath);
|
|
469
|
-
await removeLocalInstalledPluginVersion(plugin.id, state.projectPath);
|
|
470
|
-
}
|
|
460
|
+
await cliUninstallPlugin(plugin.id, scope);
|
|
461
|
+
}
|
|
462
|
+
else if (action === "update") {
|
|
463
|
+
await cliUpdatePlugin(plugin.id, scope);
|
|
471
464
|
}
|
|
472
465
|
else {
|
|
473
|
-
|
|
474
|
-
if (scopeValue === "user") {
|
|
475
|
-
await enableGlobalPlugin(plugin.id, true);
|
|
476
|
-
await saveGlobalInstalledPluginVersion(plugin.id, latestVersion);
|
|
477
|
-
}
|
|
478
|
-
else if (scopeValue === "project") {
|
|
479
|
-
await enablePlugin(plugin.id, true, state.projectPath);
|
|
480
|
-
await saveInstalledPluginVersion(plugin.id, latestVersion, state.projectPath);
|
|
481
|
-
}
|
|
482
|
-
else {
|
|
483
|
-
await enableLocalPlugin(plugin.id, true, state.projectPath);
|
|
484
|
-
await saveLocalInstalledPluginVersion(plugin.id, latestVersion, state.projectPath);
|
|
485
|
-
}
|
|
466
|
+
await cliInstallPlugin(plugin.id, scope);
|
|
486
467
|
// On fresh install, prompt for MCP server env vars if needed
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
await collectPluginEnvVars(plugin.name, plugin.marketplace);
|
|
490
|
-
}
|
|
468
|
+
modal.hideModal();
|
|
469
|
+
await collectPluginEnvVars(plugin.name, plugin.marketplace);
|
|
491
470
|
}
|
|
492
471
|
if (action !== "install") {
|
|
493
472
|
modal.hideModal();
|
|
@@ -505,16 +484,10 @@ export function PluginsScreen() {
|
|
|
505
484
|
if (!item || item.type !== "plugin" || !item.plugin?.hasUpdate)
|
|
506
485
|
return;
|
|
507
486
|
const plugin = item.plugin;
|
|
508
|
-
const
|
|
487
|
+
const scope = pluginsState.scope === "global" ? "user" : "project";
|
|
509
488
|
modal.loading(`Updating ${plugin.name}...`);
|
|
510
489
|
try {
|
|
511
|
-
|
|
512
|
-
if (isGlobal) {
|
|
513
|
-
await saveGlobalInstalledPluginVersion(plugin.id, versionToSave);
|
|
514
|
-
}
|
|
515
|
-
else {
|
|
516
|
-
await saveInstalledPluginVersion(plugin.id, versionToSave, state.projectPath);
|
|
517
|
-
}
|
|
490
|
+
await cliUpdatePlugin(plugin.id, scope);
|
|
518
491
|
modal.hideModal();
|
|
519
492
|
fetchData();
|
|
520
493
|
}
|
|
@@ -529,17 +502,11 @@ export function PluginsScreen() {
|
|
|
529
502
|
const updatable = pluginsState.plugins.data.filter((p) => p.hasUpdate);
|
|
530
503
|
if (updatable.length === 0)
|
|
531
504
|
return;
|
|
532
|
-
const
|
|
505
|
+
const scope = pluginsState.scope === "global" ? "user" : "project";
|
|
533
506
|
modal.loading(`Updating ${updatable.length} plugin(s)...`);
|
|
534
507
|
try {
|
|
535
508
|
for (const plugin of updatable) {
|
|
536
|
-
|
|
537
|
-
if (isGlobal) {
|
|
538
|
-
await saveGlobalInstalledPluginVersion(plugin.id, versionToSave);
|
|
539
|
-
}
|
|
540
|
-
else {
|
|
541
|
-
await saveInstalledPluginVersion(plugin.id, versionToSave, state.projectPath);
|
|
542
|
-
}
|
|
509
|
+
await cliUpdatePlugin(plugin.id, scope);
|
|
543
510
|
}
|
|
544
511
|
modal.hideModal();
|
|
545
512
|
fetchData();
|
|
@@ -589,39 +556,16 @@ export function PluginsScreen() {
|
|
|
589
556
|
modal.loading(`${actionLabel}...`);
|
|
590
557
|
try {
|
|
591
558
|
if (action === "uninstall") {
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
}
|
|
597
|
-
else if (scope === "project") {
|
|
598
|
-
await enablePlugin(plugin.id, false, state.projectPath);
|
|
599
|
-
await removeInstalledPluginVersion(plugin.id, state.projectPath);
|
|
600
|
-
}
|
|
601
|
-
else {
|
|
602
|
-
await enableLocalPlugin(plugin.id, false, state.projectPath);
|
|
603
|
-
await removeLocalInstalledPluginVersion(plugin.id, state.projectPath);
|
|
604
|
-
}
|
|
559
|
+
await cliUninstallPlugin(plugin.id, scope);
|
|
560
|
+
}
|
|
561
|
+
else if (action === "update") {
|
|
562
|
+
await cliUpdatePlugin(plugin.id, scope);
|
|
605
563
|
}
|
|
606
564
|
else {
|
|
607
|
-
|
|
608
|
-
if (scope === "user") {
|
|
609
|
-
await enableGlobalPlugin(plugin.id, true);
|
|
610
|
-
await saveGlobalInstalledPluginVersion(plugin.id, latestVersion);
|
|
611
|
-
}
|
|
612
|
-
else if (scope === "project") {
|
|
613
|
-
await enablePlugin(plugin.id, true, state.projectPath);
|
|
614
|
-
await saveInstalledPluginVersion(plugin.id, latestVersion, state.projectPath);
|
|
615
|
-
}
|
|
616
|
-
else {
|
|
617
|
-
await enableLocalPlugin(plugin.id, true, state.projectPath);
|
|
618
|
-
await saveLocalInstalledPluginVersion(plugin.id, latestVersion, state.projectPath);
|
|
619
|
-
}
|
|
565
|
+
await cliInstallPlugin(plugin.id, scope);
|
|
620
566
|
// On fresh install, prompt for MCP server env vars if needed
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
await collectPluginEnvVars(plugin.name, plugin.marketplace);
|
|
624
|
-
}
|
|
567
|
+
modal.hideModal();
|
|
568
|
+
await collectPluginEnvVars(plugin.name, plugin.marketplace);
|
|
625
569
|
}
|
|
626
570
|
if (action !== "install") {
|
|
627
571
|
modal.hideModal();
|
|
@@ -667,19 +611,7 @@ export function PluginsScreen() {
|
|
|
667
611
|
return; // Cancelled
|
|
668
612
|
modal.loading(`Uninstalling ${plugin.name}...`);
|
|
669
613
|
try {
|
|
670
|
-
|
|
671
|
-
await enableGlobalPlugin(plugin.id, false);
|
|
672
|
-
await removeGlobalInstalledPluginVersion(plugin.id);
|
|
673
|
-
}
|
|
674
|
-
else if (scopeValue === "project") {
|
|
675
|
-
await enablePlugin(plugin.id, false, state.projectPath);
|
|
676
|
-
await removeInstalledPluginVersion(plugin.id, state.projectPath);
|
|
677
|
-
}
|
|
678
|
-
else {
|
|
679
|
-
// local scope
|
|
680
|
-
await enableLocalPlugin(plugin.id, false, state.projectPath);
|
|
681
|
-
await removeLocalInstalledPluginVersion(plugin.id, state.projectPath);
|
|
682
|
-
}
|
|
614
|
+
await cliUninstallPlugin(plugin.id, scopeValue);
|
|
683
615
|
modal.hideModal();
|
|
684
616
|
fetchData();
|
|
685
617
|
}
|