claude-code-templates 1.13.0 → 1.13.1
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/bin/create-claude-config.js +3 -0
- package/package.json +1 -1
- package/src/index.js +183 -0
|
@@ -54,6 +54,9 @@ program
|
|
|
54
54
|
.option('--analytics', 'launch real-time Claude Code analytics dashboard')
|
|
55
55
|
.option('--chats, --agents', 'launch Claude Code chats/agents dashboard (opens directly to conversations)')
|
|
56
56
|
.option('--health-check, --health, --check, --verify', 'run comprehensive health check to verify Claude Code setup')
|
|
57
|
+
.option('--agent <agent>', 'install specific agent component')
|
|
58
|
+
.option('--command <command>', 'install specific command component')
|
|
59
|
+
.option('--mcp <mcp>', 'install specific MCP component')
|
|
57
60
|
.action(async (options) => {
|
|
58
61
|
try {
|
|
59
62
|
await createClaudeConfig(options);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-code-templates",
|
|
3
|
-
"version": "1.13.
|
|
3
|
+
"version": "1.13.1",
|
|
4
4
|
"description": "CLI tool to setup Claude Code configurations with framework-specific commands, automation hooks and MCP Servers for your projects",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
package/src/index.js
CHANGED
|
@@ -80,6 +80,22 @@ async function showMainMenu() {
|
|
|
80
80
|
async function createClaudeConfig(options = {}) {
|
|
81
81
|
const targetDir = options.directory || process.cwd();
|
|
82
82
|
|
|
83
|
+
// Handle individual component installation
|
|
84
|
+
if (options.agent) {
|
|
85
|
+
await installIndividualAgent(options.agent, targetDir, options);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (options.command) {
|
|
90
|
+
await installIndividualCommand(options.command, targetDir, options);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (options.mcp) {
|
|
95
|
+
await installIndividualMCP(options.mcp, targetDir, options);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
83
99
|
// Handle command stats analysis (both singular and plural)
|
|
84
100
|
if (options.commandStats || options.commandsStats) {
|
|
85
101
|
await runCommandStats(options);
|
|
@@ -253,4 +269,171 @@ async function createClaudeConfig(options = {}) {
|
|
|
253
269
|
}
|
|
254
270
|
}
|
|
255
271
|
|
|
272
|
+
// Individual component installation functions
|
|
273
|
+
async function installIndividualAgent(agentName, targetDir, options) {
|
|
274
|
+
console.log(chalk.blue(`🤖 Installing agent: ${agentName}`));
|
|
275
|
+
|
|
276
|
+
try {
|
|
277
|
+
// Check if components directory exists
|
|
278
|
+
const componentsPath = path.join(__dirname, '..', 'components', 'agents');
|
|
279
|
+
const agentFile = path.join(componentsPath, `${agentName}.md`);
|
|
280
|
+
|
|
281
|
+
if (!await fs.pathExists(agentFile)) {
|
|
282
|
+
console.log(chalk.red(`❌ Agent "${agentName}" not found`));
|
|
283
|
+
console.log(chalk.yellow('Available agents:'));
|
|
284
|
+
|
|
285
|
+
// List available agents
|
|
286
|
+
if (await fs.pathExists(componentsPath)) {
|
|
287
|
+
const agents = await fs.readdir(componentsPath);
|
|
288
|
+
agents.filter(f => f.endsWith('.md')).forEach(agent => {
|
|
289
|
+
console.log(chalk.cyan(` - ${agent.replace('.md', '')}`));
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// For agents, they are typically part of templates, so we need to determine
|
|
296
|
+
// the appropriate language/framework and install the complete template
|
|
297
|
+
const agentContent = await fs.readFile(agentFile, 'utf8');
|
|
298
|
+
const language = extractLanguageFromAgent(agentContent, agentName);
|
|
299
|
+
const framework = extractFrameworkFromAgent(agentContent, agentName);
|
|
300
|
+
|
|
301
|
+
console.log(chalk.yellow(`📝 Agent "${agentName}" is part of ${language}/${framework} template`));
|
|
302
|
+
console.log(chalk.blue('🚀 Installing complete template with this agent...'));
|
|
303
|
+
|
|
304
|
+
// Install the template that contains this agent (avoid recursion)
|
|
305
|
+
const setupOptions = {
|
|
306
|
+
...options,
|
|
307
|
+
language,
|
|
308
|
+
framework,
|
|
309
|
+
yes: true,
|
|
310
|
+
targetDirectory: targetDir,
|
|
311
|
+
agent: null // Remove agent to avoid recursion
|
|
312
|
+
};
|
|
313
|
+
delete setupOptions.agent;
|
|
314
|
+
await createClaudeConfig(setupOptions);
|
|
315
|
+
|
|
316
|
+
console.log(chalk.green(`✅ Agent "${agentName}" installed successfully!`));
|
|
317
|
+
|
|
318
|
+
} catch (error) {
|
|
319
|
+
console.log(chalk.red(`❌ Error installing agent: ${error.message}`));
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
async function installIndividualCommand(commandName, targetDir, options) {
|
|
324
|
+
console.log(chalk.blue(`⚡ Installing command: ${commandName}`));
|
|
325
|
+
|
|
326
|
+
try {
|
|
327
|
+
// Check if components directory exists
|
|
328
|
+
const componentsPath = path.join(__dirname, '..', 'components', 'commands');
|
|
329
|
+
const commandFile = path.join(componentsPath, `${commandName}.md`);
|
|
330
|
+
|
|
331
|
+
if (!await fs.pathExists(commandFile)) {
|
|
332
|
+
console.log(chalk.red(`❌ Command "${commandName}" not found`));
|
|
333
|
+
console.log(chalk.yellow('Available commands:'));
|
|
334
|
+
|
|
335
|
+
// List available commands
|
|
336
|
+
if (await fs.pathExists(componentsPath)) {
|
|
337
|
+
const commands = await fs.readdir(componentsPath);
|
|
338
|
+
commands.filter(f => f.endsWith('.md')).forEach(command => {
|
|
339
|
+
console.log(chalk.cyan(` - ${command.replace('.md', '')}`));
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// Create .claude/commands directory if it doesn't exist
|
|
346
|
+
const commandsDir = path.join(targetDir, '.claude', 'commands');
|
|
347
|
+
await fs.ensureDir(commandsDir);
|
|
348
|
+
|
|
349
|
+
// Copy the command file
|
|
350
|
+
const targetFile = path.join(commandsDir, `${commandName}.md`);
|
|
351
|
+
await fs.copy(commandFile, targetFile);
|
|
352
|
+
|
|
353
|
+
console.log(chalk.green(`✅ Command "${commandName}" installed successfully!`));
|
|
354
|
+
console.log(chalk.cyan(`📁 Installed to: ${path.relative(targetDir, targetFile)}`));
|
|
355
|
+
|
|
356
|
+
} catch (error) {
|
|
357
|
+
console.log(chalk.red(`❌ Error installing command: ${error.message}`));
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
async function installIndividualMCP(mcpName, targetDir, options) {
|
|
362
|
+
console.log(chalk.blue(`🔌 Installing MCP: ${mcpName}`));
|
|
363
|
+
|
|
364
|
+
try {
|
|
365
|
+
// Check if components directory exists
|
|
366
|
+
const componentsPath = path.join(__dirname, '..', 'components', 'mcps');
|
|
367
|
+
const mcpFile = path.join(componentsPath, `${mcpName}.json`);
|
|
368
|
+
|
|
369
|
+
if (!await fs.pathExists(mcpFile)) {
|
|
370
|
+
console.log(chalk.red(`❌ MCP "${mcpName}" not found`));
|
|
371
|
+
console.log(chalk.yellow('Available MCPs:'));
|
|
372
|
+
|
|
373
|
+
// List available MCPs
|
|
374
|
+
if (await fs.pathExists(componentsPath)) {
|
|
375
|
+
const mcps = await fs.readdir(componentsPath);
|
|
376
|
+
mcps.filter(f => f.endsWith('.json')).forEach(mcp => {
|
|
377
|
+
console.log(chalk.cyan(` - ${mcp.replace('.json', '')}`));
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// Read the MCP configuration
|
|
384
|
+
const mcpConfig = await fs.readJson(mcpFile);
|
|
385
|
+
|
|
386
|
+
// Check if .mcp.json exists in target directory
|
|
387
|
+
const targetMcpFile = path.join(targetDir, '.mcp.json');
|
|
388
|
+
let existingConfig = {};
|
|
389
|
+
|
|
390
|
+
if (await fs.pathExists(targetMcpFile)) {
|
|
391
|
+
existingConfig = await fs.readJson(targetMcpFile);
|
|
392
|
+
console.log(chalk.yellow('📝 Existing .mcp.json found, merging configurations...'));
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// Merge configurations
|
|
396
|
+
const mergedConfig = {
|
|
397
|
+
...existingConfig,
|
|
398
|
+
...mcpConfig
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
// Write the merged configuration
|
|
402
|
+
await fs.writeJson(targetMcpFile, mergedConfig, { spaces: 2 });
|
|
403
|
+
|
|
404
|
+
console.log(chalk.green(`✅ MCP "${mcpName}" installed successfully!`));
|
|
405
|
+
console.log(chalk.cyan(`📁 Configuration merged into: ${path.relative(targetDir, targetMcpFile)}`));
|
|
406
|
+
|
|
407
|
+
} catch (error) {
|
|
408
|
+
console.log(chalk.red(`❌ Error installing MCP: ${error.message}`));
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
// Helper functions to extract language/framework from agent content
|
|
413
|
+
function extractLanguageFromAgent(content, agentName) {
|
|
414
|
+
// Try to determine language from agent content or filename
|
|
415
|
+
if (agentName.includes('react') || content.includes('React')) return 'javascript-typescript';
|
|
416
|
+
if (agentName.includes('django') || content.includes('Django')) return 'python';
|
|
417
|
+
if (agentName.includes('fastapi') || content.includes('FastAPI')) return 'python';
|
|
418
|
+
if (agentName.includes('flask') || content.includes('Flask')) return 'python';
|
|
419
|
+
if (agentName.includes('rails') || content.includes('Rails')) return 'ruby';
|
|
420
|
+
if (agentName.includes('api-security') || content.includes('API security')) return 'javascript-typescript';
|
|
421
|
+
if (agentName.includes('database') || content.includes('database')) return 'javascript-typescript';
|
|
422
|
+
|
|
423
|
+
// Default to javascript-typescript for general agents
|
|
424
|
+
return 'javascript-typescript';
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
function extractFrameworkFromAgent(content, agentName) {
|
|
428
|
+
// Try to determine framework from agent content or filename
|
|
429
|
+
if (agentName.includes('react') || content.includes('React')) return 'react';
|
|
430
|
+
if (agentName.includes('django') || content.includes('Django')) return 'django';
|
|
431
|
+
if (agentName.includes('fastapi') || content.includes('FastAPI')) return 'fastapi';
|
|
432
|
+
if (agentName.includes('flask') || content.includes('Flask')) return 'flask';
|
|
433
|
+
if (agentName.includes('rails') || content.includes('Rails')) return 'rails';
|
|
434
|
+
|
|
435
|
+
// For general agents, return none to install the base template
|
|
436
|
+
return 'none';
|
|
437
|
+
}
|
|
438
|
+
|
|
256
439
|
module.exports = { createClaudeConfig, showMainMenu };
|