claude-setup 1.1.7 → 1.1.9
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 +88 -107
- package/dist/builder.d.ts +6 -0
- package/dist/builder.js +143 -80
- package/dist/commands/init.js +8 -1
- package/dist/commands/sync.js +76 -12
- package/dist/marketplace.d.ts +24 -19
- package/dist/marketplace.js +429 -86
- package/dist/os.d.ts +33 -4
- package/dist/os.js +238 -3
- package/package.json +1 -1
- package/templates/add.md +57 -10
- package/templates/sync.md +6 -2
package/dist/marketplace.js
CHANGED
|
@@ -1,27 +1,38 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Marketplace intelligence — provides catalog info and decision logic
|
|
3
|
-
* for the add command to suggest plugins, skills,
|
|
3
|
+
* for the add command to suggest plugins, skills, MCP servers, and agents.
|
|
4
|
+
*
|
|
5
|
+
* Implements the 4-catalog exhaustion pipeline (Rule 6) with 3-stage
|
|
6
|
+
* fetch resolution (Rule 7): find entry → navigate directory → download content.
|
|
4
7
|
*
|
|
5
8
|
* Zero API calls at import time. Catalog is fetched only when needed.
|
|
6
9
|
*/
|
|
10
|
+
// ── Source 1: VoltAgent subagents (agents/sub-agents) ────────────────
|
|
11
|
+
export const VOLTAGENT_SUBAGENTS_REPO = "VoltAgent/awesome-claude-code-subagents";
|
|
12
|
+
export const VOLTAGENT_SUBAGENTS_API = `https://api.github.com/repos/${VOLTAGENT_SUBAGENTS_REPO}/contents/categories`;
|
|
13
|
+
export const VOLTAGENT_SUBAGENTS_RAW = `https://raw.githubusercontent.com/${VOLTAGENT_SUBAGENTS_REPO}/main/categories`;
|
|
14
|
+
export const VOLTAGENT_CATEGORIES = [
|
|
15
|
+
"01-core-development",
|
|
16
|
+
"02-language-specialists",
|
|
17
|
+
"03-infrastructure",
|
|
18
|
+
"04-quality-security",
|
|
19
|
+
"05-data-ai",
|
|
20
|
+
"06-developer-experience",
|
|
21
|
+
"07-specialized-domains",
|
|
22
|
+
"08-business-product",
|
|
23
|
+
"09-meta-orchestration",
|
|
24
|
+
"10-research-analysis",
|
|
25
|
+
];
|
|
26
|
+
// ── Source 2: Community skills catalog (416+ plugins) ───────────────────
|
|
7
27
|
export const MARKETPLACE_REPO = "jeremylongshore/claude-code-plugins-plus-skills";
|
|
8
28
|
export const MARKETPLACE_CATALOG_URL = `https://raw.githubusercontent.com/${MARKETPLACE_REPO}/main/.claude-plugin/marketplace.extended.json`;
|
|
9
|
-
|
|
10
|
-
export const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
name: "awesome-claude-code",
|
|
19
|
-
description: "Community collection of Claude Code skills and workflows",
|
|
20
|
-
catalogUrl: "https://raw.githubusercontent.com/hesreallyhim/awesome-claude-code/main/catalog.json",
|
|
21
|
-
installPrefix: null,
|
|
22
|
-
note: "Browse and manually install skills"
|
|
23
|
-
}
|
|
24
|
-
];
|
|
29
|
+
// ── Source 3: VoltAgent curated agent skills ────────────────────────────
|
|
30
|
+
export const VOLTAGENT_SKILLS_REPO = "VoltAgent/awesome-agent-skills";
|
|
31
|
+
export const VOLTAGENT_SKILLS_API = `https://api.github.com/repos/${VOLTAGENT_SKILLS_REPO}/contents`;
|
|
32
|
+
// ── Source 4: ComposioHQ service integrations (1000+) ───────────────────
|
|
33
|
+
export const COMPOSIO_REPO = "ComposioHQ/awesome-claude-skills";
|
|
34
|
+
export const COMPOSIO_API = `https://api.github.com/repos/${COMPOSIO_REPO}/contents`;
|
|
35
|
+
export const COMPOSIO_RAW = `https://raw.githubusercontent.com/${COMPOSIO_REPO}/master`;
|
|
25
36
|
/** The 20 skill categories in the marketplace */
|
|
26
37
|
export const SKILL_CATEGORIES = [
|
|
27
38
|
"01-code-quality", "02-testing", "03-security",
|
|
@@ -37,7 +48,71 @@ export const SAAS_PACKS = [
|
|
|
37
48
|
"Supabase", "Vercel", "OpenRouter", "GitHub", "Azure", "MongoDB",
|
|
38
49
|
"Playwright", "Tavily", "Stripe", "Slack", "Linear", "Notion",
|
|
39
50
|
];
|
|
40
|
-
|
|
51
|
+
// ── Agent detection keywords ────────────────────────────────────────────
|
|
52
|
+
const AGENT_KEYWORDS = [
|
|
53
|
+
"agent", "subagent", "sub-agent", "orchestrat", "multi-agent",
|
|
54
|
+
"coordinator", "dispatcher", "workflow agent", "task routing",
|
|
55
|
+
"agent system", "agent framework", "meta-agent",
|
|
56
|
+
];
|
|
57
|
+
/** Map agent keywords to VoltAgent category directories */
|
|
58
|
+
const AGENT_CATEGORY_MAP = {
|
|
59
|
+
// Meta / orchestration
|
|
60
|
+
"orchestrat": "09-meta-orchestration",
|
|
61
|
+
"coordinator": "09-meta-orchestration",
|
|
62
|
+
"dispatcher": "09-meta-orchestration",
|
|
63
|
+
"multi-agent": "09-meta-orchestration",
|
|
64
|
+
"meta-agent": "09-meta-orchestration",
|
|
65
|
+
"task routing": "09-meta-orchestration",
|
|
66
|
+
"workflow agent": "09-meta-orchestration",
|
|
67
|
+
"workflow orchestrat": "09-meta-orchestration",
|
|
68
|
+
// Core development
|
|
69
|
+
"code review agent": "01-core-development",
|
|
70
|
+
"api design": "01-core-development",
|
|
71
|
+
"refactor": "01-core-development",
|
|
72
|
+
// Language specialists
|
|
73
|
+
"typescript agent": "02-language-specialists",
|
|
74
|
+
"python agent": "02-language-specialists",
|
|
75
|
+
"rust agent": "02-language-specialists",
|
|
76
|
+
"go agent": "02-language-specialists",
|
|
77
|
+
"java agent": "02-language-specialists",
|
|
78
|
+
"powershell": "02-language-specialists",
|
|
79
|
+
// Infrastructure
|
|
80
|
+
"infra": "03-infrastructure",
|
|
81
|
+
"devops agent": "03-infrastructure",
|
|
82
|
+
"docker agent": "03-infrastructure",
|
|
83
|
+
"kubernetes agent": "03-infrastructure",
|
|
84
|
+
"cloud agent": "03-infrastructure",
|
|
85
|
+
"azure agent": "03-infrastructure",
|
|
86
|
+
"aws agent": "03-infrastructure",
|
|
87
|
+
// Quality & security
|
|
88
|
+
"security agent": "04-quality-security",
|
|
89
|
+
"test agent": "04-quality-security",
|
|
90
|
+
"qa agent": "04-quality-security",
|
|
91
|
+
"audit agent": "04-quality-security",
|
|
92
|
+
// Data & AI
|
|
93
|
+
"data agent": "05-data-ai",
|
|
94
|
+
"data pipeline": "05-data-ai",
|
|
95
|
+
"data engineer": "05-data-ai",
|
|
96
|
+
"ml agent": "05-data-ai",
|
|
97
|
+
"ml pipeline": "05-data-ai",
|
|
98
|
+
"ai agent": "05-data-ai",
|
|
99
|
+
// Developer experience
|
|
100
|
+
"dx agent": "06-developer-experience",
|
|
101
|
+
"productivity agent": "06-developer-experience",
|
|
102
|
+
"documentation agent": "06-developer-experience",
|
|
103
|
+
// Specialized
|
|
104
|
+
"domain agent": "07-specialized-domains",
|
|
105
|
+
"iot agent": "07-specialized-domains",
|
|
106
|
+
"embedded agent": "07-specialized-domains",
|
|
107
|
+
// Business
|
|
108
|
+
"business agent": "08-business-product",
|
|
109
|
+
"product agent": "08-business-product",
|
|
110
|
+
"pm agent": "08-business-product",
|
|
111
|
+
// Research
|
|
112
|
+
"research agent": "10-research-analysis",
|
|
113
|
+
"analysis agent": "10-research-analysis",
|
|
114
|
+
};
|
|
115
|
+
/** Keyword-to-category mapping for classifying skill requests */
|
|
41
116
|
export const KEYWORD_CATEGORY_MAP = {
|
|
42
117
|
// Code quality
|
|
43
118
|
"lint": "01-code-quality", "format": "01-code-quality", "prettier": "01-code-quality",
|
|
@@ -79,13 +154,42 @@ export const KEYWORD_CATEGORY_MAP = {
|
|
|
79
154
|
// Project management
|
|
80
155
|
"project management": "12-project-management", "agile": "12-project-management",
|
|
81
156
|
"sprint": "12-project-management", "kanban": "12-project-management",
|
|
157
|
+
// Communication
|
|
158
|
+
"slack": "13-communication", "email": "13-communication", "notification": "13-communication",
|
|
159
|
+
"discord": "13-communication", "telegram": "13-communication",
|
|
160
|
+
// Content
|
|
161
|
+
"content": "15-content-creation", "blog": "15-content-creation",
|
|
162
|
+
"seo": "15-content-creation", "copywriting": "15-content-creation",
|
|
163
|
+
// Productivity
|
|
164
|
+
"productivity": "20-productivity", "automation": "20-productivity",
|
|
165
|
+
"workflow": "20-productivity",
|
|
82
166
|
};
|
|
83
|
-
/**
|
|
167
|
+
/** Detect whether the request is about agents/subagents/orchestration */
|
|
168
|
+
export function isAgentRequest(input) {
|
|
169
|
+
const lower = input.toLowerCase();
|
|
170
|
+
return AGENT_KEYWORDS.some(kw => lower.includes(kw));
|
|
171
|
+
}
|
|
172
|
+
/** Map input to VoltAgent agent category directories */
|
|
173
|
+
export function matchAgentCategories(input) {
|
|
174
|
+
const lower = input.toLowerCase();
|
|
175
|
+
const matched = new Set();
|
|
176
|
+
for (const [keyword, category] of Object.entries(AGENT_CATEGORY_MAP)) {
|
|
177
|
+
if (lower.includes(keyword)) {
|
|
178
|
+
matched.add(category);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
// Default to meta-orchestration for generic agent requests
|
|
182
|
+
if (matched.size === 0 && isAgentRequest(input)) {
|
|
183
|
+
matched.add("09-meta-orchestration");
|
|
184
|
+
}
|
|
185
|
+
return [...matched];
|
|
186
|
+
}
|
|
187
|
+
/** Classify a user request into marketplace categories and detect agent requests */
|
|
84
188
|
export function classifyRequest(input) {
|
|
85
189
|
const lower = input.toLowerCase();
|
|
86
190
|
const categories = new Set();
|
|
87
191
|
const saasMatches = [];
|
|
88
|
-
// Check keyword matches
|
|
192
|
+
// Check keyword matches for skills
|
|
89
193
|
for (const [keyword, category] of Object.entries(KEYWORD_CATEGORY_MAP)) {
|
|
90
194
|
if (lower.includes(keyword)) {
|
|
91
195
|
categories.add(category);
|
|
@@ -97,120 +201,359 @@ export function classifyRequest(input) {
|
|
|
97
201
|
saasMatches.push(saas);
|
|
98
202
|
}
|
|
99
203
|
}
|
|
100
|
-
return {
|
|
204
|
+
return {
|
|
205
|
+
categories: [...categories],
|
|
206
|
+
saasMatches,
|
|
207
|
+
isAgent: isAgentRequest(input),
|
|
208
|
+
agentCategories: matchAgentCategories(input),
|
|
209
|
+
};
|
|
101
210
|
}
|
|
102
|
-
|
|
211
|
+
// ── Marketplace instruction builder ─────────────────────────────────────
|
|
212
|
+
// Implements Rule 6 (4-catalog exhaustion) and Rule 7 (3-stage fetch).
|
|
213
|
+
// Agent requests route to VoltAgent subagents first.
|
|
214
|
+
// Skill requests route to jeremylongshore → VoltAgent skills → ComposioHQ.
|
|
103
215
|
export function buildMarketplaceInstructions(input) {
|
|
104
|
-
const
|
|
216
|
+
const classification = classifyRequest(input);
|
|
217
|
+
const { categories, saasMatches, isAgent: isAgentReq, agentCategories } = classification;
|
|
105
218
|
const categoryFilter = categories[0] ?? "";
|
|
106
219
|
const lines = [];
|
|
107
|
-
lines.push(`## Marketplace — fully automated install`);
|
|
220
|
+
lines.push(`## Marketplace — fully automated install (DO NOT ASK — JUST DO IT)`);
|
|
108
221
|
lines.push(``);
|
|
109
|
-
lines.push(`
|
|
110
|
-
lines.push(`
|
|
222
|
+
lines.push(`4 catalogs available. You MUST search them ALL in order before giving up.`);
|
|
223
|
+
lines.push(`A fetch failure is NOT a stop condition — it is a routing signal to the next source.`);
|
|
224
|
+
lines.push(`**DO NOT ask the user clarifying questions. Execute every command yourself.**`);
|
|
225
|
+
lines.push(`**Rate-limit safe:** all api.github.com calls include GITHUB_TOKEN when set (5000/hr vs 60/hr).`);
|
|
226
|
+
lines.push(`Downloads use raw.githubusercontent.com (no limit). For heavy usage (10+ installs/hr), set GITHUB_TOKEN.`);
|
|
111
227
|
lines.push(``);
|
|
112
|
-
if (categories.length > 0 || saasMatches.length > 0) {
|
|
113
|
-
lines.push(`###
|
|
228
|
+
if (isAgentReq || categories.length > 0 || saasMatches.length > 0) {
|
|
229
|
+
lines.push(`### Classification for "${input}":`);
|
|
230
|
+
if (isAgentReq)
|
|
231
|
+
lines.push(`- **Type: AGENT** — routing to agent catalogs first`);
|
|
232
|
+
for (const cat of agentCategories)
|
|
233
|
+
lines.push(`- agent-category: ${cat}`);
|
|
114
234
|
for (const cat of categories)
|
|
115
|
-
lines.push(`- category: ${cat}`);
|
|
235
|
+
lines.push(`- skill-category: ${cat}`);
|
|
116
236
|
for (const saas of saasMatches)
|
|
117
237
|
lines.push(`- SaaS: ${saas}`);
|
|
118
238
|
lines.push(``);
|
|
119
239
|
}
|
|
240
|
+
// ── Universal resolution rules (applies to every catalog) ──────
|
|
241
|
+
buildUniversalRulesBlock(lines);
|
|
242
|
+
// ── Route based on request type ───────────────────────────────────
|
|
243
|
+
if (isAgentReq) {
|
|
244
|
+
buildAgentPipeline(lines, input, agentCategories, categoryFilter);
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
buildSkillPipeline(lines, input, categoryFilter, saasMatches);
|
|
248
|
+
}
|
|
249
|
+
// ── Install result format ─────────────────────────────────────────
|
|
120
250
|
lines.push(`---`);
|
|
121
251
|
lines.push(``);
|
|
122
|
-
lines.push(`###
|
|
252
|
+
lines.push(`### Install result format`);
|
|
253
|
+
lines.push(`After installing, confirm with one of:`);
|
|
254
|
+
if (isAgentReq) {
|
|
255
|
+
lines.push(`✅ Agent installed: .claude/agents/<name>.md — [one line: what it orchestrates]`);
|
|
256
|
+
lines.push(`✅ Then add to CLAUDE.md agents section (separate from skills)`);
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
lines.push(`✅ Installed: .claude/skills/<name>/SKILL.md — [one line: what it does]`);
|
|
260
|
+
}
|
|
261
|
+
lines.push(`⏭ No match in [source] — moving to next catalog`);
|
|
262
|
+
lines.push(`🔧 All 4 catalogs exhausted — created production-quality custom ${isAgentReq ? "agent" : "skill"}`);
|
|
263
|
+
lines.push(``);
|
|
264
|
+
return lines.join("\n");
|
|
265
|
+
}
|
|
266
|
+
// ── Agent pipeline (VoltAgent subagents → skills fallback) ──────────
|
|
267
|
+
function buildAgentPipeline(lines, input, agentCategories, categoryFilter) {
|
|
268
|
+
const safeName = input.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
|
|
269
|
+
const targetCategories = agentCategories.length > 0
|
|
270
|
+
? agentCategories
|
|
271
|
+
: ["09-meta-orchestration"];
|
|
272
|
+
// ── STEP 1: VoltAgent/awesome-claude-code-subagents ──────────────
|
|
273
|
+
lines.push(`---`);
|
|
274
|
+
lines.push(``);
|
|
275
|
+
lines.push(`### STEP 1 — VoltAgent subagents (PRIMARY source for agents — 127+ specialized agents)`);
|
|
276
|
+
lines.push(``);
|
|
277
|
+
lines.push(`This is the preferred source for anything agent-shaped. 10 categories, 127+ agents.`);
|
|
278
|
+
lines.push(`If a match is found here, install to \`.claude/agents/\` (NOT .claude/skills/).`);
|
|
279
|
+
lines.push(``);
|
|
280
|
+
lines.push(`**1a. List agent files in the matched categories:**`);
|
|
281
|
+
lines.push(`If any curl below fails, skip to the next category or STEP 2 immediately.`);
|
|
282
|
+
lines.push(``);
|
|
283
|
+
for (const cat of targetCategories) {
|
|
284
|
+
lines.push(`\`\`\`bash`);
|
|
285
|
+
lines.push(`# Category: ${cat}`);
|
|
286
|
+
lines.push(`curl -sf \${GITHUB_TOKEN:+-H "Authorization: token \$GITHUB_TOKEN"} "${VOLTAGENT_SUBAGENTS_API}/${cat}" \\`);
|
|
287
|
+
lines.push(` | node -e "const d=JSON.parse(require('fs').readFileSync(0,'utf8'));` +
|
|
288
|
+
`if(!Array.isArray(d)){console.log('SKIP');process.exit(0)}` +
|
|
289
|
+
`d.filter(x=>x.name.endsWith('.md')&&x.name!=='README.md').forEach(x=>console.log(x.name))"`);
|
|
290
|
+
lines.push(`\`\`\``);
|
|
291
|
+
lines.push(``);
|
|
292
|
+
}
|
|
293
|
+
lines.push(`**1b. From the file list above, pick the BEST match for "${input}".**`);
|
|
294
|
+
lines.push(`Match by name and relevance. If multiple candidates exist, pick the closest one.`);
|
|
123
295
|
lines.push(``);
|
|
296
|
+
lines.push(`**1c. Download the matched agent file (3-stage resolution — this is stage 3):**`);
|
|
297
|
+
lines.push(`\`\`\`bash`);
|
|
298
|
+
lines.push(`# Replace CATEGORY and AGENT_FILE with actual values from 1a/1b`);
|
|
299
|
+
lines.push(`CATEGORY="${targetCategories[0]}"`);
|
|
300
|
+
lines.push(`AGENT_FILE="matched-agent.md"`);
|
|
301
|
+
lines.push(`mkdir -p ".claude/agents"`);
|
|
302
|
+
lines.push(`curl -sf "${VOLTAGENT_SUBAGENTS_RAW}/\${CATEGORY}/\${AGENT_FILE}" \\`);
|
|
303
|
+
lines.push(` -o ".claude/agents/\${AGENT_FILE}"`);
|
|
124
304
|
lines.push(`\`\`\``);
|
|
125
|
-
lines.push(
|
|
305
|
+
lines.push(``);
|
|
306
|
+
lines.push(`**1d. Verify the file has real content (Rule 7 — must not be empty):**`);
|
|
307
|
+
lines.push(`\`\`\`bash`);
|
|
308
|
+
lines.push(`# File must have frontmatter (---) and body content`);
|
|
309
|
+
lines.push(`head -3 ".claude/agents/\${AGENT_FILE}"`);
|
|
310
|
+
lines.push(`wc -l ".claude/agents/\${AGENT_FILE}"`);
|
|
126
311
|
lines.push(`\`\`\``);
|
|
127
|
-
lines.push(`
|
|
312
|
+
lines.push(`If the file is empty or just frontmatter with no body: delete it, log the failure, continue to STEP 2.`);
|
|
313
|
+
lines.push(`If the file has real content: agent is installed. Skip to "Install result format" below.`);
|
|
314
|
+
lines.push(``);
|
|
315
|
+
lines.push(`**README-driven fallback:** If a category listing returns a README.md instead of agent files,`);
|
|
316
|
+
lines.push(`parse the README for entries with links. Entries may point to external repos — follow them`);
|
|
317
|
+
lines.push(`using the universal URL resolution rules (extract {owner}/{repo} dynamically from the link).`);
|
|
318
|
+
lines.push(`Navigate the foreign repo to locate the agent .md file and download it.`);
|
|
319
|
+
lines.push(``);
|
|
320
|
+
// ── STEP 2: jeremylongshore community skills (fallback for agents) ─
|
|
321
|
+
lines.push(`---`);
|
|
322
|
+
lines.push(``);
|
|
323
|
+
lines.push(`### STEP 2 — Community skills catalog (fallback — 416 plugins)`);
|
|
324
|
+
lines.push(``);
|
|
325
|
+
lines.push(`Only reach here if STEP 1 found no match.`);
|
|
326
|
+
lines.push(`Search for agent-like skills in the community catalog.`);
|
|
327
|
+
lines.push(`If curl fails, skip to STEP 3.`);
|
|
328
|
+
lines.push(``);
|
|
329
|
+
buildCommunitySkillsFetchBlock(lines, categoryFilter);
|
|
330
|
+
// ── STEP 3: ComposioHQ (fallback for SaaS/integration agents) ─────
|
|
331
|
+
lines.push(`---`);
|
|
332
|
+
lines.push(``);
|
|
333
|
+
lines.push(`### STEP 3 — ComposioHQ service integrations (1000+ skills — fallback)`);
|
|
334
|
+
lines.push(``);
|
|
335
|
+
lines.push(`Only reach here if STEP 1 and 2 found no match.`);
|
|
336
|
+
lines.push(`Strong for API and SaaS automation. Skills live in per-directory SKILL.md files.`);
|
|
337
|
+
lines.push(`If curl fails, skip to STEP 4.`);
|
|
338
|
+
lines.push(``);
|
|
339
|
+
buildComposioFetchBlock(lines, input);
|
|
340
|
+
// ── STEP 4: Create custom agent ───────────────────────────────────
|
|
341
|
+
lines.push(`---`);
|
|
342
|
+
lines.push(``);
|
|
343
|
+
lines.push(`### STEP 4 — All 3 catalogs exhausted. Create a production-quality custom agent.`);
|
|
344
|
+
lines.push(``);
|
|
345
|
+
lines.push(`You MUST have attempted all 3 sources above with real fetch calls before reaching here.`);
|
|
346
|
+
lines.push(`The custom agent must be production-valid on first write (Rule 4). No placeholders.`);
|
|
347
|
+
lines.push(``);
|
|
348
|
+
lines.push(`\`\`\`bash`);
|
|
349
|
+
lines.push(`mkdir -p ".claude/agents"`);
|
|
128
350
|
lines.push(`\`\`\``);
|
|
129
|
-
lines.push(
|
|
351
|
+
lines.push(`Then create \`.claude/agents/${safeName}.md\` with:`);
|
|
352
|
+
lines.push(`\`\`\`yaml`);
|
|
353
|
+
lines.push(`---`);
|
|
354
|
+
lines.push(`name: ${safeName}`);
|
|
355
|
+
lines.push(`description: "${input}"`);
|
|
356
|
+
lines.push(`tools: Read, Write, Edit, Bash, Glob, Grep`);
|
|
357
|
+
lines.push(`model: sonnet`);
|
|
358
|
+
lines.push(`---`);
|
|
359
|
+
lines.push(``);
|
|
360
|
+
lines.push(`[Complete agent instructions — task routing, responsibilities, integration points]`);
|
|
130
361
|
lines.push(`\`\`\``);
|
|
131
|
-
lines.push(`
|
|
362
|
+
lines.push(`The body must contain real, actionable agent instructions — not a template stub.`);
|
|
363
|
+
lines.push(``);
|
|
364
|
+
}
|
|
365
|
+
// ── Skill pipeline (community → VoltAgent skills → ComposioHQ) ──────
|
|
366
|
+
function buildSkillPipeline(lines, input, categoryFilter, saasMatches) {
|
|
367
|
+
const safeName = input.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
|
|
368
|
+
// ── STEP 1: Official Anthropic plugins ────────────────────────────
|
|
369
|
+
lines.push(`---`);
|
|
370
|
+
lines.push(``);
|
|
371
|
+
lines.push(`### STEP 1 — Official Anthropic plugins (always work, no schema errors)`);
|
|
372
|
+
lines.push(``);
|
|
373
|
+
lines.push(`Check if any of these 13 official plugins match the request:`);
|
|
374
|
+
lines.push(`agent-sdk-dev, claude-opus-4-5-migration, code-review, commit-commands,`);
|
|
132
375
|
lines.push(`explanatory-output-style, feature-dev, frontend-design, hookify, learning-output-style,`);
|
|
133
376
|
lines.push(`plugin-dev, pr-review-toolkit, ralph-wiggum, security-guidance`);
|
|
134
377
|
lines.push(``);
|
|
378
|
+
lines.push(`If a name above matches "${input}": install with \`/plugin install <name>@claude-code-plugins\``);
|
|
379
|
+
lines.push(`If no match, continue to STEP 2.`);
|
|
380
|
+
lines.push(``);
|
|
381
|
+
// ── STEP 2: jeremylongshore community skills ──────────────────────
|
|
135
382
|
lines.push(`---`);
|
|
136
383
|
lines.push(``);
|
|
137
|
-
lines.push(`### STEP 2 —
|
|
384
|
+
lines.push(`### STEP 2 — Community skills catalog (jeremylongshore — 416 plugins)`);
|
|
138
385
|
lines.push(``);
|
|
139
386
|
lines.push(`NOTE: /plugin marketplace add FAILS for this repo (one entry has broken schema).`);
|
|
140
|
-
lines.push(`Use the DIRECT FETCH approach below
|
|
141
|
-
lines.push(`If the curl command fails or returns an error, skip to STEP 3 immediately — do NOT stop.`);
|
|
387
|
+
lines.push(`Use the DIRECT FETCH approach below. If curl fails, skip to STEP 3.`);
|
|
142
388
|
lines.push(``);
|
|
143
|
-
lines
|
|
144
|
-
|
|
145
|
-
lines.push(
|
|
146
|
-
lines.push(
|
|
147
|
-
lines.push(
|
|
389
|
+
buildCommunitySkillsFetchBlock(lines, categoryFilter);
|
|
390
|
+
// ── STEP 3: VoltAgent curated skills ──────────────────────────────
|
|
391
|
+
lines.push(`---`);
|
|
392
|
+
lines.push(``);
|
|
393
|
+
lines.push(`### STEP 3 — VoltAgent curated agent skills (production-proven)`);
|
|
148
394
|
lines.push(``);
|
|
149
|
-
lines.push(
|
|
395
|
+
lines.push(`Only reach here if STEP 2 found no match.`);
|
|
396
|
+
lines.push(`Curated real-world skills from engineering teams. If curl fails, skip to STEP 4.`);
|
|
150
397
|
lines.push(``);
|
|
151
|
-
lines.push(`**2c. List the skills inside that plugin:**`);
|
|
152
398
|
lines.push(`\`\`\`bash`);
|
|
153
|
-
lines.push(
|
|
154
|
-
lines.push(`
|
|
155
|
-
|
|
156
|
-
|
|
399
|
+
lines.push(`curl -sf \${GITHUB_TOKEN:+-H "Authorization: token \$GITHUB_TOKEN"} "${VOLTAGENT_SKILLS_API}" \\`);
|
|
400
|
+
lines.push(` | node -e "const d=JSON.parse(require('fs').readFileSync(0,'utf8'));` +
|
|
401
|
+
`if(!Array.isArray(d)){console.log('SKIP');process.exit(0)}` +
|
|
402
|
+
`d.filter(x=>x.type==='dir'&&!x.name.startsWith('.')).forEach(x=>console.log(x.name))"`);
|
|
157
403
|
lines.push(`\`\`\``);
|
|
158
|
-
lines.push(
|
|
159
|
-
lines.push(`**2d. For each skill listed, download and install it:**`);
|
|
404
|
+
lines.push(`If any directory name matches "${input}", fetch its SKILL.md:`);
|
|
160
405
|
lines.push(`\`\`\`bash`);
|
|
161
|
-
lines.push(
|
|
162
|
-
lines.push(`
|
|
163
|
-
lines.push(`
|
|
164
|
-
lines.push(`
|
|
165
|
-
lines.push(`curl -s "https://raw.githubusercontent.com/${MARKETPLACE_REPO}/main/\${PLUGIN_SOURCE_PATH}/skills/\${SKILL_NAME}/SKILL.md" \\`);
|
|
166
|
-
lines.push(` -o ".claude/skills/\${SKILL_NAME}/SKILL.md"`);
|
|
167
|
-
lines.push(`echo "Installed: .claude/skills/\${SKILL_NAME}/SKILL.md"`);
|
|
406
|
+
lines.push(`SKILL_DIR="matched-skill"`);
|
|
407
|
+
lines.push(`mkdir -p ".claude/skills/\${SKILL_DIR}"`);
|
|
408
|
+
lines.push(`curl -sf "https://raw.githubusercontent.com/${VOLTAGENT_SKILLS_REPO}/main/\${SKILL_DIR}/SKILL.md" \\`);
|
|
409
|
+
lines.push(` -o ".claude/skills/\${SKILL_DIR}/SKILL.md"`);
|
|
168
410
|
lines.push(`\`\`\``);
|
|
411
|
+
lines.push(`Verify content is real (not empty). If empty, delete and continue.`);
|
|
169
412
|
lines.push(``);
|
|
170
|
-
lines.push(`**
|
|
171
|
-
lines.push(
|
|
172
|
-
lines.push(
|
|
173
|
-
lines.push(`
|
|
174
|
-
lines.push(`Invoke-WebRequest $url -OutFile ".claude/skills/$SKILL_NAME/SKILL.md"`);
|
|
175
|
-
lines.push(`\`\`\``);
|
|
413
|
+
lines.push(`**README-driven fallback:** If the API returns a single file (README.md) instead of a directory listing,`);
|
|
414
|
+
lines.push(`parse its markdown sections for entries matching "${input}". Entries may link to external repos owned by`);
|
|
415
|
+
lines.push(`different authors — follow those links using the universal URL resolution rules above (extract {owner}/{repo}`);
|
|
416
|
+
lines.push(`dynamically, never hardcode). Navigate the foreign repo to find the installable .md file and download it.`);
|
|
176
417
|
lines.push(``);
|
|
418
|
+
// ── STEP 4: ComposioHQ service integrations ───────────────────────
|
|
177
419
|
lines.push(`---`);
|
|
178
420
|
lines.push(``);
|
|
179
|
-
lines.push(`### STEP
|
|
421
|
+
lines.push(`### STEP 4 — ComposioHQ service integrations (1000+ skills)`);
|
|
180
422
|
lines.push(``);
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
lines.push(`Note: ${source.note}`);
|
|
188
|
-
}
|
|
189
|
-
lines.push(``);
|
|
190
|
-
}
|
|
423
|
+
lines.push(`Only reach here if STEPs 2+3 found no match.`);
|
|
424
|
+
lines.push(`Strong for API/SaaS automation: Gmail, Slack, GitHub, Notion, Stripe, Shopify, etc.`);
|
|
425
|
+
lines.push(`If curl fails, skip to STEP 5.`);
|
|
426
|
+
lines.push(``);
|
|
427
|
+
buildComposioFetchBlock(lines, input);
|
|
428
|
+
// ── STEP 5: Create custom skill ───────────────────────────────────
|
|
191
429
|
lines.push(`---`);
|
|
192
430
|
lines.push(``);
|
|
193
|
-
lines.push(`### STEP
|
|
431
|
+
lines.push(`### STEP 5 — All 4 catalogs exhausted. Create a production-quality custom skill.`);
|
|
432
|
+
lines.push(``);
|
|
433
|
+
lines.push(`You MUST have attempted all 4 sources above with real fetch calls before reaching here.`);
|
|
434
|
+
lines.push(`The custom skill must be production-valid on first write (Rule 4). No placeholders.`);
|
|
194
435
|
lines.push(``);
|
|
195
436
|
lines.push(`\`\`\`bash`);
|
|
196
|
-
lines.push(`mkdir -p ".claude/skills/${
|
|
437
|
+
lines.push(`mkdir -p ".claude/skills/${safeName}"`);
|
|
197
438
|
lines.push(`\`\`\``);
|
|
198
|
-
lines.push(`Then create SKILL.md with:`);
|
|
439
|
+
lines.push(`Then create \`.claude/skills/${safeName}/SKILL.md\` with:`);
|
|
199
440
|
lines.push(`\`\`\`yaml`);
|
|
200
441
|
lines.push(`---`);
|
|
201
|
-
lines.push(`name: ${
|
|
202
|
-
lines.push(`description: ${input}`);
|
|
442
|
+
lines.push(`name: ${safeName}`);
|
|
443
|
+
lines.push(`description: "${input}"`);
|
|
203
444
|
lines.push(`---`);
|
|
204
445
|
lines.push(``);
|
|
205
|
-
lines.push(`[
|
|
446
|
+
lines.push(`[Complete skill instructions — not a stub. Must work on first use.]`);
|
|
206
447
|
lines.push(`\`\`\``);
|
|
207
448
|
lines.push(``);
|
|
208
|
-
|
|
449
|
+
}
|
|
450
|
+
// ── Universal catalog resolution rules (applies to all sources) ─────────
|
|
451
|
+
function buildUniversalRulesBlock(lines) {
|
|
452
|
+
lines.push(`### Universal catalog resolution rules`);
|
|
209
453
|
lines.push(``);
|
|
210
|
-
lines.push(
|
|
211
|
-
lines.push(
|
|
212
|
-
lines.push(
|
|
213
|
-
lines.push(
|
|
454
|
+
lines.push(`These rules apply to EVERY source below. Read them first.`);
|
|
455
|
+
lines.push(``);
|
|
456
|
+
lines.push(`**1. Catalog shape detection — detect before processing:**`);
|
|
457
|
+
lines.push(`When you fetch a catalog endpoint, the response determines your strategy:`);
|
|
458
|
+
lines.push(`- **JSON catalog**: valid JSON with a structured list (array of objects with name/source/description). Filter by relevance, navigate source paths, download.`);
|
|
459
|
+
lines.push(`- **README-driven catalog**: markdown organized into sections with headings. Each entry has a name, description, and a link — but that link may point to a **completely different external repository**. Parse sections, collect entries, follow external links.`);
|
|
460
|
+
lines.push(`- **Directory listing**: GitHub API array with "type"/"name"/"download_url" fields. List entries, match by name, download via raw URL.`);
|
|
461
|
+
lines.push(`Detect the shape first. Never assume one format.`);
|
|
462
|
+
lines.push(``);
|
|
463
|
+
lines.push(`**2. Universal GitHub URL resolution — works for ANY repo, ANY author:**`);
|
|
464
|
+
lines.push(`Convert any GitHub URL to a downloadable form by extracting {owner}, {repo}, {branch}, {path} dynamically:`);
|
|
465
|
+
lines.push(`- \`github.com/{owner}/{repo}/tree/{branch}/{path}\` → \`https://raw.githubusercontent.com/{owner}/{repo}/{branch}/{path}\``);
|
|
466
|
+
lines.push(`- \`github.com/{owner}/{repo}/blob/{branch}/{path}\` → \`https://raw.githubusercontent.com/{owner}/{repo}/{branch}/{path}\``);
|
|
467
|
+
lines.push(`- Directory URL → list via \`https://api.github.com/repos/{owner}/{repo}/contents/{path}\`, then download individual files`);
|
|
468
|
+
lines.push(`**Never hardcode a specific owner or repo in the resolution logic.** Always derive them dynamically from whatever link the catalog provides.`);
|
|
469
|
+
lines.push(``);
|
|
470
|
+
lines.push(`**3. README-driven external link navigation:**`);
|
|
471
|
+
lines.push(`When a catalog entry links to an external repository (different {owner}/{repo}):`);
|
|
472
|
+
lines.push(`1. Extract {owner}/{repo} from the link URL`);
|
|
473
|
+
lines.push(`2. Resolve to the raw file or directory listing in that foreign repo`);
|
|
474
|
+
lines.push(`3. If it points to a directory, list contents via API to find the installable .md file`);
|
|
475
|
+
lines.push(`4. Download from the foreign repo using universal resolution above`);
|
|
476
|
+
lines.push(`The catalog is just a curated map — the real content lives in the external repo.`);
|
|
477
|
+
lines.push(``);
|
|
478
|
+
lines.push(`**4. Candidate scoring — compare before choosing:**`);
|
|
479
|
+
lines.push(`When multiple candidates match, score each on three axes:`);
|
|
480
|
+
lines.push(`- **Relevance** (highest weight): does the description directly address the request?`);
|
|
481
|
+
lines.push(`- **Scope**: is it surgical and focused, or a kitchen-sink tool? Prefer focused — lower cost, easier to reason about.`);
|
|
482
|
+
lines.push(`- **Uniqueness**: does it duplicate something already installed in .claude/skills/ or .claude/agents/? Deprioritize duplicates.`);
|
|
483
|
+
lines.push(`Install only the highest-scoring candidate. One high-quality tool per task.`);
|
|
484
|
+
lines.push(``);
|
|
485
|
+
lines.push(`**5. Content verification — never keep stubs:**`);
|
|
486
|
+
lines.push(`After downloading any file, verify ALL of these before accepting:`);
|
|
487
|
+
lines.push(`- Not empty (0 bytes)`);
|
|
488
|
+
lines.push(`- Not only YAML frontmatter with no body (just \`---\\nname: x\\n---\` and nothing after)`);
|
|
489
|
+
lines.push(`- Contains at least 50 characters of instruction content after frontmatter`);
|
|
490
|
+
lines.push(`If verification fails: delete the file, log which source/candidate failed, continue to next candidate or next STEP.`);
|
|
491
|
+
lines.push(``);
|
|
492
|
+
}
|
|
493
|
+
// ── Shared fetch blocks ─────────────────────────────────────────────────
|
|
494
|
+
function buildCommunitySkillsFetchBlock(lines, categoryFilter) {
|
|
495
|
+
lines.push(`**Stage 1 — Fetch catalog and find matching plugin:**`);
|
|
496
|
+
lines.push(`\`\`\`bash`);
|
|
497
|
+
lines.push(`curl -sf "${MARKETPLACE_CATALOG_URL}" \\`);
|
|
498
|
+
lines.push(` | node -e "const d=JSON.parse(require('fs').readFileSync(0,'utf8'));` +
|
|
499
|
+
`const q='${categoryFilter}';` +
|
|
500
|
+
`const r=d.plugins.filter(p=>(q===''||p.category.includes(q))&&p.name&&p.source).slice(0,10)` +
|
|
501
|
+
`.map(p=>({name:p.name,source:p.source,desc:p.description}));` +
|
|
502
|
+
`console.log(JSON.stringify(r,null,2));"`);
|
|
503
|
+
lines.push(`\`\`\``);
|
|
504
|
+
lines.push(`If this returns an error or empty array, skip to the next STEP.`);
|
|
505
|
+
lines.push(``);
|
|
506
|
+
lines.push(`**Stage 2 — Score candidates and pick the best match (see rule 4: Relevance > Scope > Uniqueness):**`);
|
|
507
|
+
lines.push(`\`\`\`bash`);
|
|
508
|
+
lines.push(`# Replace PLUGIN_SOURCE_PATH with the "source" value from Stage 1`);
|
|
509
|
+
lines.push(`PLUGIN_SOURCE_PATH="plugins/category/plugin-name"`);
|
|
510
|
+
lines.push(`curl -sf \${GITHUB_TOKEN:+-H "Authorization: token \$GITHUB_TOKEN"} "https://api.github.com/repos/${MARKETPLACE_REPO}/contents/\${PLUGIN_SOURCE_PATH}/skills" \\`);
|
|
511
|
+
lines.push(` | node -e "const a=JSON.parse(require('fs').readFileSync(0,'utf8'));` +
|
|
512
|
+
`if(!Array.isArray(a)){console.log('NO_SKILLS_DIR');process.exit(0)}` +
|
|
513
|
+
`a.forEach(x=>console.log(x.name))"`);
|
|
514
|
+
lines.push(`\`\`\``);
|
|
515
|
+
lines.push(`If this fails or shows NO_SKILLS_DIR, the plugin has no installable skills — skip.`);
|
|
516
|
+
lines.push(``);
|
|
517
|
+
lines.push(`**Stage 3 — Download each skill file and install:**`);
|
|
518
|
+
lines.push(`\`\`\`bash`);
|
|
519
|
+
lines.push(`# Replace PLUGIN_SOURCE_PATH and SKILL_NAME with actual values`);
|
|
520
|
+
lines.push(`PLUGIN_SOURCE_PATH="plugins/category/plugin-name"`);
|
|
521
|
+
lines.push(`SKILL_NAME="skill-directory-name"`);
|
|
522
|
+
lines.push(`mkdir -p ".claude/skills/\${SKILL_NAME}"`);
|
|
523
|
+
lines.push(`curl -sf "https://raw.githubusercontent.com/${MARKETPLACE_REPO}/main/\${PLUGIN_SOURCE_PATH}/skills/\${SKILL_NAME}/SKILL.md" \\`);
|
|
524
|
+
lines.push(` -o ".claude/skills/\${SKILL_NAME}/SKILL.md"`);
|
|
525
|
+
lines.push(`\`\`\``);
|
|
526
|
+
lines.push(`Verify the file has real content (not empty, not just frontmatter). If empty: delete and move on.`);
|
|
527
|
+
lines.push(``);
|
|
528
|
+
}
|
|
529
|
+
function buildComposioFetchBlock(lines, input) {
|
|
530
|
+
lines.push(`**Stage 1 — List available skill directories:**`);
|
|
531
|
+
lines.push(`\`\`\`bash`);
|
|
532
|
+
lines.push(`curl -sf \${GITHUB_TOKEN:+-H "Authorization: token \$GITHUB_TOKEN"} "${COMPOSIO_API}" \\`);
|
|
533
|
+
lines.push(` | node -e "const d=JSON.parse(require('fs').readFileSync(0,'utf8'));` +
|
|
534
|
+
`if(!Array.isArray(d)){console.log('SKIP');process.exit(0)}` +
|
|
535
|
+
`d.filter(x=>x.type==='dir'&&!x.name.startsWith('.')).forEach(x=>console.log(x.name))"`);
|
|
536
|
+
lines.push(`\`\`\``);
|
|
537
|
+
lines.push(``);
|
|
538
|
+
lines.push(`**Stage 2 — Pick the directory that best matches "${input}":**`);
|
|
539
|
+
lines.push(`Match by name similarity. If no directory name is relevant, skip.`);
|
|
540
|
+
lines.push(``);
|
|
541
|
+
lines.push(`**Stage 3 — Download the SKILL.md from the matched directory:**`);
|
|
542
|
+
lines.push(`\`\`\`bash`);
|
|
543
|
+
lines.push(`SKILL_DIR="matched-directory"`);
|
|
544
|
+
lines.push(`mkdir -p ".claude/skills/\${SKILL_DIR}"`);
|
|
545
|
+
lines.push(`curl -sf "${COMPOSIO_RAW}/\${SKILL_DIR}/SKILL.md" \\`);
|
|
546
|
+
lines.push(` -o ".claude/skills/\${SKILL_DIR}/SKILL.md"`);
|
|
547
|
+
lines.push(`\`\`\``);
|
|
548
|
+
lines.push(`Verify the file has real content (rule 5 above). If empty: delete and move on.`);
|
|
549
|
+
lines.push(``);
|
|
550
|
+
lines.push(`**README-driven fallback:** If the directory listing above fails or returns unexpected content,`);
|
|
551
|
+
lines.push(`fetch the repo's README.md and parse it for sections matching "${input}":`);
|
|
552
|
+
lines.push(`\`\`\`bash`);
|
|
553
|
+
lines.push(`# Derive owner/repo dynamically from the catalog source — never hardcode`);
|
|
554
|
+
lines.push(`curl -sf "https://raw.githubusercontent.com/${COMPOSIO_REPO}/master/README.md" | head -300`);
|
|
555
|
+
lines.push(`\`\`\``);
|
|
556
|
+
lines.push(`Scan sections for entries with external links. Follow those links using universal URL resolution`);
|
|
557
|
+
lines.push(`(rule 2+3 above) to download from the linked repo, regardless of its owner.`);
|
|
214
558
|
lines.push(``);
|
|
215
|
-
return lines.join("\n");
|
|
216
559
|
}
|