claude-code-templates 1.13.0 → 1.13.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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.0",
3
+ "version": "1.13.2",
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": {
@@ -147,7 +147,7 @@ class DashboardPage {
147
147
  </div>
148
148
  </div>
149
149
  </div>
150
- <a href="https://github.com/anthropics/claude-code-templates" target="_blank" class="github-link" title="Star on GitHub">
150
+ <a href="https://github.com/davila7/claude-code-templates" target="_blank" class="github-link" title="Star on GitHub">
151
151
  <span class="github-icon">⭐</span>
152
152
  Star on GitHub
153
153
  </a>
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 };