claude-code-templates 1.1.1 → 1.1.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.
Files changed (22) hide show
  1. package/bin/create-claude-config.js +3 -4
  2. package/package.json +3 -3
  3. package/scripts/sync-templates.js +28 -28
  4. package/src/file-operations.js +56 -13
  5. package/src/index.js +3 -6
  6. package/src/prompts.js +164 -30
  7. package/src/templates.js +12 -20
  8. package/templates/javascript-typescript/examples/angular-app/.claude/commands/components.md +63 -0
  9. package/templates/javascript-typescript/examples/angular-app/.claude/commands/services.md +62 -0
  10. package/templates/javascript-typescript/examples/node-api/.claude/commands/api-endpoint.md +46 -0
  11. package/templates/javascript-typescript/examples/node-api/.claude/commands/database.md +56 -0
  12. package/templates/javascript-typescript/examples/node-api/.claude/commands/middleware.md +61 -0
  13. package/templates/javascript-typescript/examples/node-api/.claude/commands/route.md +57 -0
  14. package/templates/javascript-typescript/examples/node-api/CLAUDE.md +102 -0
  15. package/templates/javascript-typescript/examples/react-app/.claude/commands/component.md +29 -0
  16. package/templates/javascript-typescript/examples/react-app/.claude/commands/hooks.md +44 -0
  17. package/templates/javascript-typescript/examples/react-app/.claude/commands/state-management.md +45 -0
  18. package/templates/javascript-typescript/examples/react-app/CLAUDE.md +81 -0
  19. package/templates/javascript-typescript/examples/vue-app/.claude/commands/components.md +46 -0
  20. package/templates/javascript-typescript/examples/vue-app/.claude/commands/composables.md +51 -0
  21. package/templates/javascript-typescript/.claude/commands/react-component.md +0 -54
  22. package/templates/javascript-typescript/.claude/commands/route.md +0 -193
@@ -6,7 +6,7 @@ const boxen = require('boxen');
6
6
  const createClaudeConfig = require('../src/index');
7
7
 
8
8
  // ASCII Art for Claude Code Templates
