groove-dev 0.12.8 → 0.13.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/node_modules/@groove-dev/daemon/skills-registry.json +233 -0
- package/node_modules/@groove-dev/daemon/src/api.js +41 -0
- package/node_modules/@groove-dev/daemon/src/index.js +2 -0
- package/node_modules/@groove-dev/daemon/src/skills.js +198 -0
- package/node_modules/@groove-dev/gui/dist/assets/index-C4fB8_Qg.js +74 -0
- package/node_modules/@groove-dev/gui/dist/index.html +1 -1
- package/node_modules/@groove-dev/gui/src/App.jsx +3 -0
- package/node_modules/@groove-dev/gui/src/views/SkillsMarketplace.jsx +350 -0
- package/package.json +1 -1
- package/packages/daemon/skills-registry.json +233 -0
- package/packages/daemon/src/api.js +41 -0
- package/packages/daemon/src/index.js +2 -0
- package/packages/daemon/src/skills.js +198 -0
- package/packages/gui/dist/assets/index-C4fB8_Qg.js +74 -0
- package/packages/gui/dist/index.html +1 -1
- package/packages/gui/src/App.jsx +3 -0
- package/packages/gui/src/views/SkillsMarketplace.jsx +350 -0
- package/node_modules/@groove-dev/gui/dist/assets/index-CeyNe9uc.js +0 -73
- package/packages/gui/dist/assets/index-CeyNe9uc.js +0 -73
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>GROOVE</title>
|
|
7
|
-
<script type="module" crossorigin src="/assets/index-
|
|
7
|
+
<script type="module" crossorigin src="/assets/index-C4fB8_Qg.js"></script>
|
|
8
8
|
<link rel="stylesheet" crossorigin href="/assets/index-Gfb8Zxy9.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
@@ -11,9 +11,11 @@ import JournalistFeed from './views/JournalistFeed';
|
|
|
11
11
|
import TeamSelector from './components/TeamSelector';
|
|
12
12
|
import CommandCenter from './views/CommandCenter';
|
|
13
13
|
import ApprovalQueue from './components/ApprovalQueue';
|
|
14
|
+
import SkillsMarketplace from './views/SkillsMarketplace';
|
|
14
15
|
|
|
15
16
|
const TABS = [
|
|
16
17
|
{ id: 'agents', label: 'Agents' },
|
|
18
|
+
{ id: 'skills', label: 'Skills' },
|
|
17
19
|
{ id: 'stats', label: 'Stats' },
|
|
18
20
|
{ id: 'teams', label: 'Teams' },
|
|
19
21
|
{ id: 'approvals', label: 'Approvals' },
|
|
@@ -138,6 +140,7 @@ export default function App() {
|
|
|
138
140
|
{activeTab === 'agents' && (
|
|
139
141
|
!hasAgents ? <EmptyState /> : <AgentTree />
|
|
140
142
|
)}
|
|
143
|
+
{activeTab === 'skills' && <SkillsMarketplace />}
|
|
141
144
|
{activeTab === 'stats' && <CommandCenter />}
|
|
142
145
|
{activeTab === 'teams' && <TeamSelector />}
|
|
143
146
|
{activeTab === 'approvals' && <ApprovalQueue />}
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
// GROOVE GUI — Skills Marketplace
|
|
2
|
+
// FSL-1.1-Apache-2.0 — see LICENSE
|
|
3
|
+
|
|
4
|
+
import React, { useState, useEffect } from 'react';
|
|
5
|
+
|
|
6
|
+
const CATEGORY_LABELS = {
|
|
7
|
+
all: 'All Skills',
|
|
8
|
+
design: 'Design',
|
|
9
|
+
quality: 'Quality',
|
|
10
|
+
devtools: 'Dev Tools',
|
|
11
|
+
workflow: 'Workflow',
|
|
12
|
+
security: 'Security',
|
|
13
|
+
specialized: 'Specialized',
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export default function SkillsMarketplace() {
|
|
17
|
+
const [skills, setSkills] = useState([]);
|
|
18
|
+
const [categories, setCategories] = useState([]);
|
|
19
|
+
const [search, setSearch] = useState('');
|
|
20
|
+
const [category, setCategory] = useState('all');
|
|
21
|
+
const [loading, setLoading] = useState(true);
|
|
22
|
+
const [installing, setInstalling] = useState(null);
|
|
23
|
+
const [expandedSkill, setExpandedSkill] = useState(null);
|
|
24
|
+
const [skillContent, setSkillContent] = useState(null);
|
|
25
|
+
const [hovered, setHovered] = useState(null);
|
|
26
|
+
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
fetchSkills();
|
|
29
|
+
}, [search, category]);
|
|
30
|
+
|
|
31
|
+
async function fetchSkills() {
|
|
32
|
+
setLoading(true);
|
|
33
|
+
try {
|
|
34
|
+
const params = new URLSearchParams();
|
|
35
|
+
if (search) params.set('search', search);
|
|
36
|
+
if (category !== 'all') params.set('category', category);
|
|
37
|
+
const res = await fetch(`/api/skills/registry?${params}`);
|
|
38
|
+
const data = await res.json();
|
|
39
|
+
setSkills(data.skills || []);
|
|
40
|
+
setCategories(data.categories || []);
|
|
41
|
+
} catch { /* ignore */ }
|
|
42
|
+
setLoading(false);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async function handleInstall(id) {
|
|
46
|
+
setInstalling(id);
|
|
47
|
+
try {
|
|
48
|
+
await fetch(`/api/skills/${id}/install`, { method: 'POST' });
|
|
49
|
+
await fetchSkills();
|
|
50
|
+
} catch { /* ignore */ }
|
|
51
|
+
setInstalling(null);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async function handleUninstall(id) {
|
|
55
|
+
setInstalling(id);
|
|
56
|
+
try {
|
|
57
|
+
await fetch(`/api/skills/${id}`, { method: 'DELETE' });
|
|
58
|
+
setExpandedSkill(null);
|
|
59
|
+
setSkillContent(null);
|
|
60
|
+
await fetchSkills();
|
|
61
|
+
} catch { /* ignore */ }
|
|
62
|
+
setInstalling(null);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async function handleExpand(skill) {
|
|
66
|
+
if (expandedSkill === skill.id) {
|
|
67
|
+
setExpandedSkill(null);
|
|
68
|
+
setSkillContent(null);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
setExpandedSkill(skill.id);
|
|
72
|
+
setSkillContent(null);
|
|
73
|
+
if (skill.installed) {
|
|
74
|
+
try {
|
|
75
|
+
const res = await fetch(`/api/skills/${skill.id}/content`);
|
|
76
|
+
const data = await res.json();
|
|
77
|
+
setSkillContent(data.content);
|
|
78
|
+
} catch { /* ignore */ }
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const installedCount = skills.filter((s) => s.installed).length;
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<div style={styles.root}>
|
|
86
|
+
{/* Header */}
|
|
87
|
+
<div style={styles.header}>
|
|
88
|
+
<div>
|
|
89
|
+
<div style={styles.title}>Skills Marketplace</div>
|
|
90
|
+
<div style={styles.subtitle}>
|
|
91
|
+
{skills.length} skills available, {installedCount} installed
|
|
92
|
+
</div>
|
|
93
|
+
</div>
|
|
94
|
+
</div>
|
|
95
|
+
|
|
96
|
+
{/* Search + Categories */}
|
|
97
|
+
<div style={styles.toolbar}>
|
|
98
|
+
<input
|
|
99
|
+
style={styles.search}
|
|
100
|
+
placeholder="Search skills..."
|
|
101
|
+
value={search}
|
|
102
|
+
onChange={(e) => setSearch(e.target.value)}
|
|
103
|
+
/>
|
|
104
|
+
<div style={styles.catRow}>
|
|
105
|
+
<button
|
|
106
|
+
onClick={() => setCategory('all')}
|
|
107
|
+
style={{
|
|
108
|
+
...styles.catBtn,
|
|
109
|
+
...(category === 'all' ? styles.catBtnActive : {}),
|
|
110
|
+
}}
|
|
111
|
+
>
|
|
112
|
+
All
|
|
113
|
+
</button>
|
|
114
|
+
{categories.map((cat) => (
|
|
115
|
+
<button
|
|
116
|
+
key={cat.id}
|
|
117
|
+
onClick={() => setCategory(cat.id)}
|
|
118
|
+
style={{
|
|
119
|
+
...styles.catBtn,
|
|
120
|
+
...(category === cat.id ? styles.catBtnActive : {}),
|
|
121
|
+
}}
|
|
122
|
+
>
|
|
123
|
+
{CATEGORY_LABELS[cat.id] || cat.id} ({cat.count})
|
|
124
|
+
</button>
|
|
125
|
+
))}
|
|
126
|
+
</div>
|
|
127
|
+
</div>
|
|
128
|
+
|
|
129
|
+
{/* Skills Grid */}
|
|
130
|
+
<div style={styles.grid}>
|
|
131
|
+
{loading && skills.length === 0 && (
|
|
132
|
+
<div style={styles.empty}>Loading skills...</div>
|
|
133
|
+
)}
|
|
134
|
+
|
|
135
|
+
{!loading && skills.length === 0 && (
|
|
136
|
+
<div style={styles.empty}>No skills match your search.</div>
|
|
137
|
+
)}
|
|
138
|
+
|
|
139
|
+
{skills.map((skill) => (
|
|
140
|
+
<div key={skill.id}>
|
|
141
|
+
<div
|
|
142
|
+
onClick={() => handleExpand(skill)}
|
|
143
|
+
onMouseEnter={() => setHovered(skill.id)}
|
|
144
|
+
onMouseLeave={() => setHovered(null)}
|
|
145
|
+
style={{
|
|
146
|
+
...styles.card,
|
|
147
|
+
borderColor: skill.installed ? 'var(--green)' : (hovered === skill.id ? 'var(--accent)' : 'var(--border)'),
|
|
148
|
+
background: hovered === skill.id ? 'var(--bg-hover)' : 'var(--bg-surface)',
|
|
149
|
+
}}
|
|
150
|
+
>
|
|
151
|
+
{/* Card header */}
|
|
152
|
+
<div style={styles.cardTop}>
|
|
153
|
+
<div style={{
|
|
154
|
+
...styles.cardIcon,
|
|
155
|
+
background: skill.installed ? 'var(--green)' : 'var(--accent)',
|
|
156
|
+
}}>
|
|
157
|
+
{skill.icon || skill.name.charAt(0)}
|
|
158
|
+
</div>
|
|
159
|
+
<div style={styles.cardInfo}>
|
|
160
|
+
<div style={styles.cardName}>{skill.name}</div>
|
|
161
|
+
<div style={styles.cardAuthor}>{skill.author}</div>
|
|
162
|
+
</div>
|
|
163
|
+
{skill.installed && (
|
|
164
|
+
<div style={styles.installedBadge}>installed</div>
|
|
165
|
+
)}
|
|
166
|
+
</div>
|
|
167
|
+
|
|
168
|
+
{/* Description */}
|
|
169
|
+
<div style={styles.cardDesc}>{skill.description}</div>
|
|
170
|
+
|
|
171
|
+
{/* Tags */}
|
|
172
|
+
<div style={styles.tagRow}>
|
|
173
|
+
<span style={styles.catTag}>{CATEGORY_LABELS[skill.category] || skill.category}</span>
|
|
174
|
+
{skill.roles.slice(0, 3).map((r) => (
|
|
175
|
+
<span key={r} style={styles.roleTag}>{r}</span>
|
|
176
|
+
))}
|
|
177
|
+
</div>
|
|
178
|
+
</div>
|
|
179
|
+
|
|
180
|
+
{/* Expanded detail */}
|
|
181
|
+
{expandedSkill === skill.id && (
|
|
182
|
+
<div style={styles.detail}>
|
|
183
|
+
{skillContent && (
|
|
184
|
+
<div style={styles.contentPreview}>
|
|
185
|
+
<div style={styles.contentLabel}>SKILL INSTRUCTIONS</div>
|
|
186
|
+
<pre style={styles.contentPre}>
|
|
187
|
+
{skillContent.replace(/^---[\s\S]*?---\n/, '').trim().slice(0, 800)}
|
|
188
|
+
{skillContent.length > 800 ? '\n...' : ''}
|
|
189
|
+
</pre>
|
|
190
|
+
</div>
|
|
191
|
+
)}
|
|
192
|
+
<div style={styles.detailActions}>
|
|
193
|
+
{skill.installed ? (
|
|
194
|
+
<button
|
|
195
|
+
onClick={(e) => { e.stopPropagation(); handleUninstall(skill.id); }}
|
|
196
|
+
disabled={installing === skill.id}
|
|
197
|
+
style={styles.uninstallBtn}
|
|
198
|
+
>
|
|
199
|
+
{installing === skill.id ? 'Removing...' : 'Uninstall'}
|
|
200
|
+
</button>
|
|
201
|
+
) : (
|
|
202
|
+
<button
|
|
203
|
+
onClick={(e) => { e.stopPropagation(); handleInstall(skill.id); }}
|
|
204
|
+
disabled={installing === skill.id}
|
|
205
|
+
style={styles.installBtn}
|
|
206
|
+
>
|
|
207
|
+
{installing === skill.id ? 'Installing...' : 'Install'}
|
|
208
|
+
</button>
|
|
209
|
+
)}
|
|
210
|
+
</div>
|
|
211
|
+
</div>
|
|
212
|
+
)}
|
|
213
|
+
</div>
|
|
214
|
+
))}
|
|
215
|
+
</div>
|
|
216
|
+
</div>
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const styles = {
|
|
221
|
+
root: {
|
|
222
|
+
height: '100%', display: 'flex', flexDirection: 'column',
|
|
223
|
+
overflow: 'hidden',
|
|
224
|
+
},
|
|
225
|
+
header: {
|
|
226
|
+
padding: '16px 20px 0',
|
|
227
|
+
flexShrink: 0,
|
|
228
|
+
},
|
|
229
|
+
title: {
|
|
230
|
+
fontSize: 14, fontWeight: 700, color: 'var(--text-bright)',
|
|
231
|
+
},
|
|
232
|
+
subtitle: {
|
|
233
|
+
fontSize: 11, color: 'var(--text-dim)', marginTop: 2,
|
|
234
|
+
},
|
|
235
|
+
toolbar: {
|
|
236
|
+
padding: '12px 20px',
|
|
237
|
+
flexShrink: 0,
|
|
238
|
+
},
|
|
239
|
+
search: {
|
|
240
|
+
width: '100%', padding: '8px 12px',
|
|
241
|
+
background: 'var(--bg-surface)', border: '1px solid var(--border)',
|
|
242
|
+
borderRadius: 4, color: 'var(--text-primary)', fontSize: 12,
|
|
243
|
+
fontFamily: 'var(--font)', outline: 'none',
|
|
244
|
+
},
|
|
245
|
+
catRow: {
|
|
246
|
+
display: 'flex', gap: 4, marginTop: 8, flexWrap: 'wrap',
|
|
247
|
+
},
|
|
248
|
+
catBtn: {
|
|
249
|
+
padding: '3px 10px',
|
|
250
|
+
background: 'transparent', border: '1px solid var(--border)',
|
|
251
|
+
borderRadius: 12, color: 'var(--text-dim)', fontSize: 10,
|
|
252
|
+
fontFamily: 'var(--font)', cursor: 'pointer',
|
|
253
|
+
transition: 'all 0.1s',
|
|
254
|
+
},
|
|
255
|
+
catBtnActive: {
|
|
256
|
+
borderColor: 'var(--accent)', color: 'var(--accent)',
|
|
257
|
+
background: 'rgba(51, 175, 188, 0.08)',
|
|
258
|
+
},
|
|
259
|
+
grid: {
|
|
260
|
+
flex: 1, overflowY: 'auto', padding: '0 20px 20px',
|
|
261
|
+
display: 'flex', flexDirection: 'column', gap: 6,
|
|
262
|
+
},
|
|
263
|
+
empty: {
|
|
264
|
+
padding: '40px 0', textAlign: 'center',
|
|
265
|
+
color: 'var(--text-dim)', fontSize: 12,
|
|
266
|
+
},
|
|
267
|
+
card: {
|
|
268
|
+
padding: '12px 14px',
|
|
269
|
+
background: 'var(--bg-surface)', border: '1px solid var(--border)',
|
|
270
|
+
borderRadius: 6, cursor: 'pointer',
|
|
271
|
+
transition: 'border-color 0.1s, background 0.1s',
|
|
272
|
+
},
|
|
273
|
+
cardTop: {
|
|
274
|
+
display: 'flex', alignItems: 'center', gap: 10,
|
|
275
|
+
},
|
|
276
|
+
cardIcon: {
|
|
277
|
+
width: 32, height: 32, borderRadius: 6,
|
|
278
|
+
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
|
279
|
+
fontSize: 13, fontWeight: 700, color: 'var(--bg-base)',
|
|
280
|
+
flexShrink: 0,
|
|
281
|
+
},
|
|
282
|
+
cardInfo: {
|
|
283
|
+
flex: 1, minWidth: 0,
|
|
284
|
+
},
|
|
285
|
+
cardName: {
|
|
286
|
+
fontSize: 12, fontWeight: 600, color: 'var(--text-bright)',
|
|
287
|
+
},
|
|
288
|
+
cardAuthor: {
|
|
289
|
+
fontSize: 10, color: 'var(--text-muted)',
|
|
290
|
+
},
|
|
291
|
+
installedBadge: {
|
|
292
|
+
fontSize: 9, fontWeight: 600, color: 'var(--green)',
|
|
293
|
+
border: '1px solid var(--green)', borderRadius: 3,
|
|
294
|
+
padding: '1px 6px', textTransform: 'uppercase', letterSpacing: 0.5,
|
|
295
|
+
flexShrink: 0,
|
|
296
|
+
},
|
|
297
|
+
cardDesc: {
|
|
298
|
+
fontSize: 11, color: 'var(--text-dim)', marginTop: 8,
|
|
299
|
+
lineHeight: 1.45,
|
|
300
|
+
display: '-webkit-box', WebkitLineClamp: 2, WebkitBoxOrient: 'vertical',
|
|
301
|
+
overflow: 'hidden',
|
|
302
|
+
},
|
|
303
|
+
tagRow: {
|
|
304
|
+
display: 'flex', gap: 4, marginTop: 8, flexWrap: 'wrap',
|
|
305
|
+
},
|
|
306
|
+
catTag: {
|
|
307
|
+
fontSize: 9, padding: '1px 6px', borderRadius: 3,
|
|
308
|
+
background: 'var(--bg-active)', color: 'var(--text-dim)',
|
|
309
|
+
fontWeight: 600, textTransform: 'uppercase', letterSpacing: 0.5,
|
|
310
|
+
},
|
|
311
|
+
roleTag: {
|
|
312
|
+
fontSize: 9, padding: '1px 6px', borderRadius: 3,
|
|
313
|
+
background: 'rgba(51, 175, 188, 0.1)', color: 'var(--accent)',
|
|
314
|
+
},
|
|
315
|
+
detail: {
|
|
316
|
+
margin: '0 0 4px',
|
|
317
|
+
padding: '10px 14px',
|
|
318
|
+
background: 'var(--bg-base)', border: '1px solid var(--border)',
|
|
319
|
+
borderTop: 'none', borderRadius: '0 0 6px 6px',
|
|
320
|
+
},
|
|
321
|
+
contentPreview: {
|
|
322
|
+
marginBottom: 10,
|
|
323
|
+
},
|
|
324
|
+
contentLabel: {
|
|
325
|
+
fontSize: 9, fontWeight: 600, color: 'var(--text-muted)',
|
|
326
|
+
textTransform: 'uppercase', letterSpacing: 1, marginBottom: 6,
|
|
327
|
+
},
|
|
328
|
+
contentPre: {
|
|
329
|
+
fontSize: 10, color: 'var(--text-dim)', lineHeight: 1.5,
|
|
330
|
+
fontFamily: 'var(--font)', whiteSpace: 'pre-wrap', wordBreak: 'break-word',
|
|
331
|
+
maxHeight: 200, overflowY: 'auto',
|
|
332
|
+
padding: '8px 10px', background: 'var(--bg-surface)',
|
|
333
|
+
border: '1px solid var(--border)', borderRadius: 4,
|
|
334
|
+
},
|
|
335
|
+
detailActions: {
|
|
336
|
+
display: 'flex', justifyContent: 'flex-end', gap: 8,
|
|
337
|
+
},
|
|
338
|
+
installBtn: {
|
|
339
|
+
padding: '6px 20px',
|
|
340
|
+
background: 'var(--accent)', border: '1px solid var(--accent)',
|
|
341
|
+
borderRadius: 4, color: 'var(--bg-base)', fontSize: 11, fontWeight: 700,
|
|
342
|
+
fontFamily: 'var(--font)', cursor: 'pointer',
|
|
343
|
+
},
|
|
344
|
+
uninstallBtn: {
|
|
345
|
+
padding: '6px 16px',
|
|
346
|
+
background: 'transparent', border: '1px solid var(--red)',
|
|
347
|
+
borderRadius: 4, color: 'var(--red)', fontSize: 11, fontWeight: 600,
|
|
348
|
+
fontFamily: 'var(--font)', cursor: 'pointer',
|
|
349
|
+
},
|
|
350
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "groove-dev",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Open-source agent orchestration layer for AI coding tools. GUI dashboard, multi-agent coordination, zero cold-start (Journalist), infinite sessions (adaptive context rotation), AI Project Manager, Quick Launch. Works with Claude Code, Codex, Gemini CLI, Ollama.",
|
|
5
5
|
"license": "FSL-1.1-Apache-2.0",
|
|
6
6
|
"author": "Groove Dev <hello@groovedev.ai> (https://groovedev.ai)",
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"id": "frontend-design",
|
|
4
|
+
"name": "Frontend Design",
|
|
5
|
+
"description": "Create distinctive, production-grade frontend interfaces with high design quality. Avoids generic AI aesthetics.",
|
|
6
|
+
"author": "Anthropic",
|
|
7
|
+
"category": "design",
|
|
8
|
+
"tags": ["frontend", "ui", "css", "react", "design-system"],
|
|
9
|
+
"roles": ["frontend", "fullstack"],
|
|
10
|
+
"source": "claude-official",
|
|
11
|
+
"icon": "P"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"id": "code-review",
|
|
15
|
+
"name": "Code Review",
|
|
16
|
+
"description": "Comprehensive PR code review using parallel specialized agents. Checks CLAUDE.md compliance, bugs, git history, and previous PR comments.",
|
|
17
|
+
"author": "Anthropic",
|
|
18
|
+
"category": "quality",
|
|
19
|
+
"tags": ["review", "pr", "github", "quality"],
|
|
20
|
+
"roles": ["testing", "fullstack"],
|
|
21
|
+
"source": "claude-official",
|
|
22
|
+
"icon": "R"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"id": "security-guidance",
|
|
26
|
+
"name": "Security Guidance",
|
|
27
|
+
"description": "Security-focused development guidance. OWASP top 10, input validation, auth patterns, secrets management.",
|
|
28
|
+
"author": "Anthropic",
|
|
29
|
+
"category": "security",
|
|
30
|
+
"tags": ["security", "owasp", "auth", "validation"],
|
|
31
|
+
"roles": ["backend", "fullstack", "devops"],
|
|
32
|
+
"source": "claude-official",
|
|
33
|
+
"icon": "S"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"id": "claude-automation-recommender",
|
|
37
|
+
"name": "Automation Recommender",
|
|
38
|
+
"description": "Analyze a codebase and recommend Claude Code automations — hooks, subagents, skills, plugins, MCP servers.",
|
|
39
|
+
"author": "Anthropic",
|
|
40
|
+
"category": "devtools",
|
|
41
|
+
"tags": ["automation", "hooks", "plugins", "mcp", "setup"],
|
|
42
|
+
"roles": ["planner", "devops", "fullstack"],
|
|
43
|
+
"source": "claude-official",
|
|
44
|
+
"icon": "A"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"id": "claude-md-improver",
|
|
48
|
+
"name": "CLAUDE.md Improver",
|
|
49
|
+
"description": "Audit and improve CLAUDE.md files. Scans quality, evaluates against templates, makes targeted updates.",
|
|
50
|
+
"author": "Anthropic",
|
|
51
|
+
"category": "devtools",
|
|
52
|
+
"tags": ["claude-md", "project-config", "audit"],
|
|
53
|
+
"roles": ["planner", "fullstack"],
|
|
54
|
+
"source": "claude-official",
|
|
55
|
+
"icon": "C"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"id": "build-mcp-server",
|
|
59
|
+
"name": "Build MCP Server",
|
|
60
|
+
"description": "End-to-end MCP server development. Interrogates use case, picks deployment model, designs tools, hands off to specialized skills.",
|
|
61
|
+
"author": "Anthropic",
|
|
62
|
+
"category": "devtools",
|
|
63
|
+
"tags": ["mcp", "api", "integration", "tools"],
|
|
64
|
+
"roles": ["backend", "fullstack"],
|
|
65
|
+
"source": "claude-official",
|
|
66
|
+
"icon": "M"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"id": "build-mcp-app",
|
|
70
|
+
"name": "Build MCP App",
|
|
71
|
+
"description": "Add interactive UI widgets to MCP servers — forms, pickers, dashboards, confirmation dialogs inline in chat.",
|
|
72
|
+
"author": "Anthropic",
|
|
73
|
+
"category": "devtools",
|
|
74
|
+
"tags": ["mcp", "ui", "widgets", "apps-sdk"],
|
|
75
|
+
"roles": ["frontend", "fullstack"],
|
|
76
|
+
"source": "claude-official",
|
|
77
|
+
"icon": "U"
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"id": "feature-dev",
|
|
81
|
+
"name": "Feature Development",
|
|
82
|
+
"description": "Guided feature development with codebase understanding and architecture focus. Structured workflow from research to implementation.",
|
|
83
|
+
"author": "Anthropic",
|
|
84
|
+
"category": "workflow",
|
|
85
|
+
"tags": ["feature", "architecture", "guided", "development"],
|
|
86
|
+
"roles": ["backend", "frontend", "fullstack"],
|
|
87
|
+
"source": "claude-official",
|
|
88
|
+
"icon": "F"
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"id": "skill-creator",
|
|
92
|
+
"name": "Skill Creator",
|
|
93
|
+
"description": "Create new skills, modify existing ones, run evals, benchmark performance. The meta-skill for building skills.",
|
|
94
|
+
"author": "Anthropic",
|
|
95
|
+
"category": "devtools",
|
|
96
|
+
"tags": ["skills", "plugins", "meta", "evals"],
|
|
97
|
+
"roles": ["planner", "fullstack"],
|
|
98
|
+
"source": "claude-official",
|
|
99
|
+
"icon": "K"
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"id": "plugin-structure",
|
|
103
|
+
"name": "Plugin Structure",
|
|
104
|
+
"description": "Scaffold and organize Claude Code plugins. Directory layout, manifest, components, auto-discovery patterns.",
|
|
105
|
+
"author": "Anthropic",
|
|
106
|
+
"category": "devtools",
|
|
107
|
+
"tags": ["plugins", "scaffold", "architecture"],
|
|
108
|
+
"roles": ["fullstack", "devops"],
|
|
109
|
+
"source": "claude-official",
|
|
110
|
+
"icon": "L"
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"id": "hook-development",
|
|
114
|
+
"name": "Hook Development",
|
|
115
|
+
"description": "Create PreToolUse, PostToolUse, Stop hooks. Event-driven automation, tool validation, prompt-based hooks API.",
|
|
116
|
+
"author": "Anthropic",
|
|
117
|
+
"category": "devtools",
|
|
118
|
+
"tags": ["hooks", "automation", "events", "validation"],
|
|
119
|
+
"roles": ["devops", "fullstack"],
|
|
120
|
+
"source": "claude-official",
|
|
121
|
+
"icon": "H"
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"id": "agent-development",
|
|
125
|
+
"name": "Agent Development",
|
|
126
|
+
"description": "Create subagents with system prompts, triggering conditions, tool access, and autonomous behavior patterns.",
|
|
127
|
+
"author": "Anthropic",
|
|
128
|
+
"category": "devtools",
|
|
129
|
+
"tags": ["agents", "subagents", "autonomous"],
|
|
130
|
+
"roles": ["planner", "fullstack"],
|
|
131
|
+
"source": "claude-official",
|
|
132
|
+
"icon": "G"
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"id": "playground",
|
|
136
|
+
"name": "Playground Builder",
|
|
137
|
+
"description": "Create interactive HTML playgrounds — single-file explorers with live preview, visual controls, and copy-out prompts.",
|
|
138
|
+
"author": "Anthropic",
|
|
139
|
+
"category": "design",
|
|
140
|
+
"tags": ["playground", "interactive", "html", "demo"],
|
|
141
|
+
"roles": ["frontend", "docs"],
|
|
142
|
+
"source": "claude-official",
|
|
143
|
+
"icon": "Y"
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
"id": "math-olympiad",
|
|
147
|
+
"name": "Math Olympiad",
|
|
148
|
+
"description": "Advanced mathematical problem solving. Competition-level math, proofs, and formal reasoning.",
|
|
149
|
+
"author": "Anthropic",
|
|
150
|
+
"category": "specialized",
|
|
151
|
+
"tags": ["math", "proofs", "reasoning", "competition"],
|
|
152
|
+
"roles": [],
|
|
153
|
+
"source": "claude-official",
|
|
154
|
+
"icon": "X"
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
"id": "hookify",
|
|
158
|
+
"name": "Hookify",
|
|
159
|
+
"description": "Create hooks to prevent unwanted behaviors from conversation analysis or explicit instructions. Rule-based automation.",
|
|
160
|
+
"author": "Anthropic",
|
|
161
|
+
"category": "devtools",
|
|
162
|
+
"tags": ["hooks", "rules", "automation", "guardrails"],
|
|
163
|
+
"roles": ["devops", "fullstack"],
|
|
164
|
+
"source": "claude-official",
|
|
165
|
+
"icon": "I"
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
"id": "code-simplifier",
|
|
169
|
+
"name": "Code Simplifier",
|
|
170
|
+
"description": "Review changed code for reuse, quality, and efficiency. Identifies over-engineering and suggests simplifications.",
|
|
171
|
+
"author": "Anthropic",
|
|
172
|
+
"category": "quality",
|
|
173
|
+
"tags": ["refactor", "simplify", "quality", "efficiency"],
|
|
174
|
+
"roles": ["backend", "frontend", "fullstack"],
|
|
175
|
+
"source": "claude-official",
|
|
176
|
+
"icon": "Z"
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
"id": "commit-commands",
|
|
180
|
+
"name": "Commit Commands",
|
|
181
|
+
"description": "Git workflow commands — commit, push, open PR, clean gone branches. Structured commit messages.",
|
|
182
|
+
"author": "Anthropic",
|
|
183
|
+
"category": "workflow",
|
|
184
|
+
"tags": ["git", "commit", "pr", "workflow"],
|
|
185
|
+
"roles": ["fullstack", "backend", "frontend"],
|
|
186
|
+
"source": "claude-official",
|
|
187
|
+
"icon": "V"
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
"id": "pr-review-toolkit",
|
|
191
|
+
"name": "PR Review Toolkit",
|
|
192
|
+
"description": "Comprehensive PR review using specialized parallel agents. Multi-angle analysis with confidence scoring.",
|
|
193
|
+
"author": "Anthropic",
|
|
194
|
+
"category": "quality",
|
|
195
|
+
"tags": ["pr", "review", "github", "parallel-agents"],
|
|
196
|
+
"roles": ["testing", "fullstack"],
|
|
197
|
+
"source": "claude-official",
|
|
198
|
+
"icon": "T"
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
"id": "new-sdk-app",
|
|
202
|
+
"name": "Agent SDK Starter",
|
|
203
|
+
"description": "Create and setup a new Claude Agent SDK application. Scaffolds project structure and configuration.",
|
|
204
|
+
"author": "Anthropic",
|
|
205
|
+
"category": "devtools",
|
|
206
|
+
"tags": ["agent-sdk", "scaffold", "setup"],
|
|
207
|
+
"roles": ["backend", "fullstack"],
|
|
208
|
+
"source": "claude-official",
|
|
209
|
+
"icon": "N"
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
"id": "explanatory-output",
|
|
213
|
+
"name": "Explanatory Output",
|
|
214
|
+
"description": "Output style that explains reasoning and decisions. Teaches while building — great for learning and code review.",
|
|
215
|
+
"author": "Anthropic",
|
|
216
|
+
"category": "workflow",
|
|
217
|
+
"tags": ["output-style", "learning", "explanatory"],
|
|
218
|
+
"roles": [],
|
|
219
|
+
"source": "claude-official",
|
|
220
|
+
"icon": "E"
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
"id": "learning-output",
|
|
224
|
+
"name": "Learning Output",
|
|
225
|
+
"description": "Output style optimized for learning. Step-by-step explanations, concept breakdowns, guided understanding.",
|
|
226
|
+
"author": "Anthropic",
|
|
227
|
+
"category": "workflow",
|
|
228
|
+
"tags": ["output-style", "learning", "educational"],
|
|
229
|
+
"roles": [],
|
|
230
|
+
"source": "claude-official",
|
|
231
|
+
"icon": "W"
|
|
232
|
+
}
|
|
233
|
+
]
|
|
@@ -365,6 +365,47 @@ export function createApi(app, daemon) {
|
|
|
365
365
|
res.json(daemon.adaptive.getAllProfiles());
|
|
366
366
|
});
|
|
367
367
|
|
|
368
|
+
// --- Skills Marketplace ---
|
|
369
|
+
|
|
370
|
+
app.get('/api/skills/registry', (req, res) => {
|
|
371
|
+
const skills = daemon.skills.getRegistry({
|
|
372
|
+
search: req.query.search || '',
|
|
373
|
+
category: req.query.category || 'all',
|
|
374
|
+
});
|
|
375
|
+
res.json({
|
|
376
|
+
skills,
|
|
377
|
+
categories: daemon.skills.getCategories(),
|
|
378
|
+
});
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
app.get('/api/skills/installed', (req, res) => {
|
|
382
|
+
res.json(daemon.skills.getInstalled());
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
app.post('/api/skills/:id/install', (req, res) => {
|
|
386
|
+
try {
|
|
387
|
+
const result = daemon.skills.install(req.params.id);
|
|
388
|
+
res.json(result);
|
|
389
|
+
} catch (err) {
|
|
390
|
+
res.status(400).json({ error: err.message });
|
|
391
|
+
}
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
app.delete('/api/skills/:id', (req, res) => {
|
|
395
|
+
try {
|
|
396
|
+
const result = daemon.skills.uninstall(req.params.id);
|
|
397
|
+
res.json(result);
|
|
398
|
+
} catch (err) {
|
|
399
|
+
res.status(400).json({ error: err.message });
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
app.get('/api/skills/:id/content', (req, res) => {
|
|
404
|
+
const content = daemon.skills.getContent(req.params.id);
|
|
405
|
+
if (!content) return res.status(404).json({ error: 'Skill not installed' });
|
|
406
|
+
res.json({ id: req.params.id, content });
|
|
407
|
+
});
|
|
408
|
+
|
|
368
409
|
// --- Directory Browser ---
|
|
369
410
|
|
|
370
411
|
app.get('/api/browse', (req, res) => {
|
|
@@ -27,6 +27,7 @@ import { ProjectManager } from './pm.js';
|
|
|
27
27
|
import { CodebaseIndexer } from './indexer.js';
|
|
28
28
|
import { AuditLogger } from './audit.js';
|
|
29
29
|
import { Federation } from './federation.js';
|
|
30
|
+
import { SkillStore } from './skills.js';
|
|
30
31
|
import { isFirstRun, runFirstTimeSetup, loadConfig, saveConfig, printWelcome } from './firstrun.js';
|
|
31
32
|
|
|
32
33
|
const DEFAULT_PORT = 31415;
|
|
@@ -115,6 +116,7 @@ export class Daemon {
|
|
|
115
116
|
this.indexer = new CodebaseIndexer(this);
|
|
116
117
|
this.audit = new AuditLogger(this.grooveDir);
|
|
117
118
|
this.federation = new Federation(this);
|
|
119
|
+
this.skills = new SkillStore(this);
|
|
118
120
|
|
|
119
121
|
// HTTP + WebSocket server
|
|
120
122
|
this.app = express();
|