claudeup 4.22.0 → 4.23.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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claudeup",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.23.0",
|
|
4
4
|
"description": "TUI tool for managing Claude Code plugins, MCPs, and configuration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/main.tsx",
|
|
@@ -64,8 +64,8 @@
|
|
|
64
64
|
"typescript": "^5.6.3"
|
|
65
65
|
},
|
|
66
66
|
"optionalDependencies": {
|
|
67
|
-
"claudeup-darwin-arm64": "4.
|
|
68
|
-
"claudeup-darwin-x64": "4.
|
|
69
|
-
"claudeup-linux-x64": "4.
|
|
67
|
+
"claudeup-darwin-arm64": "4.23.0",
|
|
68
|
+
"claudeup-darwin-x64": "4.23.0",
|
|
69
|
+
"claudeup-linux-x64": "4.23.0"
|
|
70
70
|
}
|
|
71
71
|
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import { buildPluginBrowserItems } from "../ui/adapters/pluginsAdapter.js";
|
|
3
|
+
import type { Marketplace } from "../types/index.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The marketplace category badge is the line users read on every claudeup launch,
|
|
7
|
+
* and it had no coverage. The MadAppGang byline must not leak onto anyone else's
|
|
8
|
+
* marketplace, and the Official/Deprecated markers must still win.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const mp = (over: Partial<Marketplace> & { name: string }): Marketplace => ({
|
|
12
|
+
displayName: over.displayName ?? over.name,
|
|
13
|
+
source: { source: "github", repo: `someone/${over.name}` },
|
|
14
|
+
description: "",
|
|
15
|
+
...over,
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
/** Badge for a marketplace when it has plugins and is expanded. */
|
|
19
|
+
function badgeFor(marketplace: Marketplace): string | undefined {
|
|
20
|
+
const items = buildPluginBrowserItems({
|
|
21
|
+
marketplaces: [marketplace],
|
|
22
|
+
plugins: [
|
|
23
|
+
{
|
|
24
|
+
id: `demo@${marketplace.name}`,
|
|
25
|
+
name: "demo",
|
|
26
|
+
marketplace: marketplace.name,
|
|
27
|
+
// Only the fields the adapter groups on matter here.
|
|
28
|
+
} as never,
|
|
29
|
+
],
|
|
30
|
+
collapsedMarketplaces: new Set(),
|
|
31
|
+
});
|
|
32
|
+
const category = items.find((i) => i.kind === "category");
|
|
33
|
+
return category && "badge" in category ? category.badge : undefined;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
describe("marketplace category badge", () => {
|
|
37
|
+
test("MadAppGang marketplaces carry the byline instead of a generic label", () => {
|
|
38
|
+
for (const name of ["magus", "magus-marketing", "magus-alpha"]) {
|
|
39
|
+
const badge = badgeFor(
|
|
40
|
+
mp({ name, source: { source: "github", repo: `MadAppGang/${name}` } }),
|
|
41
|
+
);
|
|
42
|
+
expect(badge).toBe("made with ❤️ by MadAppGang");
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test("owner match is case-insensitive", () => {
|
|
47
|
+
// The npm/GitHub casing of the org has varied in config; don't depend on it.
|
|
48
|
+
const badge = badgeFor(
|
|
49
|
+
mp({ name: "magus", source: { source: "github", repo: "madappgang/magus" } }),
|
|
50
|
+
);
|
|
51
|
+
expect(badge).toBe("made with ❤️ by MadAppGang");
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test("someone else's marketplace does NOT claim the byline", () => {
|
|
55
|
+
const badge = badgeFor(
|
|
56
|
+
mp({
|
|
57
|
+
name: "superpowers-marketplace",
|
|
58
|
+
source: { source: "github", repo: "obra/superpowers-marketplace" },
|
|
59
|
+
}),
|
|
60
|
+
);
|
|
61
|
+
expect(badge).toBe("✓ Added");
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test("a repo merely containing 'madappgang' downstream does not match", () => {
|
|
65
|
+
// Guards against a substring check — only the owner segment counts.
|
|
66
|
+
const badge = badgeFor(
|
|
67
|
+
mp({ name: "impostor", source: { source: "github", repo: "evil/madappgang-magus" } }),
|
|
68
|
+
);
|
|
69
|
+
expect(badge).toBe("✓ Added");
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test("Official and Deprecated still take precedence", () => {
|
|
73
|
+
expect(
|
|
74
|
+
badgeFor(
|
|
75
|
+
mp({
|
|
76
|
+
name: "claude-plugins-official",
|
|
77
|
+
source: { source: "github", repo: "anthropics/claude-plugins-official" },
|
|
78
|
+
}),
|
|
79
|
+
),
|
|
80
|
+
).toBe("★ Official");
|
|
81
|
+
|
|
82
|
+
expect(
|
|
83
|
+
badgeFor(
|
|
84
|
+
mp({
|
|
85
|
+
name: "claude-code-plugins",
|
|
86
|
+
source: { source: "github", repo: "anthropics/claude-code" },
|
|
87
|
+
}),
|
|
88
|
+
),
|
|
89
|
+
).toBe("⚠ Deprecated");
|
|
90
|
+
});
|
|
91
|
+
});
|
|
@@ -86,10 +86,10 @@ describe("resolveExtends", () => {
|
|
|
86
86
|
extends: "growth-marketer",
|
|
87
87
|
};
|
|
88
88
|
const merged = resolveExtends(entry);
|
|
89
|
-
// seo/
|
|
89
|
+
// seo/image-generate/video-editing ship on the magus-marketing channel and
|
|
90
90
|
// pin it explicitly — they must NOT be rewritten to @magus.
|
|
91
91
|
expect(merged.plugins!["seo@magus-marketing"]).toBe("latest");
|
|
92
|
-
expect(merged.plugins!["
|
|
92
|
+
expect(merged.plugins!["image-generate@magus-marketing"]).toBe("latest");
|
|
93
93
|
expect(merged.plugins!["video-editing@magus-marketing"]).toBe("latest");
|
|
94
94
|
expect(merged.plugins!["seo@magus"]).toBeUndefined();
|
|
95
95
|
// Bare names still default to @magus.
|
|
@@ -201,7 +201,7 @@ export const PREDEFINED_PROFILES: PredefinedProfile[] = [
|
|
|
201
201
|
"statusline",
|
|
202
202
|
"seo@magus-marketing",
|
|
203
203
|
"browser-use",
|
|
204
|
-
"
|
|
204
|
+
"image-generate@magus-marketing",
|
|
205
205
|
"video-editing@magus-marketing",
|
|
206
206
|
],
|
|
207
207
|
anthropicPlugins: [
|
|
@@ -65,9 +65,22 @@ function categoryStyling(
|
|
|
65
65
|
if (mp.official) {
|
|
66
66
|
return { tone: "yellow", badge: "★ Official" };
|
|
67
67
|
}
|
|
68
|
+
if (isMadAppGang(mp)) {
|
|
69
|
+
return { tone: "green", badge: "made with ❤️ by MadAppGang" };
|
|
70
|
+
}
|
|
68
71
|
return { tone: "green", badge: "✓ Added" };
|
|
69
72
|
}
|
|
70
73
|
|
|
74
|
+
/**
|
|
75
|
+
* Our own marketplaces (magus, magus-marketing, magus-alpha) get the byline
|
|
76
|
+
* instead of the generic "Added". Matched on the repo owner rather than a list
|
|
77
|
+
* of names, so a new channel picks it up without a code change. Same idiom the
|
|
78
|
+
* marketplace sort uses to float MadAppGang entries to the top.
|
|
79
|
+
*/
|
|
80
|
+
function isMadAppGang(mp: Marketplace): boolean {
|
|
81
|
+
return (mp.source.repo ?? "").toLowerCase().startsWith("madappgang/");
|
|
82
|
+
}
|
|
83
|
+
|
|
71
84
|
/**
|
|
72
85
|
* Builds the flat list of items for the PluginsScreen list panel.
|
|
73
86
|
* Extracted from PluginsScreen so it can be tested independently.
|