9
- const banner = chalk.cyan(`
9
+ const banner = chalk.hex('#D97706')(`
10
10
  ██████╗██╗ █████╗ ██╗ ██╗██████╗ ███████╗
11
11
  ██╔════╝██║ ██╔══██╗██║ ██║██╔══██╗██╔════╝
12
12
  ██║ ██║ ███████║██║ ██║██║ ██║█████╗
@@ -27,9 +27,8 @@ const banner = chalk.cyan(`
27
27
  ██║ ██╔══╝ ██║╚██╔╝██║██╔═══╝ ██║ ██╔══██║ ██║ ██╔══╝ ╚════██║
28
28
  ██║ ███████╗██║ ╚═╝ ██║██║ ███████╗██║ ██║ ██║ ███████╗███████║
29
29
  ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚══════╝╚══════╝
30
- `) + chalk.yellow(`
31
- 🚀 Setup Claude Code for any project language 🚀
32
- `);
30
+ `) +
31
+ chalk.yellow('\n 🚀 Setup Claude Code for any project language 🚀');
33
32
 
34
33
  console.log(banner);
35
34
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-code-templates",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
4
4
  "description": "CLI tool to setup Claude Code configurations for different programming languages",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -13,8 +13,8 @@
13
13
  "start": "node bin/create-claude-config.js",
14
14
  "test": "echo \"Error: no test specified\" && exit 1",
15
15
  "sync": "node scripts/sync-templates.js",
16
- "presync": "echo \"🔄 Iniciando sincronización de plantillas...\"",
17
- "postsync": "echo \"✅ Sincronización completada. Listo para publicar!\"",
16
+ "presync": "echo \"🔄 Starting template synchronization...\"",
17
+ "postsync": "echo \"✅ Synchronization completed. Ready to publish!\"",
18
18
  "prepublishOnly": "npm run sync"
19
19
  },
20
20
  "keywords": [
@@ -5,17 +5,17 @@ const path = require('path');
5
5
  const chalk = require('chalk');
6
6
 
7
7
  /**
8
- * Script para sincronizar las plantillas desde las carpetas root
9
- * hacia cli-tool/templates/
8
+ * Script to synchronize templates from root folders
9
+ * to cli-tool/templates/
10
10
  */
11
11
 
12
12
  async function syncTemplates() {
13
- console.log(chalk.blue('🔄 Sincronizando plantillas...'));
13
+ console.log(chalk.blue('🔄 Synchronizing templates...'));
14
14
 
15
15
  const rootDir = path.join(__dirname, '..', '..');
16
16
  const templatesDir = path.join(__dirname, '..', 'templates');
17
17
 
18
- // Lenguajes a sincronizar
18
+ // Languages to synchronize
19
19
  const languages = ['common', 'javascript-typescript', 'python', 'rust', 'go'];
20
20
 
21
21
  let totalCopied = 0;
@@ -26,26 +26,26 @@ async function syncTemplates() {
26
26
  const targetDir = path.join(templatesDir, language);
27
27
 
28
28
  if (!await fs.pathExists(sourceDir)) {
29
- console.log(chalk.yellow(`⚠️ Carpeta source no existe: ${language}`));
29
+ console.log(chalk.yellow(`⚠️ Source folder does not exist: ${language}`));
30
30
  continue;
31
31
  }
32
32
 
33
- console.log(chalk.cyan(`\n📂 Sincronizando ${language}...`));
33
+ console.log(chalk.cyan(`\n📂 Synchronizing ${language}...`));
34
34
 
35
- // Limpiar directorio destino
35
+ // Clean destination directory
36
36
  if (await fs.pathExists(targetDir)) {
37
37
  await fs.remove(targetDir);
38
- console.log(chalk.gray(` 🗑️ Directorio anterior eliminado`));
38
+ console.log(chalk.gray(` 🗑️ Previous directory removed`));
39
39
  }
40
40
 
41
- // Copiar todo desde source
41
+ // Copy everything from source
42
42
  try {
43
43
  await fs.copy(sourceDir, targetDir, {
44
44
  filter: (src, dest) => {
45
- // Filtrar archivos que no queremos copiar
45
+ // Filter files we don't want to copy
46
46
  const relativePath = path.relative(sourceDir, src);
47
47
 
48
- // Excluir directorios y archivos específicos
48
+ // Exclude specific directories and files
49
49
  if (relativePath.includes('node_modules')) return false;
50
50
  if (relativePath.includes('.git')) return false;
51
51
  if (relativePath.includes('package-lock.json')) return false;
@@ -55,26 +55,26 @@ async function syncTemplates() {
55
55
  }
56
56
  });
57
57
 
58
- // Contar archivos copiados
58
+ // Count copied files
59
59
  const stats = await getDirectoryStats(targetDir);
60
60
  totalCopied += stats.files;
61
61
 
62
- console.log(chalk.green(` ✅ ${stats.files} archivos copiados`));
62
+ console.log(chalk.green(` ✅ ${stats.files} files copied`));
63
63
 
64
- // Mostrar estructura copiada
64
+ // Show copied structure
65
65
  if (stats.files > 0) {
66
66
  await showDirectoryStructure(targetDir, ' ');
67
67
  }
68
68
 
69
69
  } catch (error) {
70
- console.error(chalk.red(` ❌ Error copiando ${language}:`), error.message);
70
+ console.error(chalk.red(` ❌ Error copying ${language}:`), error.message);
71
71
  }
72
72
  }
73
73
 
74
- console.log(chalk.green(`\n🎉 Sincronización completada!`));
75
- console.log(chalk.white(`📊 Total de archivos sincronizados: ${totalCopied}`));
74
+ console.log(chalk.green(`\n🎉 Synchronization completed!`));
75
+ console.log(chalk.white(`📊 Total synchronized files: ${totalCopied}`));
76
76
 
77
- // Verificar que no existan archivos hooks
77
+ // Verify that no hook files exist
78
78
  await cleanupOldReferences();
79
79
  }
80
80
 
@@ -118,7 +118,7 @@ async function showDirectoryStructure(dir, prefix = '') {
118
118
  if (stat.isDirectory()) {
119
119
  console.log(chalk.blue(`${prefix}${connector}${item}/`));
120
120
  if (item === '.claude' || item === 'commands') {
121
- // Mostrar solo un nivel más para .claude y commands
121
+ // Show only one more level for .claude and commands
122
122
  const subItems = await fs.readdir(itemPath);
123
123
  const newPrefix = prefix + (isLast ? ' ' : '│ ');
124
124
  for (let j = 0; j < Math.min(subItems.length, 3); j++) {
@@ -127,7 +127,7 @@ async function showDirectoryStructure(dir, prefix = '') {
127
127
  console.log(chalk.gray(`${newPrefix}${subConnector}${subItem}`));
128
128
  }
129
129
  if (subItems.length > 3) {
130
- console.log(chalk.gray(`${newPrefix}└── ... y ${subItems.length - 3} más`));
130
+ console.log(chalk.gray(`${newPrefix}└── ... and ${subItems.length - 3} more`));
131
131
  }
132
132
  }
133
133
  } else {
@@ -137,22 +137,22 @@ async function showDirectoryStructure(dir, prefix = '') {
137
137
  }
138
138
 
139
139
  async function cleanupOldReferences() {
140
- console.log(chalk.yellow('\n🧹 Limpiando referencias obsoletas...'));
140
+ console.log(chalk.yellow('\n🧹 Cleaning up obsolete references...'));
141
141
 
142
142
  const templatesDir = path.join(__dirname, '..', 'templates');
143
143
 
144
- // Buscar y eliminar directorios hooks
144
+ // Search and remove hooks directories
145
145
  const languages = ['javascript-typescript', 'python', 'common'];
146
146
 
147
147
  for (const language of languages) {
148
148
  const hooksDir = path.join(templatesDir, language, '.claude', 'hooks');
149
149
  if (await fs.pathExists(hooksDir)) {
150
150
  await fs.remove(hooksDir);
151
- console.log(chalk.yellow(` 🗑️ Eliminado: ${language}/.claude/hooks/`));
151
+ console.log(chalk.yellow(` 🗑️ Removed: ${language}/.claude/hooks/`));
152
152
  }
153
153
  }
154
154
 
155
- // Verificar archivos vacíos en commands
155
+ // Check for empty files in commands
156
156
  for (const language of languages) {
157
157
  const commandsDir = path.join(templatesDir, language, '.claude', 'commands');
158
158
  if (await fs.pathExists(commandsDir)) {
@@ -160,10 +160,10 @@ async function cleanupOldReferences() {
160
160
  for (const file of files) {
161
161
  const filePath = path.join(commandsDir, file);
162
162
  const stat = await fs.stat(filePath);
163
- if (stat.size < 50) { // Archivos muy pequeños probablemente estén vacíos
163
+ if (stat.size < 50) { // Very small files are probably empty
164
164
  const content = await fs.readFile(filePath, 'utf8');
165
165
  if (content.trim().length < 10) {
166
- console.log(chalk.yellow(` ⚠️ Archivo posiblemente vacío: ${language}/.claude/commands/${file} (${stat.size} bytes)`));
166
+ console.log(chalk.yellow(` ⚠️ Possibly empty file: ${language}/.claude/commands/${file} (${stat.size} bytes)`));
167
167
  }
168
168
  }
169
169
  }
@@ -171,10 +171,10 @@ async function cleanupOldReferences() {
171
171
  }
172
172
  }
173
173
 
174
- // Función para ejecutar la sincronización
174
+ // Function to execute synchronization
175
175
  if (require.main === module) {
176
176
  syncTemplates().catch(error => {
177
- console.error(chalk.red('❌ Error durante la sincronización:'), error);
177
+ console.error(chalk.red('❌ Error during synchronization:'), error);
178
178
  process.exit(1);
179
179
  });
180
180
  }
@@ -23,25 +23,68 @@ async function copyTemplateFiles(templateConfig, targetDir) {
23
23
  console.log(chalk.yellow(`📁 Existing .claude directory backed up to .claude.backup`));
24
24
  }
25
25
 
26
- // Copy base files (but skip .claude/commands for now)
26
+ // Copy base files and framework-specific files
27
27
  for (const file of templateConfig.files) {
28
28
  const sourcePath = path.join(templateDir, file.source);
29
29
  const destPath = path.join(targetDir, file.destination);
30
30
 
31
31
  try {
32
- // Skip .claude/commands directories - we'll handle them separately
33
- if (file.source.includes('.claude/commands')) {
34
- continue;
35
- }
36
-
37
- await fs.copy(sourcePath, destPath, {
38
- overwrite: true,
39
- filter: (src) => {
40
- // Skip commands directory during base copy
41
- return !src.includes('.claude/commands');
32
+ // Handle framework-specific command files specially
33
+ if (file.source.includes('.claude/commands') && file.source.includes('examples/')) {
34
+ // This is a framework-specific commands directory - merge with existing commands
35
+ await fs.ensureDir(destPath);
36
+
37
+ // Copy framework-specific commands to the commands directory
38
+ const frameworkFiles = await fs.readdir(sourcePath);
39
+ for (const frameworkFile of frameworkFiles) {
40
+ const srcFile = path.join(sourcePath, frameworkFile);
41
+ const destFile = path.join(destPath, frameworkFile);
42
+ await fs.copy(srcFile, destFile, { overwrite: true });
43
+ }
44
+
45
+ console.log(chalk.green(`✓ Copied framework commands ${file.source} → ${file.destination}`));
46
+ } else if (file.source.includes('.claude') && !file.source.includes('examples/')) {
47
+ // This is base .claude directory - copy it but handle commands specially
48
+ await fs.copy(sourcePath, destPath, {
49
+ overwrite: true,
50
+ filter: (src) => {
51
+ // Skip the commands directory itself - we'll handle it separately
52
+ return !src.endsWith('.claude/commands');
53
+ }
54
+ });
55
+
56
+ // Now handle base commands specifically
57
+ const baseCommandsPath = path.join(sourcePath, 'commands');
58
+ const destCommandsPath = path.join(destPath, 'commands');
59
+
60
+ if (await fs.pathExists(baseCommandsPath)) {
61
+ await fs.ensureDir(destCommandsPath);
62
+
63
+ // Copy base commands, but exclude framework-specific ones that were moved
64
+ const baseCommands = await fs.readdir(baseCommandsPath);
65
+ const excludeCommands = ['react-component.md', 'route.md', 'api-endpoint.md']; // Commands moved to framework dirs
66
+
67
+ for (const baseCommand of baseCommands) {
68
+ if (!excludeCommands.includes(baseCommand)) {
69
+ const srcFile = path.join(baseCommandsPath, baseCommand);
70
+ const destFile = path.join(destCommandsPath, baseCommand);
71
+ await fs.copy(srcFile, destFile, { overwrite: true });
72
+ }
73
+ }
42
74
  }
43
- });
44
- console.log(chalk.green(`✓ Copied ${file.source} → ${file.destination}`));
75
+
76
+ console.log(chalk.green(`✓ Copied base configuration and commands ${file.source} → ${file.destination}`));
77
+ } else {
78
+ // Copy regular files (CLAUDE.md, settings.json, etc.)
79
+ await fs.copy(sourcePath, destPath, {
80
+ overwrite: true,
81
+ filter: (src) => {
82
+ // Skip commands directory during regular copy - we handle them above
83
+ return !src.includes('.claude/commands');
84
+ }
85
+ });
86
+ console.log(chalk.green(`✓ Copied ${file.source} → ${file.destination}`));
87
+ }
45
88
  } catch (error) {
46
89
  console.error(chalk.red(`✗ Failed to copy ${file.source}:`), error.message);
47
90
  throw error;
package/src/index.js CHANGED
@@ -5,7 +5,7 @@ const path = require('path');
5
5
  const ora = require('ora');
6
6
  const { detectProject } = require('./utils');
7
7
  const { getTemplateConfig } = require('./templates');
8
- const { createPrompts } = require('./prompts');
8
+ const { createPrompts, interactivePrompts } = require('./prompts');
9
9
  const { copyTemplateFiles } = require('./file-operations');
10
10
 
11
11
  async function createClaudeConfig(options = {}) {
@@ -19,9 +19,6 @@ async function createClaudeConfig(options = {}) {
19
19
  const projectInfo = await detectProject(targetDir);
20
20
  spinner.succeed('Project detection complete');
21
21
 
22
- // Create interactive prompts
23
- const prompts = createPrompts(projectInfo, options);
24
-
25
22
  let config;
26
23
  if (options.yes) {
27
24
  // Use defaults
@@ -31,8 +28,8 @@ async function createClaudeConfig(options = {}) {
31
28
  features: []
32
29
  };
33
30
  } else {
34
- // Interactive prompts
35
- config = await inquirer.prompt(prompts);
31
+ // Interactive prompts with back navigation
32
+ config = await interactivePrompts(projectInfo, options);
36
33
  }
37
34
 
38
35
  // Check if user confirmed the setup
package/src/prompts.js CHANGED
@@ -1,7 +1,169 @@
1
1
  const chalk = require('chalk');
2
+ const inquirer = require('inquirer');
2
3
  const { getAvailableLanguages, getFrameworksForLanguage } = require('./templates');
3
4
  const { getCommandsForLanguageAndFramework } = require('./command-scanner');
4
5
 
6
+ async function interactivePrompts(projectInfo, options = {}) {
7
+ const state = {
8
+ currentStep: 0,
9
+ answers: {},
10
+ steps: []
11
+ };
12
+
13
+ // Build steps array based on options
14
+ if (!options.language) state.steps.push('language');
15
+ if (!options.framework) state.steps.push('framework');
16
+ state.steps.push('commands', 'confirm');
17
+
18
+ while (state.currentStep < state.steps.length) {
19
+ const stepName = state.steps[state.currentStep];
20
+ const result = await showStep(stepName, state.answers, projectInfo, options);
21
+
22
+ if (result.action === 'back') {
23
+ if (state.currentStep > 0) {
24
+ state.currentStep--;
25
+ // Clear the answer for the step we're going back from
26
+ delete state.answers[stepName];
27
+ }
28
+ } else if (result.action === 'next') {
29
+ state.answers[stepName] = result.value;
30
+ state.currentStep++;
31
+ } else if (result.action === 'exit') {
32
+ return { confirm: false };
33
+ }
34
+ }
35
+
36
+ return state.answers;
37
+ }
38
+
39
+ async function showStep(stepName, currentAnswers, projectInfo, options) {
40
+ const stepConfig = getStepConfig(stepName, currentAnswers, projectInfo, options);
41
+
42
+ if (!stepConfig) {
43
+ return { action: 'next', value: null };
44
+ }
45
+
46
+ // Add back option if not first step
47
+ const isFirstStep = stepName === 'language' || (options.language && stepName === 'framework') ||
48
+ (options.language && options.framework && stepName === 'commands');
49
+
50
+ if (!isFirstStep && stepConfig.type === 'list') {
51
+ stepConfig.choices = [
52
+ { value: '__back__', name: chalk.gray('← Back') },
53
+ new inquirer.Separator(),
54
+ ...stepConfig.choices
55
+ ];
56
+ }
57
+
58
+ const answer = await inquirer.prompt([stepConfig]);
59
+ const value = answer[stepName];
60
+
61
+ if (value === '__back__') {
62
+ return { action: 'back' };
63
+ }
64
+
65
+ return { action: 'next', value };
66
+ }
67
+
68
+ function getStepConfig(stepName, currentAnswers, projectInfo, options) {
69
+ switch (stepName) {
70
+ case 'language':
71
+ return {
72
+ type: 'list',
73
+ name: 'language',
74
+ message: 'Select your programming language:',
75
+ choices: getAvailableLanguages(),
76
+ default: projectInfo.detectedLanguage || 'common',
77
+ prefix: chalk.blue('🔤')
78
+ };
79
+
80
+ case 'framework':
81
+ const selectedLanguage = currentAnswers.language || options.language;
82
+ const frameworks = getFrameworksForLanguage(selectedLanguage);
83
+
84
+ if (frameworks.length === 0) {
85
+ return null; // Skip this step
86
+ }
87
+
88
+ return {
89
+ type: 'list',
90
+ name: 'framework',
91
+ message: 'Select your framework (optional):',
92
+ choices: [
93
+ { value: 'none', name: 'None / Generic' },
94
+ ...frameworks
95
+ ],
96
+ default: projectInfo.detectedFramework || 'none',
97
+ prefix: chalk.green('🎯')
98
+ };
99
+
100
+ case 'commands':
101
+ const commandLanguage = currentAnswers.language || options.language;
102
+ const commandFramework = currentAnswers.framework || options.framework;
103
+
104
+ if (!commandLanguage || commandLanguage === 'common') {
105
+ return {
106
+ type: 'checkbox',
107
+ name: 'commands',
108
+ message: 'Select commands to include (use space to select):',
109
+ choices: [
110
+ {
111
+ value: 'basic-commands',
112
+ name: 'Basic development commands',
113
+ checked: true
114
+ }
115
+ ],
116
+ prefix: chalk.cyan('📋')
117
+ };
118
+ }
119
+
120
+ const availableCommands = getCommandsForLanguageAndFramework(commandLanguage, commandFramework);
121
+
122
+ return {
123
+ type: 'checkbox',
124
+ name: 'commands',
125
+ message: 'Select commands to include (use space to select, enter to continue):',
126
+ choices: availableCommands.map(cmd => ({
127
+ value: cmd.name,
128
+ name: `${cmd.displayName} - ${cmd.description}`,
129
+ checked: cmd.checked
130
+ })),
131
+ prefix: chalk.cyan('📋')
132
+ };
133
+
134
+ case 'confirm':
135
+ const confirmLanguage = currentAnswers.language || options.language || 'common';
136
+ const confirmFramework = currentAnswers.framework || options.framework || 'none';
137
+ const commandCount = currentAnswers.commands ? currentAnswers.commands.length : 0;
138
+
139
+ let message = `Setup Claude Code for ${chalk.cyan(confirmLanguage)}`;
140
+ if (confirmFramework !== 'none') {
141
+ message += ` with ${chalk.green(confirmFramework)}`;
142
+ }
143
+ if (commandCount > 0) {
144
+ message += ` (${chalk.yellow(commandCount)} commands)`;
145
+ }
146
+ message += '?';
147
+
148
+ return {
149
+ type: 'list',
150
+ name: 'confirm',
151
+ message,
152
+ choices: [
153
+ { value: '__back__', name: chalk.gray('← Back to modify settings') },
154
+ new inquirer.Separator(),
155
+ { value: true, name: chalk.green('✅ Yes, proceed with setup') },
156
+ { value: false, name: chalk.red('❌ No, cancel setup') }
157
+ ],
158
+ default: true,
159
+ prefix: chalk.red('🚀')
160
+ };
161
+
162
+ default:
163
+ return null;
164
+ }
165
+ }
166
+
5
167
  function createPrompts(projectInfo, options = {}) {
6
168
  const prompts = [];
7
169
 
@@ -76,35 +238,6 @@ function createPrompts(projectInfo, options = {}) {
76
238
  }
77
239
  });
78
240
 
79
- // Features selection
80
- prompts.push({
81
- type: 'checkbox',
82
- name: 'features',
83
- message: 'Select additional features:',
84
- choices: [
85
- {
86
- value: 'git-hooks',
87
- name: 'Git hooks integration',
88
- checked: false
89
- },
90
- {
91
- value: 'testing',
92
- name: 'Enhanced testing commands',
93
- checked: true
94
- },
95
- {
96
- value: 'linting',
97
- name: 'Code linting and formatting',
98
- checked: true
99
- },
100
- {
101
- value: 'debugging',
102
- name: 'Debugging helpers',
103
- checked: false
104
- }
105
- ],
106
- prefix: chalk.yellow('⚙️')
107
- });
108
241
 
109
242
  // Confirmation
110
243
  prompts.push({
@@ -152,5 +285,6 @@ function createProjectTypePrompt(detectedTypes) {
152
285
 
153
286
  module.exports = {
154
287
  createPrompts,
155
- createProjectTypePrompt
288
+ createProjectTypePrompt,
289
+ interactivePrompts
156
290
  };
package/src/templates.js CHANGED
@@ -15,7 +15,8 @@ const TEMPLATES_CONFIG = {
15
15
  description: 'Optimized for modern JS/TS development',
16
16
  files: [
17
17
  { source: 'javascript-typescript/CLAUDE.md', destination: 'CLAUDE.md' },
18
- { source: 'javascript-typescript/.claude', destination: '.claude' }
18
+ { source: 'javascript-typescript/.claude', destination: '.claude' },
19
+ { source: 'javascript-typescript/.mcp.json', destination: '.mcp.json' }
19
20
  ],
20
21
  frameworks: {
21
22
  'react': {
@@ -26,11 +27,15 @@ const TEMPLATES_CONFIG = {
26
27
  },
27
28
  'vue': {
28
29
  name: 'Vue.js',
29
- additionalFiles: []
30
+ additionalFiles: [
31
+ { source: 'javascript-typescript/examples/vue-app/.claude/commands', destination: '.claude/commands' }
32
+ ]
30
33
  },
31
34
  'angular': {
32
35
  name: 'Angular',
33
- additionalFiles: []
36
+ additionalFiles: [
37
+ { source: 'javascript-typescript/examples/angular-app/.claude/commands', destination: '.claude/commands' }
38
+ ]
34
39
  },
35
40
  'node': {
36
41
  name: 'Node.js',
@@ -42,25 +47,12 @@ const TEMPLATES_CONFIG = {
42
47
  },
43
48
  'python': {
44
49
  name: 'Python',
45
- description: 'Optimized for Python development',
50
+ description: 'Configuration for Python projects (Coming Soon)',
46
51
  files: [
47
- { source: 'python/CLAUDE.md', destination: 'CLAUDE.md' },
48
- { source: 'python/.claude', destination: '.claude' }
52
+ { source: 'common/CLAUDE.md', destination: 'CLAUDE.md' },
53
+ { source: 'common/.claude', destination: '.claude' }
49
54
  ],
50
- frameworks: {
51
- 'django': {
52
- name: 'Django',
53
- additionalFiles: []
54
- },
55
- 'flask': {
56
- name: 'Flask',
57
- additionalFiles: []
58
- },
59
- 'fastapi': {
60
- name: 'FastAPI',
61
- additionalFiles: []
62
- }
63
- }
55
+ comingSoon: true
64
56
  },
65
57
  'rust': {
66
58
  name: 'Rust',
@@ -0,0 +1,63 @@
1
+ # Angular Components
2
+
3
+ Create Angular components for $ARGUMENTS following project conventions.
4
+
5
+ ## Task
6
+
7
+ Create or optimize Angular components based on the requirements:
8
+
9
+ 1. **Analyze existing components**: Check current component patterns, naming conventions, and folder organization
10
+ 2. **Examine Angular setup**: Review project structure, module organization, and TypeScript configuration
11
+ 3. **Identify component type**: Determine the component category:
12
+ - Presentation components (dumb/pure components)
13
+ - Container components (smart components with state)
14
+ - Feature components (business logic components)
15
+ - Shared/UI components (reusable across features)
16
+ - Layout components (structural components)
17
+ 4. **Check dependencies**: Review existing components and shared modules to avoid duplication
18
+ 5. **Implement component**: Create component with proper TypeScript types and lifecycle hooks
19
+ 6. **Add inputs/outputs**: Define @Input and @Output properties with proper typing
20
+ 7. **Create template**: Build HTML template with proper Angular directives and bindings
21
+ 8. **Add styles**: Implement component styles following project's styling approach
22
+ 9. **Create tests**: Write comprehensive unit tests with TestBed and proper mocking
23
+ 10. **Update module**: Register component in appropriate Angular module
24
+
25
+ ## Implementation Requirements
26
+
27
+ - Follow project's Angular architecture and naming conventions
28
+ - Use proper component lifecycle hooks (OnInit, OnDestroy, etc.)
29
+ - Include comprehensive TypeScript interfaces for inputs and outputs
30
+ - Implement proper change detection strategy (OnPush when possible)
31
+ - Add proper subscription management with takeUntil or async pipe
32
+ - Follow Angular style guide and project coding standards
33
+ - Consider component performance and memory management
34
+
35
+ ## Component Patterns to Consider
36
+
37
+ Based on the request:
38
+ - **Smart Components**: Container components that manage state and services
39
+ - **Dumb Components**: Presentation components that only receive inputs
40
+ - **Feature Components**: Components specific to business features
41
+ - **Shared Components**: Reusable UI components across the application
42
+ - **Form Components**: Reactive forms with validation and custom controls
43
+ - **Data Display**: Components for tables, lists, cards with proper data binding
44
+
45
+ ## Angular-Specific Implementation
46
+
47
+ - **Template Syntax**: Proper use of Angular directives (*ngFor, *ngIf, etc.)
48
+ - **Data Binding**: Property binding, event binding, two-way binding
49
+ - **Change Detection**: OnPush strategy for performance optimization
50
+ - **Lifecycle Management**: Proper use of lifecycle hooks
51
+ - **Dependency Injection**: Service injection in component constructors
52
+ - **Testing**: TestBed configuration with proper mocking and spies
53
+
54
+ ## Important Notes
55
+
56
+ - ALWAYS examine existing components first to understand project patterns
57
+ - Use the same styling approach and class naming as existing components
58
+ - Follow project's folder structure for components (usually feature-based)
59
+ - Don't install new dependencies without asking
60
+ - Consider component reusability and single responsibility principle
61
+ - Add proper TypeScript types for all component properties and methods
62
+ - Use trackBy functions for performance in *ngFor loops
63
+ - Implement proper unsubscription patterns to prevent memory leaks