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.
- package/bin/create-claude-config.js +3 -4
- package/package.json +3 -3
- package/scripts/sync-templates.js +28 -28
- package/src/file-operations.js +56 -13
- package/src/index.js +3 -6
- package/src/prompts.js +164 -30
- package/src/templates.js +12 -20
- package/templates/javascript-typescript/examples/angular-app/.claude/commands/components.md +63 -0
- package/templates/javascript-typescript/examples/angular-app/.claude/commands/services.md +62 -0
- package/templates/javascript-typescript/examples/node-api/.claude/commands/api-endpoint.md +46 -0
- package/templates/javascript-typescript/examples/node-api/.claude/commands/database.md +56 -0
- package/templates/javascript-typescript/examples/node-api/.claude/commands/middleware.md +61 -0
- package/templates/javascript-typescript/examples/node-api/.claude/commands/route.md +57 -0
- package/templates/javascript-typescript/examples/node-api/CLAUDE.md +102 -0
- package/templates/javascript-typescript/examples/react-app/.claude/commands/component.md +29 -0
- package/templates/javascript-typescript/examples/react-app/.claude/commands/hooks.md +44 -0
- package/templates/javascript-typescript/examples/react-app/.claude/commands/state-management.md +45 -0
- package/templates/javascript-typescript/examples/react-app/CLAUDE.md +81 -0
- package/templates/javascript-typescript/examples/vue-app/.claude/commands/components.md +46 -0
- package/templates/javascript-typescript/examples/vue-app/.claude/commands/composables.md +51 -0
- package/templates/javascript-typescript/.claude/commands/react-component.md +0 -54
- 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.
|
|
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
|
-
`) +
|
|
31
|
-
|
|
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.
|
|
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 \"🔄
|
|
17
|
-
"postsync": "echo \"✅
|
|
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
|
|
9
|
-
*
|
|
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('🔄
|
|
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
|
-
//
|
|
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(`⚠️
|
|
29
|
+
console.log(chalk.yellow(`⚠️ Source folder does not exist: ${language}`));
|
|
30
30
|
continue;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
console.log(chalk.cyan(`\n📂
|
|
33
|
+
console.log(chalk.cyan(`\n📂 Synchronizing ${language}...`));
|
|
34
34
|
|
|
35
|
-
//
|
|
35
|
+
// Clean destination directory
|
|
36
36
|
if (await fs.pathExists(targetDir)) {
|
|
37
37
|
await fs.remove(targetDir);
|
|
38
|
-
console.log(chalk.gray(` 🗑️
|
|
38
|
+
console.log(chalk.gray(` 🗑️ Previous directory removed`));
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
//
|
|
41
|
+
// Copy everything from source
|
|
42
42
|
try {
|
|
43
43
|
await fs.copy(sourceDir, targetDir, {
|
|
44
44
|
filter: (src, dest) => {
|
|
45
|
-
//
|
|
45
|
+
// Filter files we don't want to copy
|
|
46
46
|
const relativePath = path.relative(sourceDir, src);
|
|
47
47
|
|
|
48
|
-
//
|
|
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
|
-
//
|
|
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}
|
|
62
|
+
console.log(chalk.green(` ✅ ${stats.files} files copied`));
|
|
63
63
|
|
|
64
|
-
//
|
|
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
|
|
70
|
+
console.error(chalk.red(` ❌ Error copying ${language}:`), error.message);
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
console.log(chalk.green(`\n🎉
|
|
75
|
-
console.log(chalk.white(`📊 Total
|
|
74
|
+
console.log(chalk.green(`\n🎉 Synchronization completed!`));
|
|
75
|
+
console.log(chalk.white(`📊 Total synchronized files: ${totalCopied}`));
|
|
76
76
|
|
|
77
|
-
//
|
|
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
|
-
//
|
|
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}└── ...
|
|
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🧹
|
|
140
|
+
console.log(chalk.yellow('\n🧹 Cleaning up obsolete references...'));
|
|
141
141
|
|
|
142
142
|
const templatesDir = path.join(__dirname, '..', 'templates');
|
|
143
143
|
|
|
144
|
-
//
|
|
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(` 🗑️
|
|
151
|
+
console.log(chalk.yellow(` 🗑️ Removed: ${language}/.claude/hooks/`));
|
|
152
152
|
}
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
-
//
|
|
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) { //
|
|
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(` ⚠️
|
|
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
|
-
//
|
|
174
|
+
// Function to execute synchronization
|
|
175
175
|
if (require.main === module) {
|
|
176
176
|
syncTemplates().catch(error => {
|
|
177
|
-
console.error(chalk.red('❌ Error
|
|
177
|
+
console.error(chalk.red('❌ Error during synchronization:'), error);
|
|
178
178
|
process.exit(1);
|
|
179
179
|
});
|
|
180
180
|
}
|
package/src/file-operations.js
CHANGED
|
@@ -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
|
|
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
|
-
//
|
|
33
|
-
if (file.source.includes('.claude/commands')) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
-
|
|
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
|
|
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: '
|
|
50
|
+
description: 'Configuration for Python projects (Coming Soon)',
|
|
46
51
|
files: [
|
|
47
|
-
{ source: '
|
|
48
|
-
{ source: '
|
|
52
|
+
{ source: 'common/CLAUDE.md', destination: 'CLAUDE.md' },
|
|
53
|
+
{ source: 'common/.claude', destination: '.claude' }
|
|
49
54
|
],
|
|
50
|
-
|
|
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
|