@laststance/claude-plugin-dashboard 0.2.3 → 0.3.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/README.md +7 -1
- package/dist/app.d.ts +7 -1
- package/dist/app.js +544 -262
- package/dist/cli.js +60 -67
- package/dist/components/ComponentBadges.d.ts +0 -9
- package/dist/components/ComponentBadges.js +0 -33
- package/dist/components/ComponentDetail.d.ts +32 -0
- package/dist/components/ComponentDetail.js +106 -0
- package/dist/components/ComponentList.d.ts +87 -0
- package/dist/components/ComponentList.js +287 -0
- package/dist/components/HelpOverlay.js +1 -0
- package/dist/components/KeyHints.d.ts +1 -0
- package/dist/components/KeyHints.js +33 -29
- package/dist/components/MarketplaceActionMenu.d.ts +41 -0
- package/dist/components/MarketplaceActionMenu.js +68 -0
- package/dist/components/MarketplaceDetail.d.ts +10 -3
- package/dist/components/MarketplaceDetail.js +10 -4
- package/dist/components/PluginDetail.d.ts +19 -3
- package/dist/components/PluginDetail.js +56 -6
- package/dist/components/PluginList.js +19 -7
- package/dist/services/componentService.d.ts +10 -31
- package/dist/services/componentService.js +19 -174
- package/dist/services/components/hookService.d.ts +17 -0
- package/dist/services/components/hookService.js +45 -0
- package/dist/services/components/index.d.ts +41 -0
- package/dist/services/components/index.js +126 -0
- package/dist/services/components/markdownService.d.ts +39 -0
- package/dist/services/components/markdownService.js +147 -0
- package/dist/services/components/serverService.d.ts +28 -0
- package/dist/services/components/serverService.js +69 -0
- package/dist/services/components/skillService.d.ts +48 -0
- package/dist/services/components/skillService.js +164 -0
- package/dist/services/components/utils.d.ts +23 -0
- package/dist/services/components/utils.js +42 -0
- package/dist/services/marketplaceActionsService.d.ts +17 -0
- package/dist/services/marketplaceActionsService.js +18 -0
- package/dist/services/pluginActionsService.d.ts +31 -2
- package/dist/services/pluginActionsService.js +65 -6
- package/dist/services/pluginService.js +78 -2
- package/dist/store/index.d.ts +46 -0
- package/dist/store/index.js +47 -0
- package/dist/store/slices/marketplaceSlice.d.ts +344 -0
- package/dist/store/slices/marketplaceSlice.js +152 -0
- package/dist/store/slices/pluginSlice.d.ts +1544 -0
- package/dist/store/slices/pluginSlice.js +191 -0
- package/dist/store/slices/uiSlice.d.ts +147 -0
- package/dist/store/slices/uiSlice.js +126 -0
- package/dist/tabs/DiscoverTab.d.ts +8 -2
- package/dist/tabs/DiscoverTab.js +2 -2
- package/dist/tabs/EnabledTab.d.ts +8 -2
- package/dist/tabs/EnabledTab.js +3 -3
- package/dist/tabs/ErrorsTab.js +1 -1
- package/dist/tabs/InstalledTab.d.ts +8 -2
- package/dist/tabs/InstalledTab.js +3 -3
- package/dist/tabs/MarketplacesTab.d.ts +15 -2
- package/dist/tabs/MarketplacesTab.js +13 -4
- package/dist/types/index.d.ts +157 -5
- package/package.json +10 -3
|
@@ -13,18 +13,27 @@ import SearchInput from '../components/SearchInput.js';
|
|
|
13
13
|
* @param selectedIndex - Currently selected item index
|
|
14
14
|
* @param searchQuery - Current search query string
|
|
15
15
|
* @param focusZone - Current focus zone for keyboard navigation
|
|
16
|
+
* @param showActionMenu - Whether to show the action menu
|
|
17
|
+
* @param actionMenuSelectedIndex - Selected index in action menu
|
|
16
18
|
* @example
|
|
17
|
-
* <MarketplacesTab
|
|
19
|
+
* <MarketplacesTab
|
|
20
|
+
* marketplaces={marketplaces}
|
|
21
|
+
* selectedIndex={0}
|
|
22
|
+
* searchQuery=""
|
|
23
|
+
* focusZone="list"
|
|
24
|
+
* showActionMenu={false}
|
|
25
|
+
* actionMenuSelectedIndex={0}
|
|
26
|
+
* />
|
|
18
27
|
*/
|
|
19
|
-
export default function MarketplacesTab({ marketplaces, selectedIndex, searchQuery = '', focusZone = 'list', }) {
|
|
28
|
+
export default function MarketplacesTab({ marketplaces, selectedIndex, searchQuery = '', focusZone = 'list', showActionMenu = false, actionMenuSelectedIndex = 0, }) {
|
|
20
29
|
const selectedMarketplace = marketplaces[selectedIndex] ?? null;
|
|
21
30
|
// Count total plugins across all marketplaces
|
|
22
31
|
const totalPlugins = marketplaces.reduce((sum, m) => sum + (m.pluginCount || 0), 0);
|
|
23
32
|
return (_jsxs(Box, { flexDirection: "column", flexGrow: 1, children: [_jsxs(Box, { marginBottom: 1, gap: 2, children: [_jsxs(Text, { bold: true, children: ["Marketplaces (", marketplaces.length > 0
|
|
24
33
|
? `${selectedIndex + 1}/${marketplaces.length}`
|
|
25
|
-
: '0', ")"] }), _jsx(Box, { flexGrow: 1 }), _jsxs(Text, { color: "gray", children: [totalPlugins, " total plugins"] })] }), _jsx(Box, { marginBottom: 1, children: _jsx(SearchInput, { query: searchQuery, isActive: focusZone === 'search', placeholder: "Type to search marketplaces..." }) }), _jsxs(Box, { flexGrow: 1, children: [_jsx(Box, { width: "50%", flexDirection: "column", children: marketplaces.length === 0 ? (_jsxs(Box, { padding: 1, flexDirection: "column", children: [_jsx(Text, { color: "gray", children: searchQuery
|
|
34
|
+
: '0', ")"] }), _jsx(Box, { flexGrow: 1 }), _jsxs(Text, { color: "gray", children: [totalPlugins, " total plugins"] })] }), _jsx(Box, { marginBottom: 1, children: _jsx(SearchInput, { query: searchQuery, isActive: focusZone === 'search', placeholder: "Type to search marketplaces..." }) }), _jsxs(Box, { flexGrow: 1, overflow: "hidden", children: [_jsx(Box, { width: "50%", flexDirection: "column", overflow: "hidden", children: marketplaces.length === 0 ? (_jsxs(Box, { padding: 1, flexDirection: "column", children: [_jsx(Text, { color: "gray", children: searchQuery
|
|
26
35
|
? 'No matching marketplaces'
|
|
27
36
|
: 'No marketplaces found' }), _jsx(Text, { dimColor: true, children: searchQuery
|
|
28
37
|
? 'Try a different search term'
|
|
29
|
-
: 'Add marketplaces with /plugin add-marketplace' })] })) : (_jsx(MarketplaceList, { marketplaces: marketplaces, selectedIndex: selectedIndex, isFocused: focusZone === 'list' })) }), _jsx(Box, { width: "50%", flexDirection: "column", children: _jsx(MarketplaceDetail, { marketplace: selectedMarketplace }) })] })] }));
|
|
38
|
+
: 'Add marketplaces with /plugin add-marketplace' })] })) : (_jsx(MarketplaceList, { marketplaces: marketplaces, selectedIndex: selectedIndex, isFocused: focusZone === 'list' })) }), _jsx(Box, { width: "50%", flexDirection: "column", overflow: "hidden", children: _jsx(MarketplaceDetail, { marketplace: selectedMarketplace, showActionMenu: showActionMenu, actionMenuSelectedIndex: actionMenuSelectedIndex }) })] })] }));
|
|
30
39
|
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -3,7 +3,114 @@
|
|
|
3
3
|
* These types aggregate data from multiple Claude Code configuration files
|
|
4
4
|
*/
|
|
5
5
|
/**
|
|
6
|
-
* Component
|
|
6
|
+
* Component type identifier
|
|
7
|
+
*/
|
|
8
|
+
export type ComponentType = 'skill' | 'command' | 'agent' | 'hook' | 'mcp' | 'lsp';
|
|
9
|
+
/**
|
|
10
|
+
* Individual component information with name and optional description
|
|
11
|
+
*
|
|
12
|
+
* Data Source Architecture:
|
|
13
|
+
* ```
|
|
14
|
+
* ┌─────────────────────────────────────────────────────────────┐
|
|
15
|
+
* │ Plugin Installed? │
|
|
16
|
+
* │ │ │
|
|
17
|
+
* │ ┌──── YES ─────┴───── NO ────┐ │
|
|
18
|
+
* │ │ │ │
|
|
19
|
+
* │ ▼ ▼ │
|
|
20
|
+
* │ ┌─────────────────────┐ ┌─────────────────────┐ │
|
|
21
|
+
* │ │ File System Scan │ │ Marketplace JSON │ │
|
|
22
|
+
* │ │ ───────────────── │ │ ───────────────── │ │
|
|
23
|
+
* │ │ skills/{name}/ │ │ skills: [ │ │
|
|
24
|
+
* │ │ commands/{name}.md │ │ "./skills/xlsx" │ │
|
|
25
|
+
* │ │ agents/{name}.md │ │ ] │ │
|
|
26
|
+
* │ │ plugin.json keys │ │ │ │
|
|
27
|
+
* │ └─────────────────────┘ └─────────────────────┘ │
|
|
28
|
+
* │ │ │ │
|
|
29
|
+
* │ ▼ ▼ │
|
|
30
|
+
* │ Names + Descriptions Names only (if available) │
|
|
31
|
+
* │ │
|
|
32
|
+
* │ └────────────────────────────┘ │
|
|
33
|
+
* │ │ │
|
|
34
|
+
* │ ▼ │
|
|
35
|
+
* │ PluginComponentsDetailed │
|
|
36
|
+
* │ ───────────────────────── │
|
|
37
|
+
* │ { │
|
|
38
|
+
* │ skills: [ │
|
|
39
|
+
* │ { name: "xlsx", description: "..." }, │
|
|
40
|
+
* │ { name: "docx" } │
|
|
41
|
+
* │ ], │
|
|
42
|
+
* │ mcpServers: ["supabase", "context7"] │
|
|
43
|
+
* │ } │
|
|
44
|
+
* └─────────────────────────────────────────────────────────────┘
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* // Skill with description (from SKILL.md frontmatter)
|
|
49
|
+
* { name: "xlsx", description: "Spreadsheet editing", type: "skill" }
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* // Command without description
|
|
53
|
+
* { name: "code-review", type: "command" }
|
|
54
|
+
*/
|
|
55
|
+
export interface ComponentInfo {
|
|
56
|
+
/** Component name (e.g., "xlsx", "code-review") */
|
|
57
|
+
name: string;
|
|
58
|
+
/** Optional description from SKILL.md frontmatter or first line of .md file */
|
|
59
|
+
description?: string;
|
|
60
|
+
/** Component type for display categorization */
|
|
61
|
+
type: ComponentType;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Extended component information with full SKILL.md parsing
|
|
65
|
+
* Used for Component detail view in PluginDetail panel
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* {
|
|
69
|
+
* name: "sentry-code-review",
|
|
70
|
+
* description: "Analyze and resolve Sentry comments...",
|
|
71
|
+
* type: "skill",
|
|
72
|
+
* allowedTools: ["Read", "Edit", "Write", "Bash", "Grep"],
|
|
73
|
+
* fullDescription: "Full markdown body content...",
|
|
74
|
+
* filePath: "/Users/.../skills/sentry-code-review/SKILL.md"
|
|
75
|
+
* }
|
|
76
|
+
*/
|
|
77
|
+
export interface ComponentDetailedInfo extends ComponentInfo {
|
|
78
|
+
/** Allowed tools from SKILL.md frontmatter (allowed-tools field) */
|
|
79
|
+
allowedTools?: string[];
|
|
80
|
+
/** Full markdown body content (after frontmatter) */
|
|
81
|
+
fullDescription?: string;
|
|
82
|
+
/** Absolute file path for reference */
|
|
83
|
+
filePath?: string;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Detailed component information for a plugin
|
|
87
|
+
* Extends PluginComponents (counts) with actual component names and descriptions
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* {
|
|
91
|
+
* skills: [
|
|
92
|
+
* { name: "xlsx", description: "Spreadsheet editing", type: "skill" },
|
|
93
|
+
* { name: "docx", type: "skill" }
|
|
94
|
+
* ],
|
|
95
|
+
* mcpServers: ["supabase", "context7"]
|
|
96
|
+
* }
|
|
97
|
+
*/
|
|
98
|
+
export interface PluginComponentsDetailed {
|
|
99
|
+
/** Skill details (name + optional description) */
|
|
100
|
+
skills?: ComponentInfo[];
|
|
101
|
+
/** Command details */
|
|
102
|
+
commands?: ComponentInfo[];
|
|
103
|
+
/** Agent details */
|
|
104
|
+
agents?: ComponentInfo[];
|
|
105
|
+
/** Hook event names */
|
|
106
|
+
hooks?: string[];
|
|
107
|
+
/** MCP server names from plugin.json mcpServers keys */
|
|
108
|
+
mcpServers?: string[];
|
|
109
|
+
/** LSP server language IDs from .lsp.json keys */
|
|
110
|
+
lspServers?: string[];
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Component types provided by a plugin (counts only)
|
|
7
114
|
* Detected by scanning plugin directory structure and plugin.json
|
|
8
115
|
* @example
|
|
9
116
|
* { skills: 5, commands: 2, mcpServers: 1 } // Plugin with skills, commands, and MCP
|
|
@@ -64,6 +171,8 @@ export interface Plugin {
|
|
|
64
171
|
gitCommitSha?: string;
|
|
65
172
|
/** Component types provided by this plugin (skills, commands, MCP, etc.) */
|
|
66
173
|
components?: PluginComponents;
|
|
174
|
+
/** Detailed component info with names and descriptions */
|
|
175
|
+
componentsDetailed?: PluginComponentsDetailed;
|
|
67
176
|
}
|
|
68
177
|
/**
|
|
69
178
|
* Raw installed plugin data from installed_plugins.json
|
|
@@ -98,6 +207,7 @@ export interface Marketplace {
|
|
|
98
207
|
installLocation: string;
|
|
99
208
|
lastUpdated: string;
|
|
100
209
|
pluginCount?: number;
|
|
210
|
+
autoUpdate?: boolean;
|
|
101
211
|
}
|
|
102
212
|
/**
|
|
103
213
|
* Structure of known_marketplaces.json file
|
|
@@ -111,6 +221,7 @@ export interface KnownMarketplacesFile {
|
|
|
111
221
|
};
|
|
112
222
|
installLocation: string;
|
|
113
223
|
lastUpdated: string;
|
|
224
|
+
autoUpdate?: boolean;
|
|
114
225
|
};
|
|
115
226
|
}
|
|
116
227
|
/**
|
|
@@ -128,6 +239,12 @@ export interface MarketplacePluginEntry {
|
|
|
128
239
|
homepage?: string;
|
|
129
240
|
tags?: string[];
|
|
130
241
|
keywords?: string[];
|
|
242
|
+
/** Skill paths from marketplace.json (e.g., ["./skills/xlsx"]) */
|
|
243
|
+
skills?: string[];
|
|
244
|
+
/** Agent paths from marketplace.json */
|
|
245
|
+
agents?: string[];
|
|
246
|
+
/** Command paths from marketplace.json */
|
|
247
|
+
commands?: string[];
|
|
131
248
|
}
|
|
132
249
|
/**
|
|
133
250
|
* Structure of marketplace.json file
|
|
@@ -178,7 +295,7 @@ export interface Settings {
|
|
|
178
295
|
* Focus zones for keyboard navigation
|
|
179
296
|
* Defines which UI area currently has keyboard focus
|
|
180
297
|
*/
|
|
181
|
-
export type FocusZone = 'tabbar' | 'search' | 'list';
|
|
298
|
+
export type FocusZone = 'tabbar' | 'search' | 'list' | 'components';
|
|
182
299
|
/**
|
|
183
300
|
* Marketplace operation types
|
|
184
301
|
*/
|
|
@@ -211,12 +328,20 @@ export interface AppState {
|
|
|
211
328
|
error: string | null;
|
|
212
329
|
/** Status message */
|
|
213
330
|
message: string | null;
|
|
214
|
-
/** Current async operation (install/uninstall) */
|
|
215
|
-
operation: 'idle' | 'installing' | 'uninstalling';
|
|
331
|
+
/** Current async operation (install/uninstall/update) */
|
|
332
|
+
operation: 'idle' | 'installing' | 'uninstalling' | 'updating';
|
|
216
333
|
/** Plugin ID being operated on */
|
|
217
334
|
operationPluginId: string | null;
|
|
218
335
|
/** Whether confirmation dialog is showing */
|
|
219
336
|
confirmUninstall: boolean;
|
|
337
|
+
/** Whether update all confirmation dialog is showing */
|
|
338
|
+
confirmUpdateAll: boolean;
|
|
339
|
+
/** Progress of bulk update operation */
|
|
340
|
+
updateProgress: {
|
|
341
|
+
current: number;
|
|
342
|
+
total: number;
|
|
343
|
+
pluginId: string;
|
|
344
|
+
} | null;
|
|
220
345
|
/** Whether help overlay is showing */
|
|
221
346
|
showHelp: boolean;
|
|
222
347
|
/** Current marketplace operation */
|
|
@@ -229,6 +354,12 @@ export interface AppState {
|
|
|
229
354
|
showAddMarketplaceDialog: boolean;
|
|
230
355
|
/** Error message for add marketplace dialog */
|
|
231
356
|
addMarketplaceError: string | null;
|
|
357
|
+
/** Whether marketplace action menu is showing */
|
|
358
|
+
showMarketplaceActionMenu: boolean;
|
|
359
|
+
/** Selected index in marketplace action menu */
|
|
360
|
+
actionMenuSelectedIndex: number;
|
|
361
|
+
/** Selected component index within the current plugin */
|
|
362
|
+
selectedComponentIndex: number;
|
|
232
363
|
}
|
|
233
364
|
/**
|
|
234
365
|
* Action types for useReducer
|
|
@@ -282,7 +413,7 @@ export type Action = {
|
|
|
282
413
|
} | {
|
|
283
414
|
type: 'START_OPERATION';
|
|
284
415
|
payload: {
|
|
285
|
-
operation: 'installing' | 'uninstalling';
|
|
416
|
+
operation: 'installing' | 'uninstalling' | 'updating';
|
|
286
417
|
pluginId: string;
|
|
287
418
|
};
|
|
288
419
|
} | {
|
|
@@ -317,4 +448,25 @@ export type Action = {
|
|
|
317
448
|
} | {
|
|
318
449
|
type: 'SET_ADD_MARKETPLACE_ERROR';
|
|
319
450
|
payload: string | null;
|
|
451
|
+
} | {
|
|
452
|
+
type: 'SHOW_MARKETPLACE_ACTION_MENU';
|
|
453
|
+
} | {
|
|
454
|
+
type: 'HIDE_MARKETPLACE_ACTION_MENU';
|
|
455
|
+
} | {
|
|
456
|
+
type: 'SET_ACTION_MENU_INDEX';
|
|
457
|
+
payload: number;
|
|
458
|
+
} | {
|
|
459
|
+
type: 'MOVE_ACTION_MENU_SELECTION';
|
|
460
|
+
payload: 'up' | 'down';
|
|
461
|
+
} | {
|
|
462
|
+
type: 'SET_COMPONENT_INDEX';
|
|
463
|
+
payload: number;
|
|
464
|
+
} | {
|
|
465
|
+
type: 'MOVE_COMPONENT_SELECTION';
|
|
466
|
+
payload: 'up' | 'down';
|
|
467
|
+
maxIndex: number;
|
|
468
|
+
} | {
|
|
469
|
+
type: 'ENTER_COMPONENT_MODE';
|
|
470
|
+
} | {
|
|
471
|
+
type: 'EXIT_COMPONENT_MODE';
|
|
320
472
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@laststance/claude-plugin-dashboard",
|
|
3
|
-
"version": "0.2
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Interactive CLI dashboard to manage Claude Code plugins",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Ryota Murakami <ryota.murakami@laststance.io> (https://github.com/ryota-murakami)",
|
|
@@ -47,13 +47,19 @@
|
|
|
47
47
|
"prettier": "prettier --ignore-unknown --write .",
|
|
48
48
|
"test": "vitest",
|
|
49
49
|
"test:run": "vitest run",
|
|
50
|
-
"test:coverage": "vitest run --coverage"
|
|
50
|
+
"test:coverage": "vitest run --coverage",
|
|
51
|
+
"push-release-commit": "push-release-commit"
|
|
51
52
|
},
|
|
52
53
|
"dependencies": {
|
|
54
|
+
"@reduxjs/toolkit": "^2.11.2",
|
|
55
|
+
"fullscreen-ink": "^0.1.0",
|
|
53
56
|
"ink": "^5.1.0",
|
|
54
|
-
"react": "^18.3.1"
|
|
57
|
+
"react": "^18.3.1",
|
|
58
|
+
"react-redux": "^9.2.0",
|
|
59
|
+
"ts-pattern": "^5.9.0"
|
|
55
60
|
},
|
|
56
61
|
"devDependencies": {
|
|
62
|
+
"@laststance/npm-publish-tool": "^2.1.0",
|
|
57
63
|
"@sindresorhus/tsconfig": "^6.0.0",
|
|
58
64
|
"@types/node": "^22.10.2",
|
|
59
65
|
"@types/react": "^18.3.18",
|
|
@@ -62,6 +68,7 @@
|
|
|
62
68
|
"ink-testing-library": "^4.0.0",
|
|
63
69
|
"lint-staged": "^16.2.7",
|
|
64
70
|
"prettier": "^3.7.4",
|
|
71
|
+
"release-it": "^19.2.4",
|
|
65
72
|
"typescript": "^5.7.2",
|
|
66
73
|
"vitest": "^4.0.16"
|
|
67
74
|
}
|