claude-setup 1.1.8 → 2.0.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/dist/builder.js +10 -4
- package/dist/commands/add.js +2 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.js +46 -0
- package/dist/marketplace.d.ts +24 -19
- package/dist/marketplace.js +521 -84
- package/package.json +1 -1
- package/templates/add.md +48 -9
package/dist/builder.js
CHANGED
|
@@ -21,10 +21,16 @@ function replaceVars(template, vars) {
|
|
|
21
21
|
}
|
|
22
22
|
function processConditionals(template, flags) {
|
|
23
23
|
let result = template;
|
|
24
|
-
//
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
// Process innermost conditionals first, repeat until stable.
|
|
25
|
+
// This prevents outer {{#if}} from greedily matching inner {{else}}/{{/if}}.
|
|
26
|
+
let prev = "";
|
|
27
|
+
while (prev !== result) {
|
|
28
|
+
prev = result;
|
|
29
|
+
// {{#if VAR}}...{{else}}...{{/if}} first (innermost — no nested {{#if}} in either branch)
|
|
30
|
+
result = result.replace(/\{\{#if\s+(\w+)\}\}\n?((?:(?!\{\{#if\b)[\s\S])*?)\{\{else\}\}\n?((?:(?!\{\{#if\b)[\s\S])*?)\{\{\/if\}\}/g, (_m, key, ifBlock, elseBlock) => flags[key] ? ifBlock : elseBlock);
|
|
31
|
+
// Simple {{#if VAR}}...{{/if}} (no else, no nested if inside)
|
|
32
|
+
result = result.replace(/\{\{#if\s+(\w+)\}\}\n?((?:(?!\{\{#if\b|\{\{else\}\})[\s\S])*?)\{\{\/if\}\}/g, (_m, key, block) => flags[key] ? block : "");
|
|
33
|
+
}
|
|
28
34
|
return result;
|
|
29
35
|
}
|
|
30
36
|
function formatList(items) {
|
package/dist/commands/add.js
CHANGED
|
@@ -6,6 +6,7 @@ import { updateManifest } from "../manifest.js";
|
|
|
6
6
|
import { buildAddCommand } from "../builder.js";
|
|
7
7
|
import { estimateTokens, estimateCost } from "../tokens.js";
|
|
8
8
|
import { c } from "../output.js";
|
|
9
|
+
import { installMarketplaceFetcher } from "./init.js";
|
|
9
10
|
function ensureDir(dir) {
|
|
10
11
|
if (!existsSync(dir))
|
|
11
12
|
mkdirSync(dir, { recursive: true });
|
|
@@ -46,6 +47,7 @@ capabilities that need documentation, MCP servers, skills, and hooks together.
|
|
|
46
47
|
const tokens = estimateTokens(content);
|
|
47
48
|
const cost = estimateCost(tokens);
|
|
48
49
|
ensureDir(".claude/commands");
|
|
50
|
+
installMarketplaceFetcher();
|
|
49
51
|
writeFileSync(".claude/commands/stack-add.md", content, "utf8");
|
|
50
52
|
await updateManifest("add", collected, {
|
|
51
53
|
input: userInput,
|
package/dist/commands/init.d.ts
CHANGED
package/dist/commands/init.js
CHANGED
|
@@ -71,6 +71,50 @@ No further action needed — the output IS the status.
|
|
|
71
71
|
writeFileSync(filepath, content, "utf8");
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
|
+
/** Install the marketplace-fetcher subagent so /stack-add can spawn it */
|
|
75
|
+
export function installMarketplaceFetcher(cwd = process.cwd()) {
|
|
76
|
+
const agentsDir = join(cwd, ".claude", "agents");
|
|
77
|
+
ensureDir(agentsDir);
|
|
78
|
+
const filepath = join(agentsDir, "marketplace-fetcher.md");
|
|
79
|
+
// Always overwrite — this is a system agent, not user-authored
|
|
80
|
+
writeFileSync(filepath, `---
|
|
81
|
+
name: marketplace-fetcher
|
|
82
|
+
description: Fetches skills and agents from all 4 marketplace catalogs. Spawned automatically by stack-add. Runs in isolation, writes to disk, returns only the install confirmation.
|
|
83
|
+
tools: Bash
|
|
84
|
+
model: haiku
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
You are a marketplace fetch agent. Your ONLY job is to search the 4 curated catalogs, download the best matching file, and confirm the install. You run in isolation — your context dies when you finish, keeping the main session clean.
|
|
88
|
+
|
|
89
|
+
## Your task
|
|
90
|
+
|
|
91
|
+
You will receive a single install request (e.g., "Stripe integration", "orchestration agent"). Execute the full pipeline below. Return exactly ONE line when done.
|
|
92
|
+
|
|
93
|
+
## Pipeline
|
|
94
|
+
|
|
95
|
+
The main session has already generated a complete marketplace instruction block. It will be passed to you as your task prompt. Follow every step in that instruction block exactly:
|
|
96
|
+
|
|
97
|
+
1. **Classify** the request (agent vs skill, categories, SaaS matches)
|
|
98
|
+
2. **Search catalogs in order** — stop at the first quality match
|
|
99
|
+
3. **Download** the matched file to \`.claude/agents/\` (agents) or \`.claude/skills/<name>/\` (skills)
|
|
100
|
+
4. **Verify** the file has real content (not empty, not a stub)
|
|
101
|
+
5. **Return** exactly one line:
|
|
102
|
+
- \`INSTALLED .claude/agents/<file> <bytes>b\` or
|
|
103
|
+
- \`INSTALLED .claude/skills/<dir>/SKILL.md <bytes>b\` or
|
|
104
|
+
- \`CREATED .claude/agents/<file> <bytes>b\` (if custom-created after all catalogs exhausted) or
|
|
105
|
+
- \`CREATED .claude/skills/<dir>/SKILL.md <bytes>b\` or
|
|
106
|
+
- \`FAILED no match in any catalog and custom creation not possible\`
|
|
107
|
+
|
|
108
|
+
## Rules
|
|
109
|
+
|
|
110
|
+
- Execute every curl yourself. Never ask for confirmation.
|
|
111
|
+
- Use relative paths only. Never \`cd\` to an absolute path.
|
|
112
|
+
- Pipe all curl output through a node parser — never return raw JSON/README to context.
|
|
113
|
+
- A fetch failure is a routing signal to the next catalog, not a stop condition.
|
|
114
|
+
- If a step produces an ambiguous result, document why it failed in one line, then continue.
|
|
115
|
+
- When creating custom skills/agents (last resort), make them production-valid — no stubs.
|
|
116
|
+
`, "utf8");
|
|
117
|
+
}
|
|
74
118
|
function installTokenHook(cwd = process.cwd()) {
|
|
75
119
|
// Write the hook script
|
|
76
120
|
const hooksDir = join(cwd, ".claude", "hooks");
|
|
@@ -139,6 +183,7 @@ export async function runInit(opts = {}) {
|
|
|
139
183
|
writeFileSync(".claude/commands/stack-init.md", content, "utf8");
|
|
140
184
|
writeFileSync(".claude/commands/stack-sync.md", buildBootstrapSync(), "utf8");
|
|
141
185
|
installBootstrapCommands(".claude/commands");
|
|
186
|
+
installMarketplaceFetcher();
|
|
142
187
|
await updateManifest("init", collected, { estimatedTokens: tokens, estimatedCost: cost });
|
|
143
188
|
installTokenHook();
|
|
144
189
|
// Create initial snapshot — collectFilesForSnapshot scans all .claude/ automatically
|
|
@@ -181,6 +226,7 @@ Claude Code will ask 3 questions, then set up your environment.
|
|
|
181
226
|
writeFileSync(".claude/commands/stack-init.md", orchestrator, "utf8");
|
|
182
227
|
writeFileSync(".claude/commands/stack-sync.md", buildBootstrapSync(), "utf8");
|
|
183
228
|
installBootstrapCommands(".claude/commands");
|
|
229
|
+
installMarketplaceFetcher();
|
|
184
230
|
await updateManifest("init", collected, { estimatedTokens: tokens, estimatedCost: cost });
|
|
185
231
|
installTokenHook();
|
|
186
232
|
// Create initial snapshot — collectFilesForSnapshot scans all .claude/ automatically
|
package/dist/marketplace.d.ts
CHANGED
|
@@ -1,34 +1,39 @@
|
|
|
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
|
+
export declare const VOLTAGENT_SUBAGENTS_REPO = "VoltAgent/awesome-claude-code-subagents";
|
|
11
|
+
export declare const VOLTAGENT_SUBAGENTS_API = "https://api.github.com/repos/VoltAgent/awesome-claude-code-subagents/contents/categories";
|
|
12
|
+
export declare const VOLTAGENT_SUBAGENTS_RAW = "https://raw.githubusercontent.com/VoltAgent/awesome-claude-code-subagents/main/categories";
|
|
13
|
+
export declare const VOLTAGENT_CATEGORIES: readonly ["01-core-development", "02-language-specialists", "03-infrastructure", "04-quality-security", "05-data-ai", "06-developer-experience", "07-specialized-domains", "08-business-product", "09-meta-orchestration", "10-research-analysis"];
|
|
7
14
|
export declare const MARKETPLACE_REPO = "jeremylongshore/claude-code-plugins-plus-skills";
|
|
8
15
|
export declare const MARKETPLACE_CATALOG_URL = "https://raw.githubusercontent.com/jeremylongshore/claude-code-plugins-plus-skills/main/.claude-plugin/marketplace.extended.json";
|
|
9
|
-
|
|
10
|
-
export declare const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
readonly note: "No marketplace add needed — available by default";
|
|
15
|
-
}, {
|
|
16
|
-
readonly name: "awesome-claude-code";
|
|
17
|
-
readonly description: "Community collection of Claude Code skills and workflows";
|
|
18
|
-
readonly catalogUrl: "https://raw.githubusercontent.com/hesreallyhim/awesome-claude-code/main/catalog.json";
|
|
19
|
-
readonly installPrefix: null;
|
|
20
|
-
readonly note: "Browse and manually install skills";
|
|
21
|
-
}];
|
|
16
|
+
export declare const VOLTAGENT_SKILLS_REPO = "VoltAgent/awesome-agent-skills";
|
|
17
|
+
export declare const VOLTAGENT_SKILLS_API = "https://api.github.com/repos/VoltAgent/awesome-agent-skills/contents";
|
|
18
|
+
export declare const COMPOSIO_REPO = "ComposioHQ/awesome-claude-skills";
|
|
19
|
+
export declare const COMPOSIO_API = "https://api.github.com/repos/ComposioHQ/awesome-claude-skills/contents";
|
|
20
|
+
export declare const COMPOSIO_RAW = "https://raw.githubusercontent.com/ComposioHQ/awesome-claude-skills/master";
|
|
22
21
|
/** The 20 skill categories in the marketplace */
|
|
23
22
|
export declare const SKILL_CATEGORIES: readonly ["01-code-quality", "02-testing", "03-security", "04-devops", "05-api-development", "06-database", "07-frontend", "08-backend", "09-mobile", "10-data-science", "11-documentation", "12-project-management", "13-communication", "14-research", "15-content-creation", "16-business", "17-finance", "18-visual-content", "19-legal", "20-productivity"];
|
|
24
23
|
/** SaaS packs available in the marketplace */
|
|
25
24
|
export declare const SAAS_PACKS: readonly ["Supabase", "Vercel", "OpenRouter", "GitHub", "Azure", "MongoDB", "Playwright", "Tavily", "Stripe", "Slack", "Linear", "Notion"];
|
|
26
|
-
/** Keyword-to-category mapping for classifying
|
|
25
|
+
/** Keyword-to-category mapping for classifying skill requests */
|
|
27
26
|
export declare const KEYWORD_CATEGORY_MAP: Record<string, string>;
|
|
28
|
-
|
|
29
|
-
export declare function classifyRequest(input: string): {
|
|
27
|
+
export interface ClassificationResult {
|
|
30
28
|
categories: string[];
|
|
31
29
|
saasMatches: string[];
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
isAgent: boolean;
|
|
31
|
+
agentCategories: string[];
|
|
32
|
+
}
|
|
33
|
+
/** Detect whether the request is about agents/subagents/orchestration */
|
|
34
|
+
export declare function isAgentRequest(input: string): boolean;
|
|
35
|
+
/** Map input to VoltAgent agent category directories */
|
|
36
|
+
export declare function matchAgentCategories(input: string): string[];
|
|
37
|
+
/** Classify a user request into marketplace categories and detect agent requests */
|
|
38
|
+
export declare function classifyRequest(input: string): ClassificationResult;
|
|
34
39
|
export declare function buildMarketplaceInstructions(input: string): string;
|
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,98 @@ export const SAAS_PACKS = [
|
|
|
37
48
|
"Supabase", "Vercel", "OpenRouter", "GitHub", "Azure", "MongoDB",
|
|
38
49
|
"Playwright", "Tavily", "Stripe", "Slack", "Linear", "Notion",
|
|
39
50
|
];
|
|
40
|
-
|
|
51
|
+
// ── Adjacent category map (for fallback when primary SKIP) ─────────────
|
|
52
|
+
const ADJACENT_CATEGORIES = {
|
|
53
|
+
"01-core-development": ["02-language-specialists", "06-developer-experience"],
|
|
54
|
+
"02-language-specialists": ["01-core-development", "06-developer-experience"],
|
|
55
|
+
"03-infrastructure": ["04-quality-security", "09-meta-orchestration"],
|
|
56
|
+
"04-quality-security": ["03-infrastructure", "01-core-development"],
|
|
57
|
+
"05-data-ai": ["10-research-analysis", "07-specialized-domains"],
|
|
58
|
+
"06-developer-experience": ["01-core-development", "02-language-specialists"],
|
|
59
|
+
"07-specialized-domains": ["05-data-ai", "08-business-product"],
|
|
60
|
+
"08-business-product": ["07-specialized-domains", "09-meta-orchestration"],
|
|
61
|
+
"09-meta-orchestration": ["03-infrastructure", "04-quality-security"],
|
|
62
|
+
"10-research-analysis": ["05-data-ai", "07-specialized-domains"],
|
|
63
|
+
};
|
|
64
|
+
/** Expand target categories with their adjacent neighbors, deduplicating */
|
|
65
|
+
function expandWithAdjacent(targets) {
|
|
66
|
+
const seen = new Set(targets);
|
|
67
|
+
const adjacent = [];
|
|
68
|
+
for (const cat of targets) {
|
|
69
|
+
for (const adj of (ADJACENT_CATEGORIES[cat] ?? [])) {
|
|
70
|
+
if (!seen.has(adj)) {
|
|
71
|
+
seen.add(adj);
|
|
72
|
+
adjacent.push(adj);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return adjacent;
|
|
77
|
+
}
|
|
78
|
+
// ── Agent detection keywords ────────────────────────────────────────────
|
|
79
|
+
const AGENT_KEYWORDS = [
|
|
80
|
+
"agent", "subagent", "sub-agent", "orchestrat", "multi-agent",
|
|
81
|
+
"coordinator", "dispatcher", "workflow agent", "task routing",
|
|
82
|
+
"agent system", "agent framework", "meta-agent",
|
|
83
|
+
];
|
|
84
|
+
/** Map agent keywords to VoltAgent category directories */
|
|
85
|
+
const AGENT_CATEGORY_MAP = {
|
|
86
|
+
// Meta / orchestration
|
|
87
|
+
"orchestrat": "09-meta-orchestration",
|
|
88
|
+
"coordinator": "09-meta-orchestration",
|
|
89
|
+
"dispatcher": "09-meta-orchestration",
|
|
90
|
+
"multi-agent": "09-meta-orchestration",
|
|
91
|
+
"meta-agent": "09-meta-orchestration",
|
|
92
|
+
"task routing": "09-meta-orchestration",
|
|
93
|
+
"workflow agent": "09-meta-orchestration",
|
|
94
|
+
"workflow orchestrat": "09-meta-orchestration",
|
|
95
|
+
// Core development
|
|
96
|
+
"code review agent": "01-core-development",
|
|
97
|
+
"api design": "01-core-development",
|
|
98
|
+
"refactor": "01-core-development",
|
|
99
|
+
// Language specialists
|
|
100
|
+
"typescript agent": "02-language-specialists",
|
|
101
|
+
"python agent": "02-language-specialists",
|
|
102
|
+
"rust agent": "02-language-specialists",
|
|
103
|
+
"go agent": "02-language-specialists",
|
|
104
|
+
"java agent": "02-language-specialists",
|
|
105
|
+
"powershell": "02-language-specialists",
|
|
106
|
+
// Infrastructure
|
|
107
|
+
"infra": "03-infrastructure",
|
|
108
|
+
"devops agent": "03-infrastructure",
|
|
109
|
+
"docker agent": "03-infrastructure",
|
|
110
|
+
"kubernetes agent": "03-infrastructure",
|
|
111
|
+
"cloud agent": "03-infrastructure",
|
|
112
|
+
"azure agent": "03-infrastructure",
|
|
113
|
+
"aws agent": "03-infrastructure",
|
|
114
|
+
// Quality & security
|
|
115
|
+
"security agent": "04-quality-security",
|
|
116
|
+
"test agent": "04-quality-security",
|
|
117
|
+
"qa agent": "04-quality-security",
|
|
118
|
+
"audit agent": "04-quality-security",
|
|
119
|
+
// Data & AI
|
|
120
|
+
"data agent": "05-data-ai",
|
|
121
|
+
"data pipeline": "05-data-ai",
|
|
122
|
+
"data engineer": "05-data-ai",
|
|
123
|
+
"ml agent": "05-data-ai",
|
|
124
|
+
"ml pipeline": "05-data-ai",
|
|
125
|
+
"ai agent": "05-data-ai",
|
|
126
|
+
// Developer experience
|
|
127
|
+
"dx agent": "06-developer-experience",
|
|
128
|
+
"productivity agent": "06-developer-experience",
|
|
129
|
+
"documentation agent": "06-developer-experience",
|
|
130
|
+
// Specialized
|
|
131
|
+
"domain agent": "07-specialized-domains",
|
|
132
|
+
"iot agent": "07-specialized-domains",
|
|
133
|
+
"embedded agent": "07-specialized-domains",
|
|
134
|
+
// Business
|
|
135
|
+
"business agent": "08-business-product",
|
|
136
|
+
"product agent": "08-business-product",
|
|
137
|
+
"pm agent": "08-business-product",
|
|
138
|
+
// Research
|
|
139
|
+
"research agent": "10-research-analysis",
|
|
140
|
+
"analysis agent": "10-research-analysis",
|
|
141
|
+
};
|
|
142
|
+
/** Keyword-to-category mapping for classifying skill requests */
|
|
41
143
|
export const KEYWORD_CATEGORY_MAP = {
|
|
42
144
|
// Code quality
|
|
43
145
|
"lint": "01-code-quality", "format": "01-code-quality", "prettier": "01-code-quality",
|
|
@@ -79,13 +181,42 @@ export const KEYWORD_CATEGORY_MAP = {
|
|
|
79
181
|
// Project management
|
|
80
182
|
"project management": "12-project-management", "agile": "12-project-management",
|
|
81
183
|
"sprint": "12-project-management", "kanban": "12-project-management",
|
|
184
|
+
// Communication
|
|
185
|
+
"slack": "13-communication", "email": "13-communication", "notification": "13-communication",
|
|
186
|
+
"discord": "13-communication", "telegram": "13-communication",
|
|
187
|
+
// Content
|
|
188
|
+
"content": "15-content-creation", "blog": "15-content-creation",
|
|
189
|
+
"seo": "15-content-creation", "copywriting": "15-content-creation",
|
|
190
|
+
// Productivity
|
|
191
|
+
"productivity": "20-productivity", "automation": "20-productivity",
|
|
192
|
+
"workflow": "20-productivity",
|
|
82
193
|
};
|
|
83
|
-
/**
|
|
194
|
+
/** Detect whether the request is about agents/subagents/orchestration */
|
|
195
|
+
export function isAgentRequest(input) {
|
|
196
|
+
const lower = input.toLowerCase();
|
|
197
|
+
return AGENT_KEYWORDS.some(kw => lower.includes(kw));
|
|
198
|
+
}
|
|
199
|
+
/** Map input to VoltAgent agent category directories */
|
|
200
|
+
export function matchAgentCategories(input) {
|
|
201
|
+
const lower = input.toLowerCase();
|
|
202
|
+
const matched = new Set();
|
|
203
|
+
for (const [keyword, category] of Object.entries(AGENT_CATEGORY_MAP)) {
|
|
204
|
+
if (lower.includes(keyword)) {
|
|
205
|
+
matched.add(category);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
// Default to meta-orchestration for generic agent requests
|
|
209
|
+
if (matched.size === 0 && isAgentRequest(input)) {
|
|
210
|
+
matched.add("09-meta-orchestration");
|
|
211
|
+
}
|
|
212
|
+
return [...matched];
|
|
213
|
+
}
|
|
214
|
+
/** Classify a user request into marketplace categories and detect agent requests */
|
|
84
215
|
export function classifyRequest(input) {
|
|
85
216
|
const lower = input.toLowerCase();
|
|
86
217
|
const categories = new Set();
|
|
87
218
|
const saasMatches = [];
|
|
88
|
-
// Check keyword matches
|
|
219
|
+
// Check keyword matches for skills
|
|
89
220
|
for (const [keyword, category] of Object.entries(KEYWORD_CATEGORY_MAP)) {
|
|
90
221
|
if (lower.includes(keyword)) {
|
|
91
222
|
categories.add(category);
|
|
@@ -97,121 +228,427 @@ export function classifyRequest(input) {
|
|
|
97
228
|
saasMatches.push(saas);
|
|
98
229
|
}
|
|
99
230
|
}
|
|
100
|
-
return {
|
|
231
|
+
return {
|
|
232
|
+
categories: [...categories],
|
|
233
|
+
saasMatches,
|
|
234
|
+
isAgent: isAgentRequest(input),
|
|
235
|
+
agentCategories: matchAgentCategories(input),
|
|
236
|
+
};
|
|
101
237
|
}
|
|
102
|
-
|
|
238
|
+
// ── Marketplace instruction builder ─────────────────────────────────────
|
|
239
|
+
// Implements Rule 6 (4-catalog exhaustion) and Rule 7 (3-stage fetch).
|
|
240
|
+
// Agent requests route to VoltAgent subagents first.
|
|
241
|
+
// Skill requests route to jeremylongshore → VoltAgent skills → ComposioHQ.
|
|
103
242
|
export function buildMarketplaceInstructions(input) {
|
|
104
|
-
const
|
|
243
|
+
const classification = classifyRequest(input);
|
|
244
|
+
const { categories, saasMatches, isAgent: isAgentReq, agentCategories } = classification;
|
|
105
245
|
const categoryFilter = categories[0] ?? "";
|
|
106
246
|
const lines = [];
|
|
107
247
|
lines.push(`## Marketplace — fully automated install (DO NOT ASK — JUST DO IT)`);
|
|
108
248
|
lines.push(``);
|
|
109
|
-
lines.push(`
|
|
110
|
-
lines.push(`
|
|
111
|
-
lines.push(`**DO NOT ask the user clarifying questions.
|
|
249
|
+
lines.push(`4 catalogs available. You MUST search them ALL in order before giving up.`);
|
|
250
|
+
lines.push(`A fetch failure is NOT a stop condition — it is a routing signal to the next source.`);
|
|
251
|
+
lines.push(`**DO NOT ask the user clarifying questions. Execute every command yourself.**`);
|
|
252
|
+
lines.push(`**Rate-limit safe:** all api.github.com calls include GITHUB_TOKEN when set (5000/hr vs 60/hr).`);
|
|
253
|
+
lines.push(`Downloads use raw.githubusercontent.com (no limit). For heavy usage (10+ installs/hr), set GITHUB_TOKEN.`);
|
|
112
254
|
lines.push(``);
|
|
113
|
-
if (categories.length > 0 || saasMatches.length > 0) {
|
|
114
|
-
lines.push(`###
|
|
255
|
+
if (isAgentReq || categories.length > 0 || saasMatches.length > 0) {
|
|
256
|
+
lines.push(`### Classification for "${input}":`);
|
|
257
|
+
if (isAgentReq)
|
|
258
|
+
lines.push(`- **Type: AGENT** — routing to agent catalogs first`);
|
|
259
|
+
for (const cat of agentCategories)
|
|
260
|
+
lines.push(`- agent-category: ${cat}`);
|
|
115
261
|
for (const cat of categories)
|
|
116
|
-
lines.push(`- category: ${cat}`);
|
|
262
|
+
lines.push(`- skill-category: ${cat}`);
|
|
117
263
|
for (const saas of saasMatches)
|
|
118
264
|
lines.push(`- SaaS: ${saas}`);
|
|
119
265
|
lines.push(``);
|
|
120
266
|
}
|
|
267
|
+
// ── Universal resolution rules (applies to every catalog) ──────
|
|
268
|
+
buildUniversalRulesBlock(lines);
|
|
269
|
+
// ── Route based on request type ───────────────────────────────────
|
|
270
|
+
if (isAgentReq) {
|
|
271
|
+
buildAgentPipeline(lines, input, agentCategories, categoryFilter);
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
buildSkillPipeline(lines, input, categoryFilter, saasMatches);
|
|
275
|
+
}
|
|
276
|
+
// ── Install result format ─────────────────────────────────────────
|
|
277
|
+
lines.push(`---`);
|
|
278
|
+
lines.push(``);
|
|
279
|
+
lines.push(`### Install result format`);
|
|
280
|
+
lines.push(`After installing, confirm with one of:`);
|
|
281
|
+
if (isAgentReq) {
|
|
282
|
+
lines.push(`✅ Agent installed: .claude/agents/<name>.md — [one line: what it orchestrates]`);
|
|
283
|
+
lines.push(`✅ Then add to CLAUDE.md agents section (separate from skills)`);
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
lines.push(`✅ Installed: .claude/skills/<name>/SKILL.md — [one line: what it does]`);
|
|
287
|
+
}
|
|
288
|
+
lines.push(`⏭ No match in [source] — moving to next catalog`);
|
|
289
|
+
lines.push(`🔧 All 4 catalogs exhausted — created production-quality custom ${isAgentReq ? "agent" : "skill"}`);
|
|
290
|
+
lines.push(``);
|
|
291
|
+
return lines.join("\n");
|
|
292
|
+
}
|
|
293
|
+
// ── Agent pipeline (VoltAgent subagents → skills fallback) ──────────
|
|
294
|
+
function buildAgentPipeline(lines, input, agentCategories, categoryFilter) {
|
|
295
|
+
const safeName = input.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
|
|
296
|
+
const targetCategories = agentCategories.length > 0
|
|
297
|
+
? agentCategories
|
|
298
|
+
: ["09-meta-orchestration"];
|
|
299
|
+
// ── STEP 1: VoltAgent/awesome-claude-code-subagents ──────────────
|
|
300
|
+
const adjacentCategories = expandWithAdjacent(targetCategories);
|
|
121
301
|
lines.push(`---`);
|
|
122
302
|
lines.push(``);
|
|
123
|
-
lines.push(`### STEP 1 —
|
|
303
|
+
lines.push(`### STEP 1 — VoltAgent subagents (PRIMARY source for agents — 127+ specialized agents)`);
|
|
304
|
+
lines.push(``);
|
|
305
|
+
lines.push(`This is the preferred source for anything agent-shaped. 10 categories, 127+ agents.`);
|
|
306
|
+
lines.push(`If a match is found here, install to \`.claude/agents/\` (NOT .claude/skills/).`);
|
|
307
|
+
lines.push(``);
|
|
308
|
+
lines.push(`**1a. List agent files in the primary categories:**`);
|
|
309
|
+
lines.push(``);
|
|
310
|
+
for (const cat of targetCategories) {
|
|
311
|
+
lines.push(`\`\`\`bash`);
|
|
312
|
+
lines.push(`# Primary category: ${cat}`);
|
|
313
|
+
lines.push(`curl -sf \${GITHUB_TOKEN:+-H "Authorization: token \$GITHUB_TOKEN"} "${VOLTAGENT_SUBAGENTS_API}/${cat}" \\`);
|
|
314
|
+
lines.push(` | node -e "const d=JSON.parse(require('fs').readFileSync(0,'utf8'));` +
|
|
315
|
+
`if(Array.isArray(d)===false){console.log('SKIP');process.exit(0)}` +
|
|
316
|
+
`d.filter(x=>x.name.endsWith('.md')&&(x.name==='README.md')===false).forEach(x=>console.log(x.name))"`);
|
|
317
|
+
lines.push(`\`\`\``);
|
|
318
|
+
lines.push(``);
|
|
319
|
+
}
|
|
320
|
+
if (adjacentCategories.length > 0) {
|
|
321
|
+
lines.push(`**1b. If ALL primary categories above returned SKIP, try adjacent categories:**`);
|
|
322
|
+
lines.push(`Do NOT skip this step. A SKIP in the primary category does NOT mean VoltAgent has no match.`);
|
|
323
|
+
lines.push(``);
|
|
324
|
+
for (const cat of adjacentCategories) {
|
|
325
|
+
lines.push(`\`\`\`bash`);
|
|
326
|
+
lines.push(`# Adjacent category: ${cat}`);
|
|
327
|
+
lines.push(`curl -sf \${GITHUB_TOKEN:+-H "Authorization: token \$GITHUB_TOKEN"} "${VOLTAGENT_SUBAGENTS_API}/${cat}" \\`);
|
|
328
|
+
lines.push(` | node -e "const d=JSON.parse(require('fs').readFileSync(0,'utf8'));` +
|
|
329
|
+
`if(Array.isArray(d)===false){console.log('SKIP');process.exit(0)}` +
|
|
330
|
+
`d.filter(x=>x.name.endsWith('.md')&&(x.name==='README.md')===false).forEach(x=>console.log(x.name))"`);
|
|
331
|
+
lines.push(`\`\`\``);
|
|
332
|
+
lines.push(``);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
lines.push(`**1c. From ALL file lists above (primary + adjacent), pick the BEST match for "${input}".**`);
|
|
336
|
+
lines.push(`Match by name and relevance. If multiple candidates exist, pick the closest one.`);
|
|
337
|
+
lines.push(``);
|
|
338
|
+
lines.push(`**1d. Download the matched agent file:**`);
|
|
339
|
+
lines.push(`\`\`\`bash`);
|
|
340
|
+
lines.push(`# Replace CATEGORY and AGENT_FILE with actual values from 1a-1c`);
|
|
341
|
+
lines.push(`CATEGORY="${targetCategories[0]}"`);
|
|
342
|
+
lines.push(`AGENT_FILE="matched-agent.md"`);
|
|
343
|
+
lines.push(`mkdir -p ".claude/agents"`);
|
|
344
|
+
lines.push(`curl -sf "${VOLTAGENT_SUBAGENTS_RAW}/\${CATEGORY}/\${AGENT_FILE}" \\`);
|
|
345
|
+
lines.push(` -o ".claude/agents/\${AGENT_FILE}"`);
|
|
346
|
+
lines.push(`\`\`\``);
|
|
347
|
+
lines.push(``);
|
|
348
|
+
lines.push(`**1e. Verify the file has real content (rule 7 — must not be empty):**`);
|
|
349
|
+
lines.push(`\`\`\`bash`);
|
|
350
|
+
lines.push(`head -3 ".claude/agents/\${AGENT_FILE}"`);
|
|
351
|
+
lines.push(`wc -l ".claude/agents/\${AGENT_FILE}"`);
|
|
352
|
+
lines.push(`\`\`\``);
|
|
353
|
+
lines.push(`If the file is empty or just frontmatter with no body: delete it, log the failure.`);
|
|
354
|
+
lines.push(`If the file has real content: agent is installed. Skip to "Install result format" below.`);
|
|
124
355
|
lines.push(``);
|
|
356
|
+
lines.push(`**1f. README-driven fallback — if ALL category listings (primary + adjacent) returned SKIP:**`);
|
|
357
|
+
lines.push(`You MUST try this before moving to STEP 2. The README contains the full agent listing.`);
|
|
358
|
+
lines.push(``);
|
|
359
|
+
lines.push(`\`\`\`bash`);
|
|
360
|
+
lines.push(`# Step 1: Fetch the VoltAgent subagents README`);
|
|
361
|
+
lines.push(`curl -sf "https://raw.githubusercontent.com/${VOLTAGENT_SUBAGENTS_REPO}/main/README.md" \\`);
|
|
362
|
+
lines.push(` | node -e "const t=require('fs').readFileSync(0,'utf8');` +
|
|
363
|
+
`const re=/\\[([^\\]]+)\\]\\(([^)]+)\\)/g;let m;const r=[];` +
|
|
364
|
+
`while((m=re.exec(t))!==null){if(m[2].includes('.md')||m[2].includes('github.com'))r.push(m[1]+' | '+m[2])}` +
|
|
365
|
+
`r.slice(0,15).forEach(x=>console.log(x))"`);
|
|
125
366
|
lines.push(`\`\`\``);
|
|
126
|
-
lines.push(
|
|
367
|
+
lines.push(``);
|
|
368
|
+
lines.push(`\`\`\`bash`);
|
|
369
|
+
lines.push(`# Step 2: Pick the best entry for "${input}" from the list above.`);
|
|
370
|
+
lines.push(`# Extract the URL, convert github.com URLs to raw.githubusercontent.com (rule 2).`);
|
|
371
|
+
lines.push(`# Step 3: Download the resolved file`);
|
|
372
|
+
lines.push(`RESOLVED_URL="raw-url-from-step-2"`);
|
|
373
|
+
lines.push(`mkdir -p ".claude/agents"`);
|
|
374
|
+
lines.push(`curl -sf "\${RESOLVED_URL}" -o ".claude/agents/matched-agent.md"`);
|
|
127
375
|
lines.push(`\`\`\``);
|
|
128
|
-
lines.push(`
|
|
376
|
+
lines.push(`Verify content (rule 7). If empty: delete and continue to STEP 2.`);
|
|
377
|
+
lines.push(``);
|
|
378
|
+
// ── STEP 2: jeremylongshore community skills (fallback for agents) ─
|
|
379
|
+
lines.push(`---`);
|
|
380
|
+
lines.push(``);
|
|
381
|
+
lines.push(`### STEP 2 — Community skills catalog (fallback — 416 plugins)`);
|
|
382
|
+
lines.push(``);
|
|
383
|
+
lines.push(`**Before continuing:** Document in one line why STEP 1 produced no result.`);
|
|
384
|
+
lines.push(`Search for agent-like skills in the community catalog.`);
|
|
385
|
+
lines.push(`If curl fails, skip to STEP 3.`);
|
|
386
|
+
lines.push(``);
|
|
387
|
+
buildCommunitySkillsFetchBlock(lines, categoryFilter);
|
|
388
|
+
// ── STEP 3: ComposioHQ (fallback for SaaS/integration agents) ─────
|
|
389
|
+
lines.push(`---`);
|
|
390
|
+
lines.push(``);
|
|
391
|
+
lines.push(`### STEP 3 — ComposioHQ service integrations (1000+ skills — fallback)`);
|
|
392
|
+
lines.push(``);
|
|
393
|
+
lines.push(`**Before continuing:** Document in one line why STEPs 1 and 2 produced no result.`);
|
|
394
|
+
lines.push(`Strong for API and SaaS automation. Skills live in per-directory SKILL.md files.`);
|
|
395
|
+
lines.push(`If curl fails, skip to STEP 4.`);
|
|
396
|
+
lines.push(``);
|
|
397
|
+
buildComposioFetchBlock(lines, input);
|
|
398
|
+
// ── STEP 4: Create custom agent ───────────────────────────────────
|
|
399
|
+
lines.push(`---`);
|
|
400
|
+
lines.push(``);
|
|
401
|
+
lines.push(`### STEP 4 — All 3 catalogs exhausted. Create a production-quality custom agent.`);
|
|
402
|
+
lines.push(``);
|
|
403
|
+
lines.push(`You MUST have attempted all 3 sources above with real fetch calls before reaching here.`);
|
|
404
|
+
lines.push(`The custom agent must be production-valid on first write (Rule 4). No placeholders.`);
|
|
405
|
+
lines.push(``);
|
|
406
|
+
lines.push(`\`\`\`bash`);
|
|
407
|
+
lines.push(`mkdir -p ".claude/agents"`);
|
|
129
408
|
lines.push(`\`\`\``);
|
|
130
|
-
lines.push(
|
|
409
|
+
lines.push(`Then create \`.claude/agents/${safeName}.md\` with:`);
|
|
410
|
+
lines.push(`\`\`\`yaml`);
|
|
411
|
+
lines.push(`---`);
|
|
412
|
+
lines.push(`name: ${safeName}`);
|
|
413
|
+
lines.push(`description: "${input}"`);
|
|
414
|
+
lines.push(`tools: Read, Write, Edit, Bash, Glob, Grep`);
|
|
415
|
+
lines.push(`model: sonnet`);
|
|
416
|
+
lines.push(`---`);
|
|
417
|
+
lines.push(``);
|
|
418
|
+
lines.push(`[Complete agent instructions — task routing, responsibilities, integration points]`);
|
|
131
419
|
lines.push(`\`\`\``);
|
|
132
|
-
lines.push(`
|
|
420
|
+
lines.push(`The body must contain real, actionable agent instructions — not a template stub.`);
|
|
421
|
+
lines.push(``);
|
|
422
|
+
}
|
|
423
|
+
// ── Skill pipeline (community → VoltAgent skills → ComposioHQ) ──────
|
|
424
|
+
function buildSkillPipeline(lines, input, categoryFilter, saasMatches) {
|
|
425
|
+
const safeName = input.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
|
|
426
|
+
// ── STEP 1: Official Anthropic plugins ────────────────────────────
|
|
427
|
+
lines.push(`---`);
|
|
428
|
+
lines.push(``);
|
|
429
|
+
lines.push(`### STEP 1 — Official Anthropic plugins (always work, no schema errors)`);
|
|
430
|
+
lines.push(``);
|
|
431
|
+
lines.push(`Check if any of these 13 official plugins match the request:`);
|
|
432
|
+
lines.push(`agent-sdk-dev, claude-opus-4-5-migration, code-review, commit-commands,`);
|
|
133
433
|
lines.push(`explanatory-output-style, feature-dev, frontend-design, hookify, learning-output-style,`);
|
|
134
434
|
lines.push(`plugin-dev, pr-review-toolkit, ralph-wiggum, security-guidance`);
|
|
135
435
|
lines.push(``);
|
|
436
|
+
lines.push(`If a name above matches "${input}": install with \`/plugin install <name>@claude-code-plugins\``);
|
|
437
|
+
lines.push(`If no match, continue to STEP 2.`);
|
|
438
|
+
lines.push(``);
|
|
439
|
+
// ── STEP 2: jeremylongshore community skills ──────────────────────
|
|
136
440
|
lines.push(`---`);
|
|
137
441
|
lines.push(``);
|
|
138
|
-
lines.push(`### STEP 2 —
|
|
442
|
+
lines.push(`### STEP 2 — Community skills catalog (jeremylongshore — 416 plugins)`);
|
|
139
443
|
lines.push(``);
|
|
140
444
|
lines.push(`NOTE: /plugin marketplace add FAILS for this repo (one entry has broken schema).`);
|
|
141
|
-
lines.push(`Use the DIRECT FETCH approach below
|
|
142
|
-
lines.push(`If the curl command fails or returns an error, skip to STEP 3 immediately — do NOT stop.`);
|
|
445
|
+
lines.push(`Use the DIRECT FETCH approach below. If curl fails, skip to STEP 3.`);
|
|
143
446
|
lines.push(``);
|
|
144
|
-
lines
|
|
145
|
-
|
|
146
|
-
lines.push(
|
|
147
|
-
lines.push(
|
|
148
|
-
lines.push(
|
|
447
|
+
buildCommunitySkillsFetchBlock(lines, categoryFilter);
|
|
448
|
+
// ── STEP 3: VoltAgent curated skills ──────────────────────────────
|
|
449
|
+
lines.push(`---`);
|
|
450
|
+
lines.push(``);
|
|
451
|
+
lines.push(`### STEP 3 — VoltAgent curated agent skills (production-proven)`);
|
|
149
452
|
lines.push(``);
|
|
150
|
-
lines.push(`**
|
|
453
|
+
lines.push(`**Before continuing:** Document in one line why STEP 2 produced no result.`);
|
|
454
|
+
lines.push(`Curated real-world skills from engineering teams. If curl fails, skip to STEP 4.`);
|
|
151
455
|
lines.push(``);
|
|
152
|
-
lines.push(`**2c. List the skills inside that plugin:**`);
|
|
153
456
|
lines.push(`\`\`\`bash`);
|
|
154
|
-
lines.push(
|
|
155
|
-
lines.push(`
|
|
156
|
-
|
|
157
|
-
|
|
457
|
+
lines.push(`curl -sf \${GITHUB_TOKEN:+-H "Authorization: token \$GITHUB_TOKEN"} "${VOLTAGENT_SKILLS_API}" \\`);
|
|
458
|
+
lines.push(` | node -e "const d=JSON.parse(require('fs').readFileSync(0,'utf8'));` +
|
|
459
|
+
`if(Array.isArray(d)===false){console.log('SKIP');process.exit(0)}` +
|
|
460
|
+
`d.filter(x=>x.type==='dir'&&x.name.startsWith('.')===false).forEach(x=>console.log(x.name))"`);
|
|
461
|
+
lines.push(`\`\`\``);
|
|
462
|
+
lines.push(`If any directory name matches "${input}", fetch its SKILL.md:`);
|
|
463
|
+
lines.push(`\`\`\`bash`);
|
|
464
|
+
lines.push(`SKILL_DIR="matched-skill"`);
|
|
465
|
+
lines.push(`mkdir -p ".claude/skills/\${SKILL_DIR}"`);
|
|
466
|
+
lines.push(`curl -sf "https://raw.githubusercontent.com/${VOLTAGENT_SKILLS_REPO}/main/\${SKILL_DIR}/SKILL.md" \\`);
|
|
467
|
+
lines.push(` -o ".claude/skills/\${SKILL_DIR}/SKILL.md"`);
|
|
158
468
|
lines.push(`\`\`\``);
|
|
469
|
+
lines.push(`Verify content is real (not empty). If empty, delete and continue.`);
|
|
470
|
+
lines.push(``);
|
|
471
|
+
lines.push(`**README-driven fallback:** If the API listing above returned SKIP or no match, fetch the README:`);
|
|
159
472
|
lines.push(``);
|
|
160
|
-
lines.push(`**2d. For each skill listed, download and install it:**`);
|
|
161
473
|
lines.push(`\`\`\`bash`);
|
|
162
|
-
lines.push(`#
|
|
163
|
-
lines.push(`
|
|
164
|
-
lines.push(`
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
lines.push(`echo "Installed: .claude/skills/\${SKILL_NAME}/SKILL.md"`);
|
|
474
|
+
lines.push(`# Step 1: Fetch the VoltAgent skills README`);
|
|
475
|
+
lines.push(`curl -sf "https://raw.githubusercontent.com/${VOLTAGENT_SKILLS_REPO}/main/README.md" \\`);
|
|
476
|
+
lines.push(` | node -e "const t=require('fs').readFileSync(0,'utf8');` +
|
|
477
|
+
`const re=/\\[([^\\]]+)\\]\\(([^)]+)\\)/g;let m;const r=[];` +
|
|
478
|
+
`while((m=re.exec(t))!==null){if(m[2].includes('SKILL.md')||m[2].includes('github.com'))r.push(m[1]+' | '+m[2])}` +
|
|
479
|
+
`r.slice(0,10).forEach(x=>console.log(x))"`);
|
|
169
480
|
lines.push(`\`\`\``);
|
|
170
481
|
lines.push(``);
|
|
171
|
-
lines.push(
|
|
172
|
-
lines.push(
|
|
173
|
-
lines.push(
|
|
174
|
-
lines.push(`
|
|
175
|
-
lines.push(`
|
|
482
|
+
lines.push(`\`\`\`bash`);
|
|
483
|
+
lines.push(`# Step 2: Pick the entry best matching "${input}". Resolve the URL (rule 2).`);
|
|
484
|
+
lines.push(`# Step 3: Download the resolved skill file`);
|
|
485
|
+
lines.push(`RESOLVED_URL="raw-url-from-step-2"`);
|
|
486
|
+
lines.push(`SKILL_DIR="matched-skill"`);
|
|
487
|
+
lines.push(`mkdir -p ".claude/skills/\${SKILL_DIR}"`);
|
|
488
|
+
lines.push(`curl -sf "\${RESOLVED_URL}" -o ".claude/skills/\${SKILL_DIR}/SKILL.md"`);
|
|
176
489
|
lines.push(`\`\`\``);
|
|
490
|
+
lines.push(`Verify content (rule 7). If empty: delete and continue to next STEP.`);
|
|
177
491
|
lines.push(``);
|
|
492
|
+
// ── STEP 4: ComposioHQ service integrations ───────────────────────
|
|
178
493
|
lines.push(`---`);
|
|
179
494
|
lines.push(``);
|
|
180
|
-
lines.push(`### STEP
|
|
495
|
+
lines.push(`### STEP 4 — ComposioHQ service integrations (1000+ skills)`);
|
|
181
496
|
lines.push(``);
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
lines.push(`Note: ${source.note}`);
|
|
189
|
-
}
|
|
190
|
-
lines.push(``);
|
|
191
|
-
}
|
|
497
|
+
lines.push(`**Before continuing:** Document in one line why STEPs 2 and 3 produced no result.`);
|
|
498
|
+
lines.push(`Strong for API/SaaS automation: Gmail, Slack, GitHub, Notion, Stripe, Shopify, etc.`);
|
|
499
|
+
lines.push(`If curl fails, skip to STEP 5.`);
|
|
500
|
+
lines.push(``);
|
|
501
|
+
buildComposioFetchBlock(lines, input);
|
|
502
|
+
// ── STEP 5: Create custom skill ───────────────────────────────────
|
|
192
503
|
lines.push(`---`);
|
|
193
504
|
lines.push(``);
|
|
194
|
-
lines.push(`### STEP
|
|
505
|
+
lines.push(`### STEP 5 — All 4 catalogs exhausted. Create a production-quality custom skill.`);
|
|
506
|
+
lines.push(``);
|
|
507
|
+
lines.push(`You MUST have attempted all 4 sources above with real fetch calls before reaching here.`);
|
|
508
|
+
lines.push(`The custom skill must be production-valid on first write (Rule 4). No placeholders.`);
|
|
195
509
|
lines.push(``);
|
|
196
510
|
lines.push(`\`\`\`bash`);
|
|
197
|
-
lines.push(`mkdir -p ".claude/skills/${
|
|
511
|
+
lines.push(`mkdir -p ".claude/skills/${safeName}"`);
|
|
198
512
|
lines.push(`\`\`\``);
|
|
199
|
-
lines.push(`Then create SKILL.md with:`);
|
|
513
|
+
lines.push(`Then create \`.claude/skills/${safeName}/SKILL.md\` with:`);
|
|
200
514
|
lines.push(`\`\`\`yaml`);
|
|
201
515
|
lines.push(`---`);
|
|
202
|
-
lines.push(`name: ${
|
|
203
|
-
lines.push(`description: ${input}`);
|
|
516
|
+
lines.push(`name: ${safeName}`);
|
|
517
|
+
lines.push(`description: "${input}"`);
|
|
204
518
|
lines.push(`---`);
|
|
205
519
|
lines.push(``);
|
|
206
|
-
lines.push(`[
|
|
520
|
+
lines.push(`[Complete skill instructions — not a stub. Must work on first use.]`);
|
|
207
521
|
lines.push(`\`\`\``);
|
|
208
522
|
lines.push(``);
|
|
209
|
-
|
|
523
|
+
}
|
|
524
|
+
// ── Universal catalog resolution rules (applies to all sources) ─────────
|
|
525
|
+
function buildUniversalRulesBlock(lines) {
|
|
526
|
+
lines.push(`### Universal catalog resolution rules`);
|
|
210
527
|
lines.push(``);
|
|
211
|
-
lines.push(
|
|
212
|
-
lines.push(
|
|
213
|
-
lines.push(
|
|
214
|
-
lines.push(
|
|
528
|
+
lines.push(`These rules apply to EVERY source below. Read them first.`);
|
|
529
|
+
lines.push(``);
|
|
530
|
+
lines.push(`**1. Catalog shape detection — detect before processing:**`);
|
|
531
|
+
lines.push(`When you fetch a catalog endpoint, the response determines your strategy:`);
|
|
532
|
+
lines.push(`- **JSON catalog**: valid JSON with a structured list (array of objects with name/source/description). Filter by relevance, navigate source paths, download.`);
|
|
533
|
+
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.`);
|
|
534
|
+
lines.push(`- **Directory listing**: GitHub API array with "type"/"name"/"download_url" fields. List entries, match by name, download via raw URL.`);
|
|
535
|
+
lines.push(`Detect the shape first. Never assume one format.`);
|
|
536
|
+
lines.push(``);
|
|
537
|
+
lines.push(`**2. Universal GitHub URL resolution — works for ANY repo, ANY author:**`);
|
|
538
|
+
lines.push(`Convert any GitHub URL to a downloadable form by extracting {owner}, {repo}, {branch}, {path} dynamically:`);
|
|
539
|
+
lines.push(`- \`github.com/{owner}/{repo}/tree/{branch}/{path}\` → \`https://raw.githubusercontent.com/{owner}/{repo}/{branch}/{path}\``);
|
|
540
|
+
lines.push(`- \`github.com/{owner}/{repo}/blob/{branch}/{path}\` → \`https://raw.githubusercontent.com/{owner}/{repo}/{branch}/{path}\``);
|
|
541
|
+
lines.push(`- Directory URL → list via \`https://api.github.com/repos/{owner}/{repo}/contents/{path}\`, then download individual files`);
|
|
542
|
+
lines.push(`**Never hardcode a specific owner or repo in the resolution logic.** Always derive them dynamically from whatever link the catalog provides.`);
|
|
543
|
+
lines.push(``);
|
|
544
|
+
lines.push(`**3. README-driven external link navigation:**`);
|
|
545
|
+
lines.push(`When a catalog entry links to an external repository (different {owner}/{repo}):`);
|
|
546
|
+
lines.push(`1. Extract {owner}/{repo} from the link URL`);
|
|
547
|
+
lines.push(`2. Resolve to the raw file or directory listing in that foreign repo`);
|
|
548
|
+
lines.push(`3. If it points to a directory, list contents via API to find the installable .md file`);
|
|
549
|
+
lines.push(`4. Download from the foreign repo using universal resolution above`);
|
|
550
|
+
lines.push(`The catalog is just a curated map — the real content lives in the external repo.`);
|
|
551
|
+
lines.push(``);
|
|
552
|
+
lines.push(`**4. Candidate scoring — compare before choosing:**`);
|
|
553
|
+
lines.push(`When multiple candidates match, score each on three axes:`);
|
|
554
|
+
lines.push(`- **Relevance** (highest weight): does the description directly address the request?`);
|
|
555
|
+
lines.push(`- **Scope**: is it surgical and focused, or a kitchen-sink tool? Prefer focused — lower cost, easier to reason about.`);
|
|
556
|
+
lines.push(`- **Uniqueness**: does it duplicate something already installed in .claude/skills/ or .claude/agents/? Deprioritize duplicates.`);
|
|
557
|
+
lines.push(`Install only the highest-scoring candidate. One high-quality tool per task.`);
|
|
558
|
+
lines.push(``);
|
|
559
|
+
lines.push(`**5. No absolute paths — never \`cd\` before commands:**`);
|
|
560
|
+
lines.push(`Claude Code already runs in the project working directory. Do NOT prepend \`cd /absolute/path &&\` to any command.`);
|
|
561
|
+
lines.push(`Use relative paths only (e.g., \`.claude/agents/\`, \`.claude/skills/\`). Absolute paths with backslashes break bash on Windows.`);
|
|
562
|
+
lines.push(``);
|
|
563
|
+
lines.push(`**6. Output filtering — cap context cost:**`);
|
|
564
|
+
lines.push(`Every curl result MUST be piped through a node parser that returns at most 5–15 lines of structured data.`);
|
|
565
|
+
lines.push(`The raw JSON/README response must NEVER enter the context unfiltered.`);
|
|
566
|
+
lines.push(`Chain multiple sequential fetch decisions inside a single bash script so they execute as one tool call.`);
|
|
567
|
+
lines.push(``);
|
|
568
|
+
lines.push(`**7. Content verification — never keep stubs:**`);
|
|
569
|
+
lines.push(`After downloading any file, verify ALL of these before accepting:`);
|
|
570
|
+
lines.push(`- Not empty (0 bytes)`);
|
|
571
|
+
lines.push(`- Not only YAML frontmatter with no body (just \`---\\nname: x\\n---\` and nothing after)`);
|
|
572
|
+
lines.push(`- Contains at least 50 characters of instruction content after frontmatter`);
|
|
573
|
+
lines.push(`If verification fails: delete the file, log which source/candidate failed, continue to next candidate or next STEP.`);
|
|
574
|
+
lines.push(``);
|
|
575
|
+
}
|
|
576
|
+
// ── Shared fetch blocks ─────────────────────────────────────────────────
|
|
577
|
+
function buildCommunitySkillsFetchBlock(lines, categoryFilter) {
|
|
578
|
+
lines.push(`**Stage 1 — Fetch catalog and find matching plugin:**`);
|
|
579
|
+
lines.push(`\`\`\`bash`);
|
|
580
|
+
lines.push(`curl -sf "${MARKETPLACE_CATALOG_URL}" \\`);
|
|
581
|
+
lines.push(` | node -e "const d=JSON.parse(require('fs').readFileSync(0,'utf8'));` +
|
|
582
|
+
`const q='${categoryFilter}';` +
|
|
583
|
+
`const r=d.plugins.filter(p=>(q===''||p.category.includes(q))&&p.name&&p.source).slice(0,10)` +
|
|
584
|
+
`.map(p=>({name:p.name,source:p.source,desc:p.description}));` +
|
|
585
|
+
`console.log(JSON.stringify(r,null,2));"`);
|
|
586
|
+
lines.push(`\`\`\``);
|
|
587
|
+
lines.push(`If this returns an error or empty array, skip to the next STEP.`);
|
|
588
|
+
lines.push(``);
|
|
589
|
+
lines.push(`**Stage 2 — Score candidates and pick the best match (see rule 4: Relevance > Scope > Uniqueness):**`);
|
|
590
|
+
lines.push(`\`\`\`bash`);
|
|
591
|
+
lines.push(`# Replace PLUGIN_SOURCE_PATH with the "source" value from Stage 1`);
|
|
592
|
+
lines.push(`PLUGIN_SOURCE_PATH="plugins/category/plugin-name"`);
|
|
593
|
+
lines.push(`curl -sf \${GITHUB_TOKEN:+-H "Authorization: token \$GITHUB_TOKEN"} "https://api.github.com/repos/${MARKETPLACE_REPO}/contents/\${PLUGIN_SOURCE_PATH}/skills" \\`);
|
|
594
|
+
lines.push(` | node -e "const a=JSON.parse(require('fs').readFileSync(0,'utf8'));` +
|
|
595
|
+
`if(Array.isArray(a)===false){console.log('NO_SKILLS_DIR');process.exit(0)}` +
|
|
596
|
+
`a.forEach(x=>console.log(x.name))"`);
|
|
597
|
+
lines.push(`\`\`\``);
|
|
598
|
+
lines.push(`If this fails or shows NO_SKILLS_DIR, the plugin has no installable skills — skip.`);
|
|
599
|
+
lines.push(``);
|
|
600
|
+
lines.push(`**Stage 3 — Download each skill file and install:**`);
|
|
601
|
+
lines.push(`\`\`\`bash`);
|
|
602
|
+
lines.push(`# Replace PLUGIN_SOURCE_PATH and SKILL_NAME with actual values`);
|
|
603
|
+
lines.push(`PLUGIN_SOURCE_PATH="plugins/category/plugin-name"`);
|
|
604
|
+
lines.push(`SKILL_NAME="skill-directory-name"`);
|
|
605
|
+
lines.push(`mkdir -p ".claude/skills/\${SKILL_NAME}"`);
|
|
606
|
+
lines.push(`curl -sf "https://raw.githubusercontent.com/${MARKETPLACE_REPO}/main/\${PLUGIN_SOURCE_PATH}/skills/\${SKILL_NAME}/SKILL.md" \\`);
|
|
607
|
+
lines.push(` -o ".claude/skills/\${SKILL_NAME}/SKILL.md"`);
|
|
608
|
+
lines.push(`\`\`\``);
|
|
609
|
+
lines.push(`Verify the file has real content (not empty, not just frontmatter). If empty: delete and move on.`);
|
|
610
|
+
lines.push(``);
|
|
611
|
+
}
|
|
612
|
+
function buildComposioFetchBlock(lines, input) {
|
|
613
|
+
lines.push(`**Stage 1 — List available skill directories:**`);
|
|
614
|
+
lines.push(`\`\`\`bash`);
|
|
615
|
+
lines.push(`curl -sf \${GITHUB_TOKEN:+-H "Authorization: token \$GITHUB_TOKEN"} "${COMPOSIO_API}" \\`);
|
|
616
|
+
lines.push(` | node -e "const d=JSON.parse(require('fs').readFileSync(0,'utf8'));` +
|
|
617
|
+
`if(Array.isArray(d)===false){console.log('SKIP');process.exit(0)}` +
|
|
618
|
+
`d.filter(x=>x.type==='dir'&&x.name.startsWith('.')===false).forEach(x=>console.log(x.name))"`);
|
|
619
|
+
lines.push(`\`\`\``);
|
|
620
|
+
lines.push(``);
|
|
621
|
+
lines.push(`**Stage 2 — Pick the directory that best matches "${input}":**`);
|
|
622
|
+
lines.push(`Match by name similarity. If no directory name is relevant, skip.`);
|
|
623
|
+
lines.push(``);
|
|
624
|
+
lines.push(`**Stage 3 — Download the SKILL.md from the matched directory:**`);
|
|
625
|
+
lines.push(`\`\`\`bash`);
|
|
626
|
+
lines.push(`SKILL_DIR="matched-directory"`);
|
|
627
|
+
lines.push(`mkdir -p ".claude/skills/\${SKILL_DIR}"`);
|
|
628
|
+
lines.push(`curl -sf "${COMPOSIO_RAW}/\${SKILL_DIR}/SKILL.md" \\`);
|
|
629
|
+
lines.push(` -o ".claude/skills/\${SKILL_DIR}/SKILL.md"`);
|
|
630
|
+
lines.push(`\`\`\``);
|
|
631
|
+
lines.push(`Verify the file has real content (rule 7 above). If empty: delete and move on.`);
|
|
632
|
+
lines.push(``);
|
|
633
|
+
lines.push(`**README-driven fallback:** If the directory listing above fails or returns unexpected content:`);
|
|
634
|
+
lines.push(``);
|
|
635
|
+
lines.push(`\`\`\`bash`);
|
|
636
|
+
lines.push(`# Step 1: Fetch the ComposioHQ README and extract entries with links`);
|
|
637
|
+
lines.push(`curl -sf "https://raw.githubusercontent.com/${COMPOSIO_REPO}/master/README.md" \\`);
|
|
638
|
+
lines.push(` | node -e "const t=require('fs').readFileSync(0,'utf8');` +
|
|
639
|
+
`const re=/\\[([^\\]]+)\\]\\(([^)]+)\\)/g;let m;const r=[];` +
|
|
640
|
+
`while((m=re.exec(t))!==null){if(m[2].includes('SKILL.md')||m[2].includes('github.com'))r.push(m[1]+' | '+m[2])}` +
|
|
641
|
+
`r.slice(0,10).forEach(x=>console.log(x))"`);
|
|
642
|
+
lines.push(`\`\`\``);
|
|
643
|
+
lines.push(``);
|
|
644
|
+
lines.push(`\`\`\`bash`);
|
|
645
|
+
lines.push(`# Step 2: Pick the entry best matching "${input}". Resolve the URL (rule 2).`);
|
|
646
|
+
lines.push(`# Step 3: Download the resolved skill file`);
|
|
647
|
+
lines.push(`RESOLVED_URL="raw-url-from-step-2"`);
|
|
648
|
+
lines.push(`SKILL_DIR="matched-skill"`);
|
|
649
|
+
lines.push(`mkdir -p ".claude/skills/\${SKILL_DIR}"`);
|
|
650
|
+
lines.push(`curl -sf "\${RESOLVED_URL}" -o ".claude/skills/\${SKILL_DIR}/SKILL.md"`);
|
|
651
|
+
lines.push(`\`\`\``);
|
|
652
|
+
lines.push(`Verify content (rule 7). If empty: delete and continue to next STEP.`);
|
|
215
653
|
lines.push(``);
|
|
216
|
-
return lines.join("\n");
|
|
217
654
|
}
|
package/package.json
CHANGED
package/templates/add.md
CHANGED
|
@@ -4,6 +4,7 @@ Add to Claude Code setup: "{{USER_INPUT}}"
|
|
|
4
4
|
|
|
5
5
|
**CRITICAL: Marketplace-first. Do NOT ask clarifying questions. Search and install automatically.**
|
|
6
6
|
**Execute every curl/install command yourself. The user expects zero-friction automation.**
|
|
7
|
+
**A fetch failure is NOT a stop — it is a routing signal to the next catalog.**
|
|
7
8
|
|
|
8
9
|
## Project context
|
|
9
10
|
{{PROJECT_CONTEXT}}
|
|
@@ -29,15 +30,52 @@ Skills: {{SKILLS_LIST}} | Commands: {{COMMANDS_LIST}}
|
|
|
29
30
|
|
|
30
31
|
---
|
|
31
32
|
|
|
33
|
+
## Marketplace search — AUTOMATICALLY spawn the marketplace-fetcher subagent
|
|
34
|
+
|
|
35
|
+
**MANDATORY:** For any request that involves installing a skill, agent, plugin, or integration,
|
|
36
|
+
you MUST use the Agent tool to spawn the `marketplace-fetcher` subagent. Do NOT run catalog
|
|
37
|
+
fetches in your own context. Do NOT ask the user whether to spawn — just do it.
|
|
38
|
+
|
|
39
|
+
**How to spawn:** Use the Agent tool with these parameters:
|
|
40
|
+
- `description`: "Fetch and install: {{USER_INPUT}}"
|
|
41
|
+
- `prompt`: Copy the ENTIRE marketplace instructions block below (between the `BEGIN` and `END` markers) as the subagent's task prompt.
|
|
42
|
+
|
|
43
|
+
The subagent runs in isolation on Haiku: it fetches catalogs, parses READMEs, downloads files to disk,
|
|
44
|
+
and returns exactly one confirmation line. Its context dies when it finishes — zero catalog bloat
|
|
45
|
+
enters your session. This cuts API calls from ~113 to ~6 and cache-read tokens from ~4.8M to ~180K.
|
|
46
|
+
|
|
47
|
+
**Only skip the subagent** if the request is purely a single-file edit (add one MCP server to .mcp.json,
|
|
48
|
+
add a hook to settings.json, or append to CLAUDE.md) with no catalog search needed.
|
|
49
|
+
|
|
50
|
+
--- BEGIN MARKETPLACE INSTRUCTIONS (pass this entire block to the subagent) ---
|
|
51
|
+
|
|
32
52
|
{{MARKETPLACE_INSTRUCTIONS}}
|
|
33
53
|
|
|
54
|
+
--- END MARKETPLACE INSTRUCTIONS ---
|
|
55
|
+
|
|
56
|
+
After the subagent returns its one-line result, continue to the post-install steps below.
|
|
57
|
+
If the subagent returned `FAILED`, create a production-quality custom skill/agent yourself.
|
|
58
|
+
|
|
34
59
|
---
|
|
35
60
|
|
|
36
61
|
## What you must actually do
|
|
37
62
|
|
|
38
63
|
Parse the user's request and take ALL applicable actions:
|
|
39
64
|
|
|
40
|
-
### 1.
|
|
65
|
+
### 1. Agents (if request is about agents/orchestration/subagents)
|
|
66
|
+
If the marketplace pipeline installed an agent file to `.claude/agents/`:
|
|
67
|
+
- Verify the file has YAML frontmatter (name, description, tools, model) and a body
|
|
68
|
+
- Document it in CLAUDE.md under a **separate agents section** (not mixed with skills)
|
|
69
|
+
- Agent entry format in CLAUDE.md:
|
|
70
|
+
```
|
|
71
|
+
## Agents
|
|
72
|
+
- **agent-name** — what it orchestrates, when to invoke it
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Agent files live in `.claude/agents/<name>.md` — NOT in `.claude/skills/`.
|
|
76
|
+
Agents and skills are architecturally different and must never be mixed.
|
|
77
|
+
|
|
78
|
+
### 2. MCP servers
|
|
41
79
|
If the request mentions an external service (database, API, browser, etc.):
|
|
42
80
|
- Check the verified MCP package list below
|
|
43
81
|
- If found: add to `.mcp.json` with OS-correct format (detected: {{DETECTED_OS}})
|
|
@@ -125,8 +163,8 @@ MCP format — create new .mcp.json:
|
|
|
125
163
|
```
|
|
126
164
|
{{/if}}
|
|
127
165
|
|
|
128
|
-
###
|
|
129
|
-
If the request mentions skills or capabilities:
|
|
166
|
+
### 3. Skills
|
|
167
|
+
If the request mentions skills or capabilities (NOT agents):
|
|
130
168
|
- Create `.claude/skills/<name>/SKILL.md` with proper frontmatter
|
|
131
169
|
- Use `description:` so Claude knows when to load the skill
|
|
132
170
|
- Search the marketplace for matching pre-built skills (see above)
|
|
@@ -141,7 +179,7 @@ description: What this skill does
|
|
|
141
179
|
Instructions...
|
|
142
180
|
```
|
|
143
181
|
|
|
144
|
-
###
|
|
182
|
+
### 4. Hooks
|
|
145
183
|
If the request implies automated actions (formatting, building, notifications):
|
|
146
184
|
- Add to `.claude/settings.json` using the CORRECT hooks format
|
|
147
185
|
- Verify the tool exists before adding a hook for it
|
|
@@ -165,13 +203,11 @@ Correct hooks format:
|
|
|
165
203
|
}
|
|
166
204
|
```
|
|
167
205
|
|
|
168
|
-
### 4. Plugins
|
|
169
|
-
If the request matches a marketplace category or SaaS platform:
|
|
170
|
-
- Suggest the relevant plugin with install commands
|
|
171
|
-
- Show the user exactly how to install it
|
|
172
|
-
|
|
173
206
|
### 5. CLAUDE.md
|
|
174
207
|
Document any new capabilities, services, or patterns added.
|
|
208
|
+
- Skills go under `## Skills` section
|
|
209
|
+
- Agents go under `## Agents` section (separate — never mixed)
|
|
210
|
+
- MCP servers go under `## MCP Servers` section
|
|
175
211
|
|
|
176
212
|
## Rules
|
|
177
213
|
- Read current content above before writing. Merge/append only.
|
|
@@ -180,6 +216,9 @@ Document any new capabilities, services, or patterns added.
|
|
|
180
216
|
- All env var refs use `${VARNAME}` syntax. Document new vars in .env.example.
|
|
181
217
|
- **NEVER write a "model" key into settings.json**
|
|
182
218
|
- Produce valid JSON only.
|
|
219
|
+
- Agents install to `.claude/agents/` — Skills install to `.claude/skills/`
|
|
220
|
+
- Every installed file must contain real, functional content (Rule 7).
|
|
221
|
+
- A fetch failure is a routing signal, not a stop condition (Rule 6).
|
|
183
222
|
|
|
184
223
|
## Output — one line per file
|
|
185
224
|
Updated: ✅ [path] — [what and why]
